reformat code using `cargo fmt`

master
WangRunji 6 years ago
parent fe88f4f77f
commit b836b11792

@ -80,8 +80,16 @@ impl<T: BitAlloc> BitAllocCascade16<T> {
assert!(start <= end);
assert!(end <= Self::CAP);
for i in start / T::CAP..=(end - 1) / T::CAP {
let begin = if start / T::CAP == i { start % T::CAP } else { 0 };
let end = if end / T::CAP == i { end % T::CAP } else { T::CAP };
let begin = if start / T::CAP == i {
start % T::CAP
} else {
0
};
let end = if end / T::CAP == i {
end % T::CAP
} else {
T::CAP
};
f(&mut self.sub[i], begin..end);
self.bitset.set_bit(i, self.sub[i].any());
}

@ -24,7 +24,9 @@ impl Page {
** @retval Page the page of the given virtual address
*/
pub fn of_addr(addr: VirtAddr) -> Self {
Page { number: addr / PAGE_SIZE }
Page {
number: addr / PAGE_SIZE,
}
}
/*
@ -44,7 +46,9 @@ impl Page {
impl Add<usize> for Page {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
Page { number: self.number + rhs }
Page {
number: self.number + rhs,
}
}
}

@ -69,8 +69,7 @@ impl<T: PageTable> CowExt<T> {
** @retval none
*/
pub fn unmap_shared(&mut self, addr: VirtAddr) {
let entry = self.page_table.get_entry(addr)
.expect("entry not exist");
let entry = self.page_table.get_entry(addr).expect("entry not exist");
let frame = entry.target() / PAGE_SIZE;
if entry.readonly_shared() {
self.rc_map.read_decrease(&frame);
@ -89,7 +88,11 @@ impl<T: PageTable> CowExt<T> {
** of beginning of the page
** @retval bool whether copy-on-write happens.
*/
pub fn page_fault_handler(&mut self, addr: VirtAddr, alloc_frame: impl FnOnce() -> PhysAddr) -> bool {
pub fn page_fault_handler(
&mut self,
addr: VirtAddr,
alloc_frame: impl FnOnce() -> PhysAddr,
) -> bool {
let entry = self.page_table.get_entry(addr);
if entry.is_none() {
return false;
@ -113,7 +116,8 @@ impl<T: PageTable> CowExt<T> {
self.unmap_shared(addr);
self.map(addr, alloc_frame());
self.get_page_slice_mut(addr).copy_from_slice(&temp_data[..]);
self.get_page_slice_mut(addr)
.copy_from_slice(&temp_data[..]);
true
}
}
@ -222,7 +226,8 @@ pub mod test {
}
let mut alloc = FrameAlloc(4);
pt.page_table.set_handler(Box::new(move |_, addr: VirtAddr| {
pt.page_table
.set_handler(Box::new(move |_, addr: VirtAddr| {
pt0.page_fault_handler(addr, || alloc.alloc());
}));
@ -263,8 +268,11 @@ pub mod test {
pt.write(0x2000, 3);
assert_eq!(pt.rc_map.read_count(&frame), 0);
assert_eq!(pt.rc_map.write_count(&frame), 0);
assert_eq!(pt.get_entry(0x2000).unwrap().target(), target,
"The last write reference should not allocate new frame.");
assert_eq!(
pt.get_entry(0x2000).unwrap().target(),
target,
"The last write reference should not allocate new frame."
);
assert_eq!(pt.read(0x1000), 2);
assert_eq!(pt.read(0x2000), 3);
}

@ -6,17 +6,17 @@
use log::*;
extern crate alloc;
pub mod paging;
mod addr;
pub mod cow;
pub mod swap;
pub mod memory_set;
mod addr;
pub mod no_mmu;
pub mod paging;
pub mod swap;
pub use crate::addr::*;
pub enum VMError {
InvalidPtr
InvalidPtr,
}
pub type VMResult<T> = Result<T, VMError>;

@ -34,11 +34,11 @@ pub trait FrameAllocator: Debug + Clone + 'static {
fn dealloc(&self, target: PhysAddr);
}
mod linear;
mod byframe;
mod delay;
mod linear;
//mod swap;
pub use self::linear::Linear;
pub use self::byframe::ByFrame;
pub use self::delay::Delay;
pub use self::linear::Linear;

@ -1,7 +1,7 @@
//! memory set, area
//! and the inactive page table
use alloc::{boxed::Box, vec::Vec, string::String};
use alloc::{boxed::Box, string::String, vec::Vec};
use core::fmt::{Debug, Error, Formatter};
use crate::paging::*;
@ -31,14 +31,20 @@ impl MemoryArea {
** @retval &[u8] the slice of the content in the memory area
*/
pub unsafe fn as_slice(&self) -> &[u8] {
::core::slice::from_raw_parts(self.start_addr as *const u8, self.end_addr - self.start_addr)
::core::slice::from_raw_parts(
self.start_addr as *const u8,
self.end_addr - self.start_addr,
)
}
/*
** @brief get mutable slice of the content in the memory area
** @retval &mut[u8] the mutable slice of the content in the memory area
*/
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
::core::slice::from_raw_parts_mut(self.start_addr as *mut u8, self.end_addr - self.start_addr)
::core::slice::from_raw_parts_mut(
self.start_addr as *mut u8,
self.end_addr - self.start_addr,
)
}
/*
** @brief test whether a virtual address is in the memory area
@ -50,8 +56,7 @@ impl MemoryArea {
}
/// Check the array is within the readable memory
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool {
ptr as usize >= self.start_addr &&
unsafe { ptr.add(count) as usize } <= self.end_addr
ptr as usize >= self.start_addr && unsafe { ptr.add(count) as usize } <= self.end_addr
}
/// Check the array is within the writable memory
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
@ -206,24 +211,30 @@ impl<T: InactivePageTable> MemorySet<T> {
}
/// Check the array is within the readable memory
pub fn check_read_array<S>(&self, ptr: *const S, count: usize) -> VMResult<()> {
self.areas.iter()
self.areas
.iter()
.find(|area| area.check_read_array(ptr, count))
.map(|_|()).ok_or(VMError::InvalidPtr)
.map(|_| ())
.ok_or(VMError::InvalidPtr)
}
/// Check the array is within the writable memory
pub fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> VMResult<()> {
self.areas.iter()
self.areas
.iter()
.find(|area| area.check_write_array(ptr, count))
.map(|_|()).ok_or(VMError::InvalidPtr)
.map(|_| ())
.ok_or(VMError::InvalidPtr)
}
/// Check the null-end C string is within the readable memory, and is valid.
/// If so, clone it to a String.
///
/// Unsafe: the page table must be active.
pub unsafe fn check_and_clone_cstr(&self, ptr: *const u8) -> VMResult<String> {
self.areas.iter()
self.areas
.iter()
.filter_map(|area| area.check_and_clone_cstr(ptr))
.next().ok_or(VMError::InvalidPtr)
.next()
.ok_or(VMError::InvalidPtr)
}
/// Find a free area with hint address `addr_hint` and length `len`.
/// Return the start address of found free area.
@ -239,7 +250,8 @@ impl<T: InactivePageTable> MemorySet<T> {
}
/// Test if [`start_addr`, `end_addr`) is a free area
fn test_free_area(&self, start_addr: usize, end_addr: usize) -> bool {
self.areas.iter()
self.areas
.iter()
.find(|area| area.is_overlap_with(start_addr, end_addr))
.is_none()
}
@ -248,10 +260,26 @@ impl<T: InactivePageTable> MemorySet<T> {
** @param area: MemoryArea the memory area to add
** @retval none
*/
pub fn push(&mut self, start_addr: VirtAddr, end_addr: VirtAddr, attr: MemoryAttr, handler: impl MemoryHandler, name: &'static str) {
pub fn push(
&mut self,
start_addr: VirtAddr,
end_addr: VirtAddr,
attr: MemoryAttr,
handler: impl MemoryHandler,
name: &'static str,
) {
assert!(start_addr <= end_addr, "invalid memory area");
assert!(self.test_free_area(start_addr, end_addr), "memory area overlap");
let area = MemoryArea { start_addr, end_addr, attr, handler: Box::new(handler), name };
assert!(
self.test_free_area(start_addr, end_addr),
"memory area overlap"
);
let area = MemoryArea {
start_addr,
end_addr,
attr,
handler: Box::new(handler),
name,
};
self.page_table.edit(|pt| area.map(pt));
self.areas.push(area);
}
@ -288,28 +316,73 @@ impl<T: InactivePageTable> MemorySet<T> {
let area = self.areas.remove(i);
self.page_table.edit(|pt| area.unmap(pt));
i -= 1;
} else if self.areas[i].start_addr >= start_addr && self.areas[i].start_addr < end_addr {
} else if self.areas[i].start_addr >= start_addr
&& self.areas[i].start_addr < end_addr
{
// prefix
let area = self.areas.remove(i);
let dead_area = MemoryArea { start_addr: area.start_addr, end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
let dead_area = MemoryArea {
start_addr: area.start_addr,
end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
self.page_table.edit(|pt| dead_area.unmap(pt));
let new_area = MemoryArea { start_addr: end_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler, name: area.name };
let new_area = MemoryArea {
start_addr: end_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i, new_area);
} else if self.areas[i].end_addr <= end_addr && self.areas[i].end_addr > start_addr {
} else if self.areas[i].end_addr <= end_addr && self.areas[i].end_addr > start_addr
{
// postfix
let area = self.areas.remove(i);
let dead_area = MemoryArea { start_addr: start_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
let dead_area = MemoryArea {
start_addr: start_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
self.page_table.edit(|pt| dead_area.unmap(pt));
let new_area = MemoryArea { start_addr: area.start_addr, end_addr: start_addr, attr: area.attr, handler: area.handler, name: area.name };
let new_area = MemoryArea {
start_addr: area.start_addr,
end_addr: start_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i, new_area);
} else {
// superset
let area = self.areas.remove(i);
let dead_area = MemoryArea { start_addr: start_addr, end_addr: end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
let dead_area = MemoryArea {
start_addr: start_addr,
end_addr: end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
self.page_table.edit(|pt| dead_area.unmap(pt));
let new_area_left = MemoryArea { start_addr: area.start_addr, end_addr: start_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
let new_area_left = MemoryArea {
start_addr: area.start_addr,
end_addr: start_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
self.areas.insert(i, new_area_left);
let new_area_right = MemoryArea { start_addr: end_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler, name: area.name };
let new_area_right = MemoryArea {
start_addr: end_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i + 1, new_area_right);
i += 1;
}
@ -356,7 +429,11 @@ impl<T: InactivePageTable> MemorySet<T> {
** @retval none
*/
pub fn clear(&mut self) {
let Self { ref mut page_table, ref mut areas, .. } = self;
let Self {
ref mut page_table,
ref mut areas,
..
} = self;
page_table.edit(|pt| {
for area in areas.iter() {
area.unmap(pt);
@ -389,7 +466,9 @@ impl<T: InactivePageTable> MemorySet<T> {
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
let area = self.areas.iter().find(|area| area.contains(addr));
match area {
Some(area) => self.page_table.edit(|pt| area.handler.handle_page_fault(pt, addr)),
Some(area) => self
.page_table
.edit(|pt| area.handler.handle_page_fault(pt, addr)),
None => false,
}
}
@ -419,8 +498,6 @@ impl<T: InactivePageTable> Drop for MemorySet<T> {
impl<T: InactivePageTable> Debug for MemorySet<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.debug_list()
.entries(self.areas.iter())
.finish()
f.debug_list().entries(self.areas.iter()).finish()
}
}

@ -1,5 +1,5 @@
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::vec::Vec;
use alloc::alloc::{Layout, GlobalAlloc};
use core::marker::PhantomData;
pub trait NoMMUSupport {
@ -28,8 +28,12 @@ impl<S: NoMMUSupport> MemorySet<S> {
slice
}
// empty impls
pub fn with<T>(&self, f: impl FnOnce() -> T) -> T { f() }
pub fn token(&self) -> usize { 0 }
pub fn with<T>(&self, f: impl FnOnce() -> T) -> T {
f()
}
pub fn token(&self) -> usize {
0
}
pub unsafe fn activate(&self) {}
}
@ -44,7 +48,11 @@ impl<S: NoMMUSupport> MemoryArea<S> {
fn new(size: usize) -> Self {
let layout = Layout::from_size_align(size, 1).unwrap();
let ptr = unsafe { S::allocator().alloc(layout) } as usize;
MemoryArea { ptr, layout, support: PhantomData }
MemoryArea {
ptr,
layout,
support: PhantomData,
}
}
unsafe fn as_buf(&self) -> &'static mut [u8] {
core::slice::from_raw_parts_mut(self.ptr as *mut u8, self.layout.size())

@ -8,9 +8,14 @@ pub trait PageTableExt: PageTable {
// So this should be really high in kernel space when necessary.
const TEMP_PAGE_ADDR: VirtAddr = 0xcafeb000;
fn with_temporary_map<T, D>(&mut self, target: PhysAddr, f: impl FnOnce(&mut Self, &mut D) -> T) -> T {
fn with_temporary_map<T, D>(
&mut self,
target: PhysAddr,
f: impl FnOnce(&mut Self, &mut D) -> T,
) -> T {
self.map(Self::TEMP_PAGE_ADDR, target);
let data = unsafe { &mut *(self.get_page_slice_mut(Self::TEMP_PAGE_ADDR).as_ptr() as *mut D) };
let data =
unsafe { &mut *(self.get_page_slice_mut(Self::TEMP_PAGE_ADDR).as_ptr() as *mut D) };
let ret = f(self, data);
self.unmap(Self::TEMP_PAGE_ADDR);
ret

@ -3,8 +3,8 @@
//! An mock implementation for the PageTable.
//! Used to test page table operation.
use alloc::boxed::Box;
use super::*;
use alloc::boxed::Box;
const PAGE_COUNT: usize = 16;
const PAGE_SIZE: usize = 4096;
@ -31,18 +31,42 @@ pub struct MockEntry {
impl Entry for MockEntry {
fn update(&mut self) {}
fn accessed(&self) -> bool { self.accessed }
fn dirty(&self) -> bool { self.dirty }
fn writable(&self) -> bool { self.writable }
fn present(&self) -> bool { self.present }
fn clear_accessed(&mut self) { self.accessed = false; }
fn clear_dirty(&mut self) { self.dirty = false; }
fn set_writable(&mut self, value: bool) { self.writable = value; }
fn set_present(&mut self, value: bool) { self.present = value; }
fn target(&self) -> usize { self.target }
fn set_target(&mut self, target: usize) { self.target = target; }
fn writable_shared(&self) -> bool { self.writable_shared }
fn readonly_shared(&self) -> bool { self.readonly_shared }
fn accessed(&self) -> bool {
self.accessed
}
fn dirty(&self) -> bool {
self.dirty
}
fn writable(&self) -> bool {
self.writable
}
fn present(&self) -> bool {
self.present
}
fn clear_accessed(&mut self) {
self.accessed = false;
}
fn clear_dirty(&mut self) {
self.dirty = false;
}
fn set_writable(&mut self, value: bool) {
self.writable = value;
}
fn set_present(&mut self, value: bool) {
self.present = value;
}
fn target(&self) -> usize {
self.target
}
fn set_target(&mut self, target: usize) {
self.target = target;
}
fn writable_shared(&self) -> bool {
self.writable_shared
}
fn readonly_shared(&self) -> bool {
self.readonly_shared
}
fn set_shared(&mut self, writable: bool) {
self.writable_shared = writable;
self.readonly_shared = !writable;
@ -51,14 +75,30 @@ impl Entry for MockEntry {
self.writable_shared = false;
self.readonly_shared = false;
}
fn swapped(&self) -> bool { self.swapped }
fn set_swapped(&mut self, value: bool) { self.swapped = value; }
fn user(&self) -> bool { unimplemented!() }
fn set_user(&mut self, _value: bool) { unimplemented!() }
fn execute(&self) -> bool { unimplemented!() }
fn set_execute(&mut self, _value: bool) { unimplemented!() }
fn mmio(&self) -> u8 { unimplemented!() }
fn set_mmio(&mut self, _value: u8) { unimplemented!() }
fn swapped(&self) -> bool {
self.swapped
}
fn set_swapped(&mut self, value: bool) {
self.swapped = value;
}
fn user(&self) -> bool {
unimplemented!()
}
fn set_user(&mut self, _value: bool) {
unimplemented!()
}
fn execute(&self) -> bool {
unimplemented!()
}
fn set_execute(&mut self, _value: bool) {
unimplemented!()
}
fn mmio(&self) -> u8 {
unimplemented!()
}
fn set_mmio(&mut self, _value: u8) {
unimplemented!()
}
}
type PageFaultHandler = Box<FnMut(&mut MockPageTable, VirtAddr)>;

@ -2,15 +2,14 @@
//!
//! Implemented for every architecture, used by OS.
use super::*;
pub use self::ext::*;
#[cfg(test)]
pub use self::mock_page_table::MockPageTable;
pub use self::ext::*;
use super::*;
mod ext;
#[cfg(test)]
mod mock_page_table;
mod ext;
pub trait PageTable {
// type Entry: Entry;

@ -1,8 +1,7 @@
//! Implememnt the swap manager with the FIFO page replacement algorithm
use alloc::collections::VecDeque;
use super::*;
use alloc::collections::VecDeque;
#[derive(Default)]
pub struct FifoSwapManager {
@ -13,22 +12,29 @@ impl SwapManager for FifoSwapManager {
fn tick(&mut self) {}
fn push(&mut self, frame: Frame) {
info!("SwapManager push token: {:x?} vaddr: {:x?}", frame.get_token(), frame.get_virtaddr());
info!(
"SwapManager push token: {:x?} vaddr: {:x?}",
frame.get_token(),
frame.get_virtaddr()
);
self.deque.push_back(frame);
}
fn remove(&mut self, token: usize, addr: VirtAddr) {
info!("SwapManager remove token: {:x?} vaddr: {:x?}", token, addr);
let id = self.deque.iter()
let id = self
.deque
.iter()
.position(|ref x| x.get_virtaddr() == addr && x.get_token() == token)
.expect("address not found");
self.deque.remove(id);
//info!("SwapManager remove token finished: {:x?} vaddr: {:x?}", token, addr);
}
fn pop<T, S>(&mut self, _: &mut T, _: &mut S) -> Option<Frame>
where T: PageTable, S: Swapper
where
T: PageTable,
S: Swapper,
{
self.deque.pop_front()
}

@ -6,9 +6,9 @@
//! Invoke page_fault_handler() on the SwapExt to run the swap process
//! If the method above returns true, a page is swapped in, else do your own things.
use super::*;
use super::paging::*;
use super::addr::Frame;
use super::paging::*;
use super::*;
use core::ops::{Deref, DerefMut};
//pub use self::fifo::FifoSwapManager;
@ -52,7 +52,9 @@ pub trait SwapManager {
** @retval Option<Frame> the Frame of the victim page, if present
*/
fn pop<T, S>(&mut self, page_table: &mut T, swapper: &mut S) -> Option<Frame>
where T: PageTable, S: Swapper;
where
T: PageTable,
S: Swapper;
}
/// Implement swap in & out execution
@ -108,14 +110,24 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
** @param addr: VirtAddr the target page's virtual address
*/
pub unsafe fn set_swappable<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr) {
let Self {ref mut page_table, ref mut swap_manager, ..} = self;
let Self {
ref mut page_table,
ref mut swap_manager,
..
} = self;
let targetpt = &mut *(pt);
let pttoken = {
info!("SET_SWAPPABLE: the target page table token is {:x?}, addr is {:x?}", targetpt.token(), addr);
info!(
"SET_SWAPPABLE: the target page table token is {:x?}, addr is {:x?}",
targetpt.token(),
addr
);
targetpt.token()
};
targetpt.with(|| {
let entry = page_table.get_entry(addr).expect("failed to get page entry when set swappable");
let entry = page_table
.get_entry(addr)
.expect("failed to get page entry when set swappable");
if entry.present() {
let frame = Frame::new(pt as usize, addr, pttoken);
swap_manager.push(frame);
@ -136,12 +148,25 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
** @param addr: VirtAddr the target page's virtual address
** @param alloc_frame: the function to alloc a free physical frame for once
*/
pub unsafe fn remove_from_swappable<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr, alloc_frame: impl FnOnce() -> PhysAddr){
pub unsafe fn remove_from_swappable<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
alloc_frame: impl FnOnce() -> PhysAddr,
) {
//info!("come into remove_from swappable");
let Self {ref mut page_table, ref mut swap_manager, ref mut swapper} = self;
let Self {
ref mut page_table,
ref mut swap_manager,
ref mut swapper,
} = self;
let targetpt = &mut *(pt);
let pttoken = {
info!("SET_UNSWAPPABLE: the target page table token is {:x?}, addr is {:x?}", targetpt.token(), addr);
info!(
"SET_UNSWAPPABLE: the target page table token is {:x?}, addr is {:x?}",
targetpt.token(),
addr
);
targetpt.token()
};
//info!("try to change pagetable");
@ -191,7 +216,11 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
pub fn swap_out_any<T2: InactivePageTable>(&mut self) -> Result<PhysAddr, SwapError> {
info!("COME in to swap_out_any");
let victim: Option<Frame> = {
let Self {ref mut page_table, ref mut swap_manager, ref mut swapper} = self;
let Self {
ref mut page_table,
ref mut swap_manager,
ref mut swapper,
} = self;
swap_manager.pop(page_table, swapper)
};
info!("swap out page {}", victim.unwrap().get_virtaddr());
@ -209,14 +238,19 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
** the error if failed
*/
fn swap_out<T2: InactivePageTable>(&mut self, frame: &Frame) -> Result<PhysAddr, SwapError> {
let Self {ref mut page_table, ref mut swapper, ..} = self;
let Self {
ref mut page_table,
ref mut swapper,
..
} = self;
let ret = unsafe {
let pt = &mut *(frame.get_page_table() as *mut T2);
pt.with(|| {
//use core::slice;
//let data = unsafe { slice::from_raw_parts_mut((frame.virtaddr & !(PAGE_SIZE - 1)) as *mut u8, PAGE_SIZE) };
let data = page_table.get_page_slice_mut(frame.get_virtaddr());
let entry = page_table.get_entry(frame.get_virtaddr())
let entry = page_table
.get_entry(frame.get_virtaddr())
.ok_or(SwapError::NotMapped)?;
if entry.swapped() {
return Err(SwapError::AlreadySwapped);
@ -242,9 +276,16 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
** @retval Result<()), SwapError>
** the execute result, and the error if failed
*/
fn swap_in<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr, target: PhysAddr) -> Result<(), SwapError> {
fn swap_in<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
target: PhysAddr,
) -> Result<(), SwapError> {
info!("come in to swap in");
let entry = self.page_table.get_entry(addr)
let entry = self
.page_table
.get_entry(addr)
.ok_or(SwapError::NotMapped)?;
if !entry.swapped() {
return Err(SwapError::NotSwapped);
@ -255,10 +296,10 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
entry.set_present(true);
entry.update();
let data = self.page_table.get_page_slice_mut(addr);
self.swapper.swap_in(token, data).map_err(|_| SwapError::IOError)?;
let pttoken = unsafe{
(*pt).token()
};
self.swapper
.swap_in(token, data)
.map_err(|_| SwapError::IOError)?;
let pttoken = unsafe { (*pt).token() };
let frame = Frame::new(pt as usize, addr, pttoken);
;
self.swap_manager.push(frame);
@ -276,7 +317,13 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
** of beginning of the page
** @retval bool whether swap in happens.
*/
pub fn page_fault_handler<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr, swapin: bool, alloc_frame: impl FnOnce() -> PhysAddr) -> bool {
pub fn page_fault_handler<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
swapin: bool,
alloc_frame: impl FnOnce() -> PhysAddr,
) -> bool {
// handle page delayed allocating
{
info!("try handling delayed frame allocator");
@ -311,7 +358,11 @@ impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
match self.page_table.get_entry(addr) {
// infact the get_entry(addr) should not be None here
None => return false,
Some(entry) => if !entry.swapped() { return false; },
Some(entry) => {
if !entry.swapped() {
return false;
}
}
}
// Allocate a frame, if failed, swap out a page
let frame = alloc_frame();

@ -1,7 +1,7 @@
//! entrance to test the communication in processes with solving five philosophers problem
mod mutex;
mod monitor;
mod mutex;
fn main() {
// mutex::main();

@ -1,7 +1,7 @@
//! solve the five philosophers problem with monitor
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
use std::sync::{Mutex, Condvar, Arc};
use std::time::Duration;
struct Philosopher {
@ -57,7 +57,13 @@ struct Table {
pub fn main() {
let table = Arc::new(Table {
fork_status: Mutex::new(vec![false; 5]),
fork_condvar: vec![Condvar::new(), Condvar::new(), Condvar::new(), Condvar::new(), Condvar::new()],
fork_condvar: vec![
Condvar::new(),
Condvar::new(),
Condvar::new(),
Condvar::new(),
Condvar::new(),
],
});
let philosophers = vec![
@ -68,7 +74,9 @@ pub fn main() {
Philosopher::new("5", 0, 4),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let handles: Vec<_> = philosophers
.into_iter()
.map(|p| {
let table = table.clone();
thread::spawn(move || {
@ -77,7 +85,8 @@ pub fn main() {
p.eat(&table);
}
})
}).collect();
})
.collect();
for h in handles {
h.join().unwrap();

@ -1,7 +1,7 @@
//! solve the five philosophers problem with mutex
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::{Mutex, Arc};
use std::time::Duration;
struct Philosopher {
@ -46,7 +46,7 @@ pub fn main() {
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
]
],
});
let philosophers = vec![
@ -57,7 +57,9 @@ pub fn main() {
Philosopher::new("5", 0, 4),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let handles: Vec<_> = philosophers
.into_iter()
.map(|p| {
let table = table.clone();
thread::spawn(move || {
@ -66,7 +68,8 @@ pub fn main() {
p.eat(&table);
}
})
}).collect();
})
.collect();
for h in handles {
h.join().unwrap();

@ -1,2 +1 @@
fn main() {
}
fn main() {}

@ -8,12 +8,12 @@
extern crate alloc;
mod thread_pool;
mod interrupt;
mod processor;
pub mod scheduler;
pub mod std_thread;
mod thread_pool;
mod timer;
mod interrupt;
pub use crate::thread_pool::*;
pub use crate::processor::Processor;
pub use crate::thread_pool::*;

@ -1,9 +1,9 @@
use crate::interrupt;
use crate::thread_pool::*;
use alloc::boxed::Box;
use alloc::sync::Arc;
use log::*;
use core::cell::UnsafeCell;
use crate::thread_pool::*;
use crate::interrupt;
use log::*;
/// Thread executor
///
@ -25,7 +25,9 @@ struct ProcessorInner {
impl Processor {
pub const fn new() -> Self {
Processor { inner: UnsafeCell::new(None) }
Processor {
inner: UnsafeCell::new(None),
}
}
pub unsafe fn init(&self, id: usize, context: Box<Context>, manager: Arc<ThreadPool>) {
@ -38,7 +40,8 @@ impl Processor {
}
fn inner(&self) -> &mut ProcessorInner {
unsafe { &mut *self.inner.get() }.as_mut()
unsafe { &mut *self.inner.get() }
.as_mut()
.expect("Processor is not initialized")
}
@ -51,22 +54,30 @@ impl Processor {
/// via switch back to the scheduler.
pub fn run(&self) -> ! {
let inner = self.inner();
unsafe { interrupt::disable_and_store(); }
unsafe {
interrupt::disable_and_store();
}
loop {
if let Some(proc) = inner.manager.run(inner.id) {
trace!("CPU{} begin running thread {}", inner.id, proc.0);
inner.proc = Some(proc);
unsafe {
inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1);
inner
.loop_context
.switch_to(&mut *inner.proc.as_mut().unwrap().1);
}
let (tid, context) = inner.proc.take().unwrap();
trace!("CPU{} stop running thread {}", inner.id, tid);
inner.manager.stop(tid, context);
} else {
trace!("CPU{} idle", inner.id);
unsafe { interrupt::enable_and_wfi(); }
unsafe {
interrupt::enable_and_wfi();
}
// wait for a timer interrupt
unsafe { interrupt::disable_and_store(); }
unsafe {
interrupt::disable_and_store();
}
}
}
}
@ -79,7 +90,12 @@ impl Processor {
let inner = self.inner();
unsafe {
let flags = interrupt::disable_and_store();
inner.proc.as_mut().unwrap().1.switch_to(&mut *inner.loop_context);
inner
.proc
.as_mut()
.unwrap()
.1
.switch_to(&mut *inner.loop_context);
interrupt::restore(flags);
}
}

@ -36,7 +36,9 @@ impl RRScheduler {
max_time_slice,
infos: Vec::default(),
};
RRScheduler { inner: Mutex::new(inner) }
RRScheduler {
inner: Mutex::new(inner),
}
}
}
@ -63,7 +65,7 @@ impl RRSchedulerInner {
self.infos[tid].present = false;
self._list_remove(tid);
Some(tid - 1)
},
}
};
trace!("rr pop {:?}", ret);
ret

@ -62,7 +62,9 @@ impl StrideScheduler {
infos: Vec::default(),
queue: BinaryHeap::default(),
};
StrideScheduler { inner: Mutex::new(inner) }
StrideScheduler {
inner: Mutex::new(inner),
}
}
}

@ -6,12 +6,12 @@
//! - `processor`: Get a reference of the current `Processor`
//! - `new_kernel_context`: Construct a `Context` of the new kernel thread
use crate::processor::*;
use crate::thread_pool::*;
use alloc::boxed::Box;
use core::marker::PhantomData;
use core::time::Duration;
use log::*;
use crate::processor::*;
use crate::thread_pool::*;
#[linkage = "weak"]
#[no_mangle]
@ -23,14 +23,15 @@ fn processor() -> &'static Processor {
#[linkage = "weak"]
#[no_mangle]
/// Construct a `Context` of the new kernel thread
fn new_kernel_context(_entry: extern fn(usize) -> !, _arg: usize) -> Box<Context> {
fn new_kernel_context(_entry: extern "C" fn(usize) -> !, _arg: usize) -> Box<Context> {
unimplemented!("thread: Please implement and export `new_kernel_context`")
}
/// Gets a handle to the thread that invokes it.
pub fn current() -> Thread {
Thread { tid: processor().tid() }
Thread {
tid: processor().tid(),
}
}
/// Puts the current thread to sleep for the specified amount of time.
@ -69,7 +70,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
//
// 注意到它具有泛型参数因此对每一次spawn调用
// 由于F类型是独特的因此都会生成一个新的kernel_thread_entry
extern fn kernel_thread_entry<F, T>(f: usize) -> !
extern "C" fn kernel_thread_entry<F, T>(f: usize) -> !
where
F: Send + 'static + FnOnce() -> T,
T: Send + 'static,

@ -1,9 +1,9 @@
use crate::scheduler::Scheduler;
use crate::timer::Timer;
use alloc::boxed::Box;
use alloc::vec::Vec;
use spin::{Mutex, MutexGuard};
use log::*;
use crate::scheduler::Scheduler;
use crate::timer::Timer;
use spin::{Mutex, MutexGuard};
struct Thread {
status: Status,
@ -105,8 +105,7 @@ impl ThreadPool {
/// The manager first mark it `Running`,
/// then take out and return its Context.
pub(crate) fn run(&self, cpu_id: usize) -> Option<(Tid, Box<Context>)> {
self.scheduler.pop(cpu_id)
.map(|tid| {
self.scheduler.pop(cpu_id).map(|tid| {
let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("thread not exist");
proc.status = Status::Running(cpu_id);
@ -175,7 +174,7 @@ impl ThreadPool {
// release the tid
*proc_lock = None;
Some(code)
},
}
_ => None,
}
}

@ -14,12 +14,9 @@ fn main() {
"x86_64" => {
gen_vector_asm().unwrap();
}
"riscv32" => {
}
"riscv64" => {
}
"aarch64" => {
}
"riscv32" => {}
"riscv64" => {}
"aarch64" => {}
_ => panic!("Unknown arch {}", arch),
}
}

@ -57,16 +57,10 @@ impl ColorBuffer {
unsafe {
match color_depth {
ColorDepth16 => ColorBuffer {
buf16: core::slice::from_raw_parts_mut(
base_addr as *mut u16,
size / 2,
),
buf16: core::slice::from_raw_parts_mut(base_addr as *mut u16, size / 2),
},
ColorDepth32 => ColorBuffer {
buf32: core::slice::from_raw_parts_mut(
base_addr as *mut u32,
size / 4,
),
buf32: core::slice::from_raw_parts_mut(base_addr as *mut u32, size / 4),
},
}
}

@ -3,12 +3,12 @@
//! (ref: https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface)
use super::fb::FramebufferInfo;
use bcm2837::mailbox::{Mailbox, MailboxChannel};
use lazy_static::lazy_static;
use aarch64::asm;
use alloc::string::String;
use bcm2837::mailbox::{Mailbox, MailboxChannel};
use core::mem;
use lazy_static::lazy_static;
use spin::Mutex;
use aarch64::asm;
lazy_static! {
static ref MAILBOX: Mutex<Mailbox> = Mutex::new(Mailbox::new());
@ -268,7 +268,10 @@ pub fn framebuffer_get_depth() -> PropertyMailboxResult<u32> {
/// Set virtual offset. Returns `(X, Y)` in pixel.
/// The response may not be the same as the request so it must be checked.
/// May be the previous offset or 0 for unsupported.
pub fn framebuffer_set_virtual_offset(xoffset: u32, yoffset: u32) -> PropertyMailboxResult<(u32, u32)> {
pub fn framebuffer_set_virtual_offset(
xoffset: u32,
yoffset: u32,
) -> PropertyMailboxResult<(u32, u32)> {
let ret = send_one_tag!(
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET,
[xoffset, yoffset]
@ -278,7 +281,11 @@ pub fn framebuffer_set_virtual_offset(xoffset: u32, yoffset: u32) -> PropertyMai
/// Allocate framebuffer on GPU and try to set width/height/depth.
/// Returns `FramebufferInfo`.
pub fn framebuffer_alloc(width: u32, height: u32, depth: u32) -> PropertyMailboxResult<FramebufferInfo> {
pub fn framebuffer_alloc(
width: u32,
height: u32,
depth: u32,
) -> PropertyMailboxResult<FramebufferInfo> {
#[repr(C, packed)]
#[derive(Debug)]
struct FramebufferAllocTag {

@ -1,13 +1,13 @@
//! Raspberry PI 3 Model B/B+
use once::*;
use bcm2837::atags::Atags;
use once::*;
pub mod fb;
pub mod irq;
pub mod timer;
pub mod serial;
pub mod mailbox;
pub mod serial;
pub mod timer;
pub const IO_REMAP_BASE: usize = bcm2837::consts::IO_BASE;
pub const IO_REMAP_END: usize = bcm2837::consts::KERNEL_OFFSET + 0x4000_1000;

@ -1,8 +1,8 @@
use bcm2837::mini_uart::{MiniUart, MiniUartInterruptId};
use lazy_static::lazy_static;
use core::fmt;
use spin::Mutex;
use lazy_static::lazy_static;
use once::*;
use spin::Mutex;
/// Struct to get a global SerialPort interface
pub struct SerialPort {

File diff suppressed because it is too large Load Diff

@ -10,7 +10,7 @@ use spin::Mutex;
use crate::util::escape_parser::{CharacterAttribute, EscapeParser};
use super::fb::{ColorDepth::*, FRAME_BUFFER, FramebufferInfo};
use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER};
use self::color::FramebufferColor;
use self::fonts::{Font, Font8x16};
@ -67,10 +67,7 @@ impl<F: Font> ConsoleBuffer<F> {
ch.attr.foreground.pack16() as u32,
ch.attr.background.pack16() as u32,
),
ColorDepth32 => (
ch.attr.foreground.pack32(),
ch.attr.background.pack32(),
),
ColorDepth32 => (ch.attr.foreground.pack32(), ch.attr.background.pack32()),
};
if ch.attr.reverse {
core::mem::swap(&mut foreground, &mut background);
@ -87,7 +84,10 @@ impl<F: Font> ConsoleBuffer<F> {
};
for y in 0..F::HEIGHT {
for x in 0..F::WIDTH {
let pixel = if y == underline_y || y == strikethrough_y || F::get(ch.ascii_char, x, y) {
let pixel = if y == underline_y
|| y == strikethrough_y
|| F::get(ch.ascii_char, x, y)
{
foreground
} else {
background

@ -1,11 +1,11 @@
//! TrapFrame and context definitions for aarch64.
use spin::Mutex;
use lazy_static::lazy_static;
use aarch64::barrier;
use aarch64::addr::PhysAddr;
use aarch64::paging::PhysFrame;
use aarch64::asm::{tlb_invalidate_all, ttbr_el1_read, ttbr_el1_write_asid};
use aarch64::barrier;
use aarch64::paging::PhysFrame;
use lazy_static::lazy_static;
use spin::Mutex;
#[repr(C)]
#[derive(Default, Debug, Copy, Clone)]
@ -23,7 +23,7 @@ pub struct TrapFrame {
/// 用于在内核栈中构造新线程的中断帧
impl TrapFrame {
fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self {
fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x0 = arg;
@ -65,7 +65,7 @@ impl InitStack {
}
}
extern {
extern "C" {
fn __trapret();
}
@ -78,7 +78,10 @@ struct ContextData {
impl ContextData {
fn new() -> Self {
ContextData { lr: __trapret as usize, ..ContextData::default() }
ContextData {
lr: __trapret as usize,
..ContextData::default()
}
}
}
@ -99,7 +102,7 @@ impl Context {
/// Pop all callee-saved registers, then return to the target.
#[naked]
#[inline(never)]
unsafe extern fn __switch(_self_stack: &mut usize, _target_stack: &mut usize) {
unsafe extern "C" fn __switch(_self_stack: &mut usize, _target_stack: &mut usize) {
asm!(
"
mov x10, #-(12 * 8)
@ -144,17 +147,30 @@ impl Context {
}
}
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, ttbr: usize) -> Self {
pub unsafe fn new_kernel_thread(
entry: extern "C" fn(usize) -> !,
arg: usize,
kstack_top: usize,
ttbr: usize,
) -> Self {
InitStack {
context: ContextData::new(),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top, ttbr)
}
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, ttbr: usize) -> Self {
.push_at(kstack_top, ttbr)
}
pub unsafe fn new_user_thread(
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
_is32: bool,
ttbr: usize,
) -> Self {
InitStack {
context: ContextData::new(),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}.push_at(kstack_top, ttbr)
}
.push_at(kstack_top, ttbr)
}
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, ttbr: usize) -> Self {
InitStack {
@ -164,9 +180,16 @@ impl Context {
tf.x0 = 0;
tf
},
}.push_at(kstack_top, ttbr)
}
pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, ttbr: usize, tls: usize) -> Self {
.push_at(kstack_top, ttbr)
}
pub unsafe fn new_clone(
tf: &TrapFrame,
ustack_top: usize,
kstack_top: usize,
ttbr: usize,
tls: usize,
) -> Self {
InitStack {
context: ContextData::new(),
tf: {
@ -176,14 +199,14 @@ impl Context {
tf.x0 = 0;
tf
},
}.push_at(kstack_top, ttbr)
}
.push_at(kstack_top, ttbr)
}
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.stack_top as *const InitStack)).tf.clone()
}
}
const ASID_MASK: u16 = 0xffff;
@ -199,7 +222,10 @@ struct AsidAllocator(Asid);
impl AsidAllocator {
fn new() -> Self {
AsidAllocator(Asid { value: 0, generation: 1 })
AsidAllocator(Asid {
value: 0,
generation: 1,
})
}
fn alloc(&mut self, old_asid: Asid) -> Asid {

@ -1,8 +1,8 @@
//! Trap handler
use crate::arch::board::irq::handle_irq;
use super::context::TrapFrame;
use super::syndrome::{Fault, Syndrome};
use crate::arch::board::irq::handle_irq;
use aarch64::regs::*;
use log::*;

@ -1,7 +1,7 @@
//! Interrupt and exception for aarch64.
mod handler;
mod context;
mod handler;
mod syndrome;
use aarch64::regs::*;

@ -1,7 +1,7 @@
//! Input/output for aarch64.
use super::driver::serial::*;
use super::driver::console::CONSOLE;
use super::driver::serial::*;
use core::fmt::{Arguments, Write};
pub fn getchar() -> char {

@ -1,8 +1,8 @@
//! Memory initialization for aarch64.
use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR};
use crate::consts::{MEMORY_OFFSET, KERNEL_OFFSET};
use super::paging::MMIOType;
use crate::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR};
use aarch64::regs::*;
use log::*;
use rcore_memory::PAGE_SIZE;
@ -19,7 +19,9 @@ fn init_frame_allocator() {
use bit_allocator::BitAlloc;
use core::ops::Range;
let end = super::board::probe_memory().expect("failed to find memory map").1;
let end = super::board::probe_memory()
.expect("failed to find memory map")
.1;
let start = (_end as u64 + PAGE_SIZE as u64).wrapping_sub(KERNEL_OFFSET as u64) as usize;
let mut ba = FRAME_ALLOCATOR.lock();
ba.insert(to_range(start, end));
@ -39,14 +41,50 @@ static mut KERNEL_MEMORY_SET: Option<MemorySet> = None;
fn remap_the_kernel() {
let offset = -(KERNEL_OFFSET as isize);
let mut ms = MemorySet::new_bare();
ms.push(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), Linear::new(offset), "text");
ms.push(sdata as usize, edata as usize, MemoryAttr::default(), Linear::new(offset), "data");
ms.push(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), Linear::new(offset), "rodata");
ms.push(sbss as usize, ebss as usize, MemoryAttr::default(), Linear::new(offset), "bss");
ms.push(bootstack as usize, bootstacktop as usize, MemoryAttr::default(), Linear::new(offset), "kstack");
ms.push(
stext as usize,
etext as usize,
MemoryAttr::default().execute().readonly(),
Linear::new(offset),
"text",
);
ms.push(
sdata as usize,
edata as usize,
MemoryAttr::default(),
Linear::new(offset),
"data",
);
ms.push(
srodata as usize,
erodata as usize,
MemoryAttr::default().readonly(),
Linear::new(offset),
"rodata",
);
ms.push(
sbss as usize,
ebss as usize,
MemoryAttr::default(),
Linear::new(offset),
"bss",
);
ms.push(
bootstack as usize,
bootstacktop as usize,
MemoryAttr::default(),
Linear::new(offset),
"kstack",
);
use super::board::{IO_REMAP_BASE, IO_REMAP_END};
ms.push(IO_REMAP_BASE, IO_REMAP_END, MemoryAttr::default().mmio(MMIOType::Device as u8), Linear::new(offset), "io_remap");
ms.push(
IO_REMAP_BASE,
IO_REMAP_END,
MemoryAttr::default().mmio(MMIOType::Device as u8),
Linear::new(offset),
"io_remap",
);
info!("{:#x?}", ms);
unsafe { ms.get_page_table_mut().activate_as_kernel() }
@ -58,7 +96,13 @@ pub fn ioremap(paddr: usize, len: usize, name: &'static str) -> usize {
let offset = -(KERNEL_OFFSET as isize);
let vaddr = paddr.wrapping_add(KERNEL_OFFSET);
if let Some(ms) = unsafe { KERNEL_MEMORY_SET.as_mut() } {
ms.push(vaddr, vaddr + len, MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8), Linear::new(offset), name);
ms.push(
vaddr,
vaddr + len,
MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8),
Linear::new(offset),
name,
);
return vaddr;
}
0

@ -1,15 +1,15 @@
//! Entrance and initialization for aarch64.
pub mod io;
pub mod paging;
pub mod memory;
pub mod interrupt;
pub mod consts;
pub mod cpu;
pub mod driver;
pub mod timer;
pub mod syscall;
pub mod interrupt;
pub mod io;
pub mod memory;
pub mod paging;
pub mod rand;
pub mod syscall;
pub mod timer;
#[cfg(feature = "board_raspi3")]
#[path = "board/raspi3/mod.rs"]

@ -1,11 +1,13 @@
//! Page table implementations for aarch64.
use rcore_memory::paging::*;
use aarch64::asm::{tlb_invalidate, tlb_invalidate_all, ttbr_el1_read, ttbr_el1_write};
use aarch64::{PhysAddr, VirtAddr};
use aarch64::paging::{Mapper, PageTable as Aarch64PageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable};
use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame, Size4KiB};
use aarch64::paging::memory_attribute::*;
use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame, Size4KiB};
use aarch64::paging::{
Mapper, PageTable as Aarch64PageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable,
};
use aarch64::{PhysAddr, VirtAddr};
use log::*;
use rcore_memory::paging::*;
// Depends on kernel
use crate::consts::{KERNEL_OFFSET, KERNEL_PML4, RECURSIVE_INDEX};
use crate::memory::{active_table, alloc_frame, dealloc_frame};
@ -18,8 +20,16 @@ impl PageTable for ActivePageTable {
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
let flags = EF::default();
let attr = MairNormal::attr_value();
self.0.map_to(Page::of_addr(addr as u64), Frame::of_addr(target as u64), flags, attr, &mut FrameAllocatorForAarch64)
.unwrap().flush();
self.0
.map_to(
Page::of_addr(addr as u64),
Frame::of_addr(target as u64),
flags,
attr,
&mut FrameAllocatorForAarch64,
)
.unwrap()
.flush();
self.get_entry(addr).expect("fail to get entry")
}
@ -30,7 +40,8 @@ impl PageTable for ActivePageTable {
fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> {
// get p1 entry
let entry_addr = ((vaddr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39) | (vaddr & KERNEL_OFFSET);
let entry_addr =
((vaddr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39) | (vaddr & KERNEL_OFFSET);
Some(unsafe { &mut *(entry_addr as *mut PageEntry) })
}
}
@ -39,12 +50,12 @@ impl PageTableExt for ActivePageTable {
const TEMP_PAGE_ADDR: usize = KERNEL_OFFSET | 0xcafeb000;
}
const ROOT_PAGE_TABLE: *mut Aarch64PageTable =
(KERNEL_OFFSET |
(RECURSIVE_INDEX << 39) |
(RECURSIVE_INDEX << 30) |
(RECURSIVE_INDEX << 21) |
(RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable;
const ROOT_PAGE_TABLE: *mut Aarch64PageTable = (KERNEL_OFFSET
| (RECURSIVE_INDEX << 39)
| (RECURSIVE_INDEX << 30)
| (RECURSIVE_INDEX << 21)
| (RECURSIVE_INDEX << 12))
as *mut Aarch64PageTable;
impl ActivePageTable {
pub unsafe fn new() -> Self {
@ -66,38 +77,63 @@ impl Entry for PageEntry {
tlb_invalidate(addr);
}
fn present(&self) -> bool { self.0.flags().contains(EF::VALID) }
fn accessed(&self) -> bool { self.0.flags().contains(EF::AF) }
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITE) }
fn dirty(&self) -> bool { self.hw_dirty() && self.sw_dirty() }
fn present(&self) -> bool {
self.0.flags().contains(EF::VALID)
}
fn accessed(&self) -> bool {
self.0.flags().contains(EF::AF)
}
fn writable(&self) -> bool {
self.0.flags().contains(EF::WRITE)
}
fn dirty(&self) -> bool {
self.hw_dirty() && self.sw_dirty()
}
fn clear_accessed(&mut self) { self.as_flags().remove(EF::AF); }
fn clear_dirty(&mut self)
{
fn clear_accessed(&mut self) {
self.as_flags().remove(EF::AF);
}
fn clear_dirty(&mut self) {
self.as_flags().remove(EF::DIRTY);
self.as_flags().insert(EF::AP_RO);
}
fn set_writable(&mut self, value: bool)
{
fn set_writable(&mut self, value: bool) {
self.as_flags().set(EF::AP_RO, !value);
self.as_flags().set(EF::WRITE, value);
}
fn set_present(&mut self, value: bool) { self.as_flags().set(EF::VALID, value); }
fn target(&self) -> usize { self.0.addr().as_u64() as usize }
fn set_present(&mut self, value: bool) {
self.as_flags().set(EF::VALID, value);
}
fn target(&self) -> usize {
self.0.addr().as_u64() as usize
}
fn set_target(&mut self, target: usize) {
self.0.modify_addr(PhysAddr::new(target as u64));
}
fn writable_shared(&self) -> bool { self.0.flags().contains(EF::WRITABLE_SHARED) }
fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::READONLY_SHARED) }
fn writable_shared(&self) -> bool {
self.0.flags().contains(EF::WRITABLE_SHARED)
}
fn readonly_shared(&self) -> bool {
self.0.flags().contains(EF::READONLY_SHARED)
}
fn set_shared(&mut self, writable: bool) {
let flags = self.as_flags();
flags.set(EF::WRITABLE_SHARED, writable);
flags.set(EF::READONLY_SHARED, !writable);
}
fn clear_shared(&mut self) { self.as_flags().remove(EF::WRITABLE_SHARED | EF::READONLY_SHARED); }
fn user(&self) -> bool { self.0.flags().contains(EF::AP_EL0) }
fn swapped(&self) -> bool { self.0.flags().contains(EF::SWAPPED) }
fn set_swapped(&mut self, value: bool) { self.as_flags().set(EF::SWAPPED, value); }
fn clear_shared(&mut self) {
self.as_flags()
.remove(EF::WRITABLE_SHARED | EF::READONLY_SHARED);
}
fn user(&self) -> bool {
self.0.flags().contains(EF::AP_EL0)
}
fn swapped(&self) -> bool {
self.0.flags().contains(EF::SWAPPED)
}
fn set_swapped(&mut self, value: bool) {
self.as_flags().set(EF::SWAPPED, value);
}
fn set_user(&mut self, value: bool) {
self.as_flags().set(EF::AP_EL0, value);
self.as_flags().set(EF::nG, value); // set non-global to use ASID
@ -140,9 +176,15 @@ impl Entry for PageEntry {
}
impl PageEntry {
fn read_only(&self) -> bool { self.0.flags().contains(EF::AP_RO) }
fn hw_dirty(&self) -> bool { self.writable() && !self.read_only() }
fn sw_dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
fn read_only(&self) -> bool {
self.0.flags().contains(EF::AP_RO)
}
fn hw_dirty(&self) -> bool {
self.writable() && !self.read_only()
}
fn sw_dirty(&self) -> bool {
self.0.flags().contains(EF::DIRTY)
}
fn as_flags(&mut self) -> &mut EF {
unsafe { &mut *(self as *mut _ as *mut EF) }
}
@ -168,7 +210,11 @@ impl InactivePageTable for InactivePageTable0 {
active_table().with_temporary_map(target, |_, table: &mut Aarch64PageTable| {
table.zero();
// set up recursive mapping for the table
table[RECURSIVE_INDEX].set_frame(frame.clone(), EF::default(), MairNormal::attr_value());
table[RECURSIVE_INDEX].set_frame(
frame.clone(),
EF::default(),
MairNormal::attr_value(),
);
});
InactivePageTable0 { p4_frame: frame }
}
@ -179,7 +225,11 @@ impl InactivePageTable for InactivePageTable0 {
assert!(!e0.is_unused());
self.edit(|_| {
table[KERNEL_PML4].set_frame(Frame::containing_address(e0.addr()), EF::default(), MairNormal::attr_value());
table[KERNEL_PML4].set_frame(
Frame::containing_address(e0.addr()),
EF::default(),
MairNormal::attr_value(),
);
});
}
@ -201,12 +251,18 @@ impl InactivePageTable for InactivePageTable0 {
fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T {
let target = ttbr_el1_read(1).start_address().as_u64() as usize;
active_table().with_temporary_map(target, |active_table, p4_table: &mut Aarch64PageTable| {
active_table().with_temporary_map(
target,
|active_table, p4_table: &mut Aarch64PageTable| {
let backup = p4_table[RECURSIVE_INDEX].clone();
let old_frame = ttbr_el1_read(0);
// overwrite recursive mapping
p4_table[RECURSIVE_INDEX].set_frame(self.p4_frame.clone(), EF::default(), MairNormal::attr_value());
p4_table[RECURSIVE_INDEX].set_frame(
self.p4_frame.clone(),
EF::default(),
MairNormal::attr_value(),
);
ttbr_el1_write(0, self.p4_frame.clone());
tlb_invalidate_all();
@ -218,7 +274,8 @@ impl InactivePageTable for InactivePageTable0 {
ttbr_el1_write(0, old_frame);
tlb_invalidate_all();
ret
})
},
)
}
}

@ -10,7 +10,8 @@ pub unsafe fn init_external_interrupt() {
/// Claim and complete external interrupt by reading and writing to
/// PLIC Interrupt Claim/Complete Register.
pub unsafe fn handle_external_interrupt() {
const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = (KERNEL_OFFSET + 0x0C20_2004) as *mut u32;
const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 =
(KERNEL_OFFSET + 0x0C20_2004) as *mut u32;
// claim
let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read();
// complete

@ -3,6 +3,6 @@
//! [atomic](http://llvm.org/docs/Atomics.html#libcalls-atomic)
#[no_mangle]
pub extern fn abort() {
pub extern "C" fn abort() {
panic!("abort");
}

@ -1,8 +1,4 @@
use riscv::register::{
sstatus,
sstatus::Sstatus,
scause::Scause,
};
use riscv::register::{scause::Scause, sstatus, sstatus::Sstatus};
/// Saved registers on a trap.
#[derive(Clone)]
@ -27,7 +23,7 @@ impl TrapFrame {
///
/// The new thread starts at function `entry` with an usize argument `arg`.
/// The stack pointer will be set to `sp`.
fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, sp: usize) -> Self {
fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x[10] = arg; // a0
@ -57,17 +53,17 @@ impl TrapFrame {
}
}
use core::fmt::{Debug, Formatter, Error};
use core::fmt::{Debug, Error, Formatter};
impl Debug for TrapFrame {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
struct Regs<'a>(&'a [usize; 32]);
impl<'a> Debug for Regs<'a> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
const REG_NAME: [&str; 32] = [
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
"t3", "t4", "t5", "t6"];
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2",
"a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
"s10", "s11", "t3", "t4", "t5", "t6",
];
f.debug_map().entries(REG_NAME.iter().zip(self.0)).finish()
}
}
@ -98,7 +94,7 @@ impl InitStack {
}
}
extern {
extern "C" {
fn trap_return();
}
@ -116,7 +112,11 @@ struct ContextData {
impl ContextData {
fn new(satp: usize) -> Self {
ContextData { ra: trap_return as usize, satp, ..ContextData::default() }
ContextData {
ra: trap_return as usize,
satp,
..ContextData::default()
}
}
}
@ -137,25 +137,29 @@ impl Context {
/// Pop all callee-saved registers, then return to the target.
#[naked]
#[inline(never)]
pub unsafe extern fn switch(&mut self, _target: &mut Self) {
pub unsafe extern "C" fn switch(&mut self, _target: &mut Self) {
#[cfg(target_arch = "riscv32")]
asm!(r"
asm!(
r"
.equ XLENB, 4
.macro Load reg, mem
lw \reg, \mem
.endm
.macro Store reg, mem
sw \reg, \mem
.endm");
.endm"
);
#[cfg(target_arch = "riscv64")]
asm!(r"
asm!(
r"
.equ XLENB, 8
.macro Load reg, mem
ld \reg, \mem
.endm
.macro Store reg, mem
sd \reg, \mem
.endm");
.endm"
);
asm!("
// save from's registers
addi sp, sp, (-XLENB*14)
@ -210,11 +214,17 @@ impl Context {
/// The new thread starts at function `entry` with an usize argument `arg`.
/// The stack pointer will be set to `kstack_top`.
/// The SATP register will be set to `satp`.
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, satp: usize) -> Self {
pub unsafe fn new_kernel_thread(
entry: extern "C" fn(usize) -> !,
arg: usize,
kstack_top: usize,
satp: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
/// Constructs Context for a new user thread.
@ -222,11 +232,18 @@ impl Context {
/// The new thread starts at `entry_addr`.
/// The stack pointer of user and kernel mode will be set to `ustack_top`, `kstack_top`.
/// The SATP register will be set to `satp`.
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, satp: usize) -> Self {
pub unsafe fn new_user_thread(
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
_is32: bool,
satp: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
/// Fork a user process and get the new Context.
@ -243,7 +260,8 @@ impl Context {
tf.x[10] = 0; // a0
tf
},
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
/// Fork a user thread and get the new Context.
@ -253,7 +271,13 @@ impl Context {
/// The new user stack will be set to `ustack_top`.
/// The new thread pointer will be set to `tls`.
/// All the other registers are same as the original.
pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, satp: usize, tls: usize) -> Self {
pub unsafe fn new_clone(
tf: &TrapFrame,
ustack_top: usize,
kstack_top: usize,
satp: usize,
tls: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
tf: {
@ -263,7 +287,8 @@ impl Context {
tf.x[10] = 0; // a0
tf
},
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
/// Used for getting the init TrapFrame of a new user context in `sys_exec`.

@ -9,7 +9,9 @@ pub unsafe fn set_cpu_id(cpu_id: usize) {
pub fn id() -> usize {
let cpu_id;
unsafe { asm!("mv $0, gp" : "=r"(cpu_id)); }
unsafe {
asm!("mv $0, gp" : "=r"(cpu_id));
}
cpu_id
}

@ -1,14 +1,14 @@
use riscv::register::*;
use crate::drivers::DRIVERS;
pub use self::context::*;
use crate::drivers::DRIVERS;
use log::*;
use riscv::register::*;
#[path = "context.rs"]
mod context;
/// Initialize interrupt
pub fn init() {
extern {
extern "C" {
fn trap_entry();
}
unsafe {
@ -53,9 +53,13 @@ pub unsafe fn restore(flags: usize) {
///
/// This function is called from `trap.asm`.
#[no_mangle]
pub extern fn rust_trap(tf: &mut TrapFrame) {
use self::scause::{Trap, Interrupt as I, Exception as E};
trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), tf.scause.cause());
pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
use self::scause::{Exception as E, Interrupt as I, Trap};
trace!(
"Interrupt @ CPU{}: {:?} ",
super::cpu::id(),
tf.scause.cause()
);
match tf.scause.cause() {
Trap::Interrupt(I::SupervisorExternal) => external(),
Trap::Interrupt(I::SupervisorSoft) => ipi(),
@ -71,13 +75,15 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
fn external() {
#[cfg(feature = "board_u540")]
unsafe { super::board::handle_external_interrupt(); }
unsafe {
super::board::handle_external_interrupt();
}
// true means handled, false otherwise
let handlers = [try_process_serial, try_process_drivers];
for handler in handlers.iter() {
if handler() == true {
break
break;
}
}
}
@ -88,17 +94,17 @@ fn try_process_serial() -> bool {
crate::trap::serial(ch);
true
}
None => false
None => false,
}
}
fn try_process_drivers() -> bool {
for driver in DRIVERS.read().iter() {
if driver.try_handle_interrupt(None) == true {
return true
return true;
}
}
return false
return false;
}
fn ipi() {
@ -113,7 +119,11 @@ fn timer() {
fn syscall(tf: &mut TrapFrame) {
tf.sepc += 4; // Must before syscall, because of fork.
let ret = crate::syscall::syscall(tf.x[17], [tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]], tf);
let ret = crate::syscall::syscall(
tf.x[17],
[tf.x[10], tf.x[11], tf.x[12], tf.x[13], tf.x[14], tf.x[15]],
tf,
);
tf.x[10] = ret as usize;
}

@ -1,5 +1,5 @@
use core::fmt::{Write, Result, Arguments};
use super::sbi;
use core::fmt::{Arguments, Result, Write};
struct SerialPort;

@ -1,14 +1,16 @@
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET};
use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR};
use core::mem;
use riscv::{addr::*, register::sstatus};
use rcore_memory::PAGE_SIZE;
use log::*;
use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryAttr, MemorySet, Linear};
use crate::consts::{MEMORY_OFFSET, MEMORY_END, KERNEL_OFFSET};
use rcore_memory::PAGE_SIZE;
use riscv::register::satp;
use riscv::{addr::*, register::sstatus};
/// Initialize the memory management module
pub fn init(dtb: usize) {
unsafe { sstatus::set_sum(); } // Allow user memory access
unsafe {
sstatus::set_sum();
} // Allow user memory access
// initialize heap and Frame allocator
init_frame_allocator();
init_heap();
@ -28,7 +30,10 @@ fn init_frame_allocator() {
use core::ops::Range;
let mut ba = FRAME_ALLOCATOR.lock();
let range = to_range((end as usize) - KERNEL_OFFSET + MEMORY_OFFSET + PAGE_SIZE, MEMORY_END);
let range = to_range(
(end as usize) - KERNEL_OFFSET + MEMORY_OFFSET + PAGE_SIZE,
MEMORY_END,
);
ba.insert(range);
info!("frame allocator: init end");
@ -46,18 +51,70 @@ fn init_frame_allocator() {
fn remap_the_kernel(dtb: usize) {
let offset = -(KERNEL_OFFSET as isize - MEMORY_OFFSET as isize);
let mut ms = MemorySet::new_bare();
ms.push(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), Linear::new(offset), "text");
ms.push(sdata as usize, edata as usize, MemoryAttr::default(), Linear::new(offset), "data");
ms.push(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), Linear::new(offset), "rodata");
ms.push(bootstack as usize, bootstacktop as usize, MemoryAttr::default(), Linear::new(offset), "stack");
ms.push(sbss as usize, ebss as usize, MemoryAttr::default(), Linear::new(offset), "bss");
ms.push(dtb, dtb + super::consts::MAX_DTB_SIZE, MemoryAttr::default().readonly(), Linear::new(offset), "dts");
ms.push(
stext as usize,
etext as usize,
MemoryAttr::default().execute().readonly(),
Linear::new(offset),
"text",
);
ms.push(
sdata as usize,
edata as usize,
MemoryAttr::default(),
Linear::new(offset),
"data",
);
ms.push(
srodata as usize,
erodata as usize,
MemoryAttr::default().readonly(),
Linear::new(offset),
"rodata",
);
ms.push(
bootstack as usize,
bootstacktop as usize,
MemoryAttr::default(),
Linear::new(offset),
"stack",
);
ms.push(
sbss as usize,
ebss as usize,
MemoryAttr::default(),
Linear::new(offset),
"bss",
);
ms.push(
dtb,
dtb + super::consts::MAX_DTB_SIZE,
MemoryAttr::default().readonly(),
Linear::new(offset),
"dts",
);
// map PLIC for HiFiveU
let offset = -(KERNEL_OFFSET as isize);
ms.push(KERNEL_OFFSET + 0x0C00_2000, KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic0");
ms.push(KERNEL_OFFSET + 0x0C20_2000, KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic1");
unsafe { ms.activate(); }
unsafe { SATP = ms.token(); }
ms.push(
KERNEL_OFFSET + 0x0C00_2000,
KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(offset),
"plic0",
);
ms.push(
KERNEL_OFFSET + 0x0C20_2000,
KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(offset),
"plic1",
);
unsafe {
ms.activate();
}
unsafe {
SATP = ms.token();
}
mem::forget(ms);
info!("remap kernel end");
}
@ -77,7 +134,7 @@ pub unsafe fn clear_bss() {
// Symbols provided by linker script
#[allow(dead_code)]
extern {
extern "C" {
fn stext();
fn etext();
fn sdata();

@ -1,25 +1,27 @@
pub mod io;
pub mod interrupt;
pub mod timer;
pub mod paging;
pub mod memory;
#[cfg(feature = "board_u540")]
#[path = "board/u540/mod.rs"]
mod board;
pub mod compiler_rt;
pub mod consts;
pub mod cpu;
pub mod syscall;
pub mod interrupt;
pub mod io;
pub mod memory;
pub mod paging;
pub mod rand;
#[cfg(feature = "board_u540")]
#[path = "board/u540/mod.rs"]
mod board;
mod sbi;
pub mod syscall;
pub mod timer;
use log::*;
#[no_mangle]
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
pub extern "C" fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
// An initial recursive page table has been set by BBL (shared by all cores)
unsafe { cpu::set_cpu_id(hartid); }
unsafe {
cpu::set_cpu_id(hartid);
}
if hartid != BOOT_HART_ID {
while unsafe { !cpu::has_started(hartid) } {}
@ -28,7 +30,9 @@ pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
//other_main -> !
}
unsafe { memory::clear_bss(); }
unsafe {
memory::clear_bss();
}
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
@ -40,10 +44,14 @@ pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
#[cfg(not(feature = "board_u540"))]
crate::drivers::init(dtb);
#[cfg(feature = "board_u540")]
unsafe { board::init_external_interrupt(); }
unsafe {
board::init_external_interrupt();
}
crate::process::init();
unsafe { cpu::start_others(hart_mask); }
unsafe {
cpu::start_others(hart_mask);
}
crate::kmain();
}
@ -61,7 +69,8 @@ const BOOT_HART_ID: usize = 1;
/// Constant & Macro for `trap.asm`
#[cfg(target_arch = "riscv32")]
global_asm!(r"
global_asm!(
r"
.equ XLENB, 4
.equ XLENb, 32
.macro LOAD a1, a2
@ -70,9 +79,11 @@ global_asm!(r"
.macro STORE a1, a2
sw \a1, \a2*XLENB(sp)
.endm
");
"
);
#[cfg(target_arch = "riscv64")]
global_asm!(r"
global_asm!(
r"
.equ XLENB, 8
.equ XLENb, 64
.macro LOAD a1, a2
@ -81,8 +92,8 @@ global_asm!(r"
.macro STORE a1, a2
sd \a1, \a2*XLENB(sp)
.endm
");
"
);
global_asm!(include_str!("boot/entry.asm"));
global_asm!(include_str!("boot/trap.asm"));

@ -1,17 +1,20 @@
use crate::consts::RECURSIVE_INDEX;
// Depends on kernel
#[cfg(target_arch = "riscv32")]
use crate::consts::KERNEL_P2_INDEX;
#[cfg(target_arch = "riscv64")]
use crate::consts::KERNEL_P4_INDEX;
use crate::memory::{active_table, alloc_frame, dealloc_frame};
use log::*;
use rcore_memory::paging::*;
use riscv::addr::*;
use riscv::asm::{sfence_vma, sfence_vma_all};
use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable, PageTableType};
use riscv::paging::{FrameAllocator, FrameDeallocator};
use riscv::paging::{
Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, PageTableType,
RecursivePageTable,
};
use riscv::register::satp;
use rcore_memory::paging::*;
use log::*;
#[cfg(target_arch = "riscv32")]
use crate::consts::KERNEL_P2_INDEX;
#[cfg(target_arch = "riscv64")]
use crate::consts::KERNEL_P4_INDEX;
pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry);
@ -20,7 +23,6 @@ pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry);
pub struct PageEntry(&'static mut PageTableEntry, Page);
impl PageTable for ActivePageTable {
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
// use riscv::paging:Mapper::map_to,
// map the 4K `page` to the 4K `frame` with `flags`
@ -29,7 +31,10 @@ impl PageTable for ActivePageTable {
let frame = Frame::of_addr(PhysAddr::new(target));
// map the page to the frame using FrameAllocatorForRiscv
// we may need frame allocator to alloc frame for new page table(first/second)
self.0.map_to(page, frame, flags, &mut FrameAllocatorForRiscv).unwrap().flush();
self.0
.map_to(page, frame, flags, &mut FrameAllocatorForRiscv)
.unwrap()
.flush();
self.get_entry(addr).expect("fail to get entry")
}
@ -56,29 +61,26 @@ impl PageTableExt for ActivePageTable {}
/// The virtual address of root page table
#[cfg(target_arch = "riscv32")]
const ROOT_PAGE_TABLE: *mut RvPageTable =
((RECURSIVE_INDEX << 12 << 10) |
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
((RECURSIVE_INDEX << 12 << 10) | ((RECURSIVE_INDEX + 1) << 12)) as *mut RvPageTable;
#[cfg(all(target_arch = "riscv64", feature = "sv39"))]
const ROOT_PAGE_TABLE: *mut RvPageTable =
((0xFFFF_0000_0000_0000) |
(0o777 << 12 << 9 << 9 << 9) |
(RECURSIVE_INDEX << 12 << 9 << 9) |
(RECURSIVE_INDEX << 12 << 9) |
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
const ROOT_PAGE_TABLE: *mut RvPageTable = ((0xFFFF_0000_0000_0000)
| (0o777 << 12 << 9 << 9 << 9)
| (RECURSIVE_INDEX << 12 << 9 << 9)
| (RECURSIVE_INDEX << 12 << 9)
| ((RECURSIVE_INDEX + 1) << 12)) as *mut RvPageTable;
#[cfg(all(target_arch = "riscv64", not(feature = "sv39")))]
const ROOT_PAGE_TABLE: *mut RvPageTable =
((0xFFFF_0000_0000_0000) |
(RECURSIVE_INDEX << 12 << 9 << 9 << 9) |
(RECURSIVE_INDEX << 12 << 9 << 9) |
(RECURSIVE_INDEX << 12 << 9) |
((RECURSIVE_INDEX+1) << 12)) as *mut RvPageTable;
const ROOT_PAGE_TABLE: *mut RvPageTable = ((0xFFFF_0000_0000_0000)
| (RECURSIVE_INDEX << 12 << 9 << 9 << 9)
| (RECURSIVE_INDEX << 12 << 9 << 9)
| (RECURSIVE_INDEX << 12 << 9)
| ((RECURSIVE_INDEX + 1) << 12)) as *mut RvPageTable;
impl ActivePageTable {
#[cfg(target_arch = "riscv32")]
pub unsafe fn new() -> Self {
ActivePageTable(
RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(),
::core::mem::uninitialized()
::core::mem::uninitialized(),
)
}
#[cfg(target_arch = "riscv64")]
@ -89,7 +91,7 @@ impl ActivePageTable {
let type_ = PageTableType::Sv48;
ActivePageTable(
RecursivePageTable::new(&mut *ROOT_PAGE_TABLE, type_).unwrap(),
::core::mem::uninitialized()
::core::mem::uninitialized(),
)
}
}
@ -97,37 +99,77 @@ impl ActivePageTable {
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
impl Entry for PageEntry {
fn update(&mut self) {
unsafe { sfence_vma(0, self.1.start_address().as_usize()); }
}
fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) }
fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) }
fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) }
fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); }
fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); }
fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); }
fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID | EF::READABLE, value); }
fn target(&self) -> usize { self.0.addr().as_usize() }
unsafe {
sfence_vma(0, self.1.start_address().as_usize());
}
}
fn accessed(&self) -> bool {
self.0.flags().contains(EF::ACCESSED)
}
fn dirty(&self) -> bool {
self.0.flags().contains(EF::DIRTY)
}
fn writable(&self) -> bool {
self.0.flags().contains(EF::WRITABLE)
}
fn present(&self) -> bool {
self.0.flags().contains(EF::VALID | EF::READABLE)
}
fn clear_accessed(&mut self) {
self.0.flags_mut().remove(EF::ACCESSED);
}
fn clear_dirty(&mut self) {
self.0.flags_mut().remove(EF::DIRTY);
}
fn set_writable(&mut self, value: bool) {
self.0.flags_mut().set(EF::WRITABLE, value);
}
fn set_present(&mut self, value: bool) {
self.0.flags_mut().set(EF::VALID | EF::READABLE, value);
}
fn target(&self) -> usize {
self.0.addr().as_usize()
}
fn set_target(&mut self, target: usize) {
let flags = self.0.flags();
let frame = Frame::of_addr(PhysAddr::new(target));
self.0.set(frame, flags);
}
fn writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) }
fn writable_shared(&self) -> bool {
self.0.flags().contains(EF::RESERVED1)
}
fn readonly_shared(&self) -> bool {
self.0.flags().contains(EF::RESERVED2)
}
fn set_shared(&mut self, writable: bool) {
let flags = self.0.flags_mut();
flags.set(EF::RESERVED1, writable);
flags.set(EF::RESERVED2, !writable);
}
fn clear_shared(&mut self) { self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2); }
fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); }
fn user(&self) -> bool { self.0.flags().contains(EF::USER) }
fn set_user(&mut self, value: bool) { self.0.flags_mut().set(EF::USER, value); }
fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) }
fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); }
fn mmio(&self) -> u8 { 0 }
fn clear_shared(&mut self) {
self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2);
}
fn swapped(&self) -> bool {
self.0.flags().contains(EF::RESERVED1)
}
fn set_swapped(&mut self, value: bool) {
self.0.flags_mut().set(EF::RESERVED1, value);
}
fn user(&self) -> bool {
self.0.flags().contains(EF::USER)
}
fn set_user(&mut self, value: bool) {
self.0.flags_mut().set(EF::USER, value);
}
fn execute(&self) -> bool {
self.0.flags().contains(EF::EXECUTABLE)
}
fn set_execute(&mut self, value: bool) {
self.0.flags_mut().set(EF::EXECUTABLE, value);
}
fn mmio(&self) -> u8 {
0
}
fn set_mmio(&mut self, _value: u8) {}
}
@ -152,7 +194,7 @@ impl InactivePageTable for InactivePageTable0 {
#[cfg(target_arch = "riscv32")]
fn map_kernel(&mut self) {
let table = unsafe { &mut *ROOT_PAGE_TABLE };
extern {
extern "C" {
fn start();
fn end();
}
@ -208,7 +250,9 @@ impl InactivePageTable for InactivePageTable0 {
}
fn flush_tlb() {
unsafe { sfence_vma_all(); }
unsafe {
sfence_vma_all();
}
}
fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T {
@ -218,14 +262,18 @@ impl InactivePageTable for InactivePageTable0 {
// overwrite recursive mapping
root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID);
unsafe { sfence_vma_all(); }
unsafe {
sfence_vma_all();
}
// execute f in the new context
let ret = f(active_table);
// restore recursive mapping to original p2 table
root_table[RECURSIVE_INDEX] = backup;
unsafe { sfence_vma_all(); }
unsafe {
sfence_vma_all();
}
ret
})

@ -28,7 +28,12 @@ pub fn shutdown() -> ! {
pub fn set_timer(stime_value: u64) {
#[cfg(target_pointer_width = "32")]
sbi_call(SBI_SET_TIMER, stime_value as usize, (stime_value >> 32) as usize, 0);
sbi_call(
SBI_SET_TIMER,
stime_value as usize,
(stime_value >> 32) as usize,
0,
);
#[cfg(target_pointer_width = "64")]
sbi_call(SBI_SET_TIMER, stime_value as usize, 0, 0);
}
@ -50,7 +55,12 @@ pub fn remote_sfence_vma(hart_mask: usize, _start: usize, _size: usize) {
}
pub fn remote_sfence_vma_asid(hart_mask: usize, _start: usize, _size: usize, _asid: usize) {
sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, 0);
sbi_call(
SBI_REMOTE_SFENCE_VMA_ASID,
&hart_mask as *const _ as usize,
0,
0,
);
}
const SBI_SET_TIMER: usize = 0;

@ -1,6 +1,6 @@
use riscv::register::*;
use super::sbi;
use log::*;
use riscv::register::*;
#[cfg(target_pointer_width = "64")]
pub fn get_cycle() -> u64 {
@ -27,7 +27,9 @@ pub fn read_epoch() -> u64 {
/// Enable timer interrupt
pub fn init() {
// Enable supervisor timer interrupt
unsafe { sie::set_stimer(); }
unsafe {
sie::set_stimer();
}
set_next();
info!("timer: init end");
}

@ -14,7 +14,10 @@ pub unsafe fn exit_in_qemu(error_code: u8) -> ! {
}
pub fn id() -> usize {
CpuId::new().get_feature_info().unwrap().initial_local_apic_id() as usize
CpuId::new()
.get_feature_info()
.unwrap()
.initial_local_apic_id() as usize
}
pub fn send_ipi(cpu_id: usize) {

@ -16,10 +16,26 @@ pub struct IDE {
impl IDE {
pub fn new(num: u8) -> Self {
let ide = match num {
0 => IDE { num: 0, base: 0x1f0, ctrl: 0x3f4 },
1 => IDE { num: 1, base: 0x1f0, ctrl: 0x3f4 },
2 => IDE { num: 2, base: 0x170, ctrl: 0x374 },
3 => IDE { num: 3, base: 0x170, ctrl: 0x374 },
0 => IDE {
num: 0,
base: 0x1f0,
ctrl: 0x3f4,
},
1 => IDE {
num: 1,
base: 0x1f0,
ctrl: 0x3f4,
},
2 => IDE {
num: 2,
base: 0x170,
ctrl: 0x374,
},
3 => IDE {
num: 3,
base: 0x170,
ctrl: 0x374,
},
_ => panic!("ide number should be 0,1,2,3"),
};
ide.init();
@ -103,7 +119,10 @@ impl IDE {
port::outb(self.base + ISA_SECTOR, (sector & 0xFF) as u8);
port::outb(self.base + ISA_CYL_LO, ((sector >> 8) & 0xFF) as u8);
port::outb(self.base + ISA_CYL_HI, ((sector >> 16) & 0xFF) as u8);
port::outb(self.base + ISA_SDH, 0xE0 | ((self.num & 1) << 4) | (((sector >> 24) & 0xF) as u8));
port::outb(
self.base + ISA_SDH,
0xE0 | ((self.num & 1) << 4) | (((sector >> 24) & 0xF) as u8),
);
}
}
}

@ -1,7 +1,7 @@
use lazy_static::lazy_static;
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
use spin::Mutex;
use x86_64::instructions::port::Port;
use pc_keyboard::{Keyboard, ScancodeSet1, DecodedKey, layouts, HandleControl};
use lazy_static::lazy_static;
pub fn init() {
use crate::arch::interrupt::consts;
@ -13,8 +13,9 @@ pub fn init() {
/// Should be called on every interrupt
pub fn receive() -> Option<DecodedKey> {
lazy_static! {
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore));
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = Mutex::new(
Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore)
);
}
let mut keyboard = KEYBOARD.lock();

@ -1,12 +1,12 @@
use once::*;
pub mod vga;
pub mod serial;
pub mod pic;
pub mod ide;
pub mod keyboard;
pub mod pic;
pub mod pit;
pub mod ide;
pub mod rtc_cmos;
pub mod serial;
pub mod vga;
pub fn init() {
assert_has_not_been_called!();

@ -1,9 +1,9 @@
// Copy from Redox
use x86_64::instructions::port::Port;
use spin::Mutex;
use once::*;
use log::*;
use once::*;
use spin::Mutex;
use x86_64::instructions::port::Port;
static MASTER: Mutex<Pic> = Mutex::new(Pic::new(0x20));
static SLAVE: Mutex<Pic> = Mutex::new(Pic::new(0xA0));
@ -80,7 +80,9 @@ impl Pic {
}
fn ack(&mut self) {
unsafe { self.cmd.write(0x20); }
unsafe {
self.cmd.write(0x20);
}
}
fn mask_set(&mut self, irq: u8) {

@ -1,6 +1,6 @@
use x86_64::instructions::port::Port;
use log::*;
use once::*;
use x86_64::instructions::port::Port;
pub fn init() {
assert_has_not_been_called!("pit::init must be called only once");

@ -61,7 +61,8 @@ pub fn read_epoch() -> u64 {
month = month - 2;
}
let result = ((((year / 4 - year / 100 + year / 400 + 367 * month / 12 + day) + year * 365
let result = ((((year / 4 - year / 100 + year / 400 + 367 * month / 12 + day)
+ year * 365
- 719499)
* 24
+ hour)

@ -51,10 +51,14 @@ pub struct ScreenChar {
}
impl ScreenChar {
pub fn new(ascii_char: u8, foreground_color: ConsoleColor, background_color: ConsoleColor) -> Self {
pub fn new(
ascii_char: u8,
foreground_color: ConsoleColor,
background_color: ConsoleColor,
) -> Self {
ScreenChar {
ascii_char,
color_code: ColorCode::new(foreground_color, background_color)
color_code: ColorCode::new(foreground_color, background_color),
}
}
}
@ -135,7 +139,8 @@ impl BaseConsole for VgaWriter {
pos.row.bound(self.get_height());
pos.col.bound(self.get_width());
self.pos = pos;
self.buffer.set_cursor_at(pos.row.0 as usize, pos.col.0 as usize);
self.buffer
.set_cursor_at(pos.row.0 as usize, pos.col.0 as usize);
Ok(())
}
@ -180,7 +185,8 @@ impl AsciiConsole for VgaWriter {
ascii_char: ch,
color_code: self.color_code,
};
self.buffer.write(pos.row.0 as usize, pos.col.0 as usize, screen_char);
self.buffer
.write(pos.row.0 as usize, pos.col.0 as usize, screen_char);
Ok(())
}
@ -221,8 +227,7 @@ impl AsciiConsole for VgaWriter {
0x1b => Some(SpecialChar::Escape),
0x7f => Some(SpecialChar::Delete),
0x08 => Some(SpecialChar::Backspace),
_ if !(ch.is_ascii_graphic() || ch == b' ')
=> Some(SpecialChar::Delete), // ignore non-graphic ascii
_ if !(ch.is_ascii_graphic() || ch == b' ') => Some(SpecialChar::Delete), // ignore non-graphic ascii
_ => None,
},
_ => None,
@ -246,7 +251,6 @@ impl VgaWriter {
impl fmt::Write for VgaWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_string(s.as_bytes())
.map_err(|_| fmt::Error)
self.write_string(s.as_bytes()).map_err(|_| fmt::Error)
}
}

@ -1,9 +1,9 @@
use alloc::boxed::Box;
use x86_64::{PrivilegeLevel, VirtAddr};
use x86_64::registers::model_specific::Msr;
use x86_64::structures::gdt::*;
use x86_64::structures::tss::TaskStateSegment;
use x86_64::registers::model_specific::Msr;
use x86_64::{PrivilegeLevel, VirtAddr};
use crate::consts::MAX_CPU_NUM;
@ -17,8 +17,7 @@ pub fn init() {
static mut CPUS: [Option<Cpu>; MAX_CPU_NUM] = [
// TODO: More elegant ?
None, None, None, None,
None, None, None, None,
None, None, None, None, None, None, None, None,
];
pub struct Cpu {
@ -41,7 +40,7 @@ impl Cpu {
}
unsafe fn init(&'static mut self) {
use x86_64::instructions::segmentation::{set_cs, load_fs};
use x86_64::instructions::segmentation::{load_fs, set_cs};
use x86_64::instructions::tables::load_tss;
// Set the stack when DoubleFault occurs

@ -1,5 +1,5 @@
use x86_64::structures::idt::*;
use lazy_static::lazy_static;
use x86_64::structures::idt::*;
pub fn init() {
IDT.load();
@ -37,9 +37,9 @@ lazy_static! {
};
}
extern {
extern "C" {
/// 中断向量表
/// 符号定义在 [trap.asm](boot/trap.asm)
//noinspection RsStaticConstNaming
static __vectors: [extern fn(); 256];
static __vectors: [extern "C" fn(); 256];
}

@ -1,9 +1,8 @@
/// `syscall` instruction
use x86_64::registers::model_specific::*;
use core::mem::transmute;
use super::super::gdt;
use super::TrapFrame;
use core::mem::transmute;
/// `syscall` instruction
use x86_64::registers::model_specific::*;
pub fn init() {
unsafe {
@ -26,7 +25,7 @@ pub fn init() {
}
}
extern {
extern "C" {
fn syscall_entry();
}

@ -66,17 +66,21 @@
use super::consts::*;
use super::TrapFrame;
use log::*;
use bitflags::*;
use crate::drivers::DRIVERS;
use bitflags::*;
use log::*;
global_asm!(include_str!("trap.asm"));
global_asm!(include_str!("vector.asm"));
#[allow(non_upper_case_globals)]
#[no_mangle]
pub extern fn rust_trap(tf: &mut TrapFrame) {
trace!("Interrupt: {:#x} @ CPU{}", tf.trap_num, super::super::cpu::id());
pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
trace!(
"Interrupt: {:#x} @ CPU{}",
tf.trap_num,
super::super::cpu::id()
);
// Dispatch
match tf.trap_num as u8 {
Breakpoint => breakpoint(),
@ -99,7 +103,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
}
}
warn!("unhandled external IRQ number: {}", irq);
},
}
}
}
Syscall32 => syscall32(tf),
@ -120,7 +124,9 @@ fn double_fault(tf: &TrapFrame) {
fn page_fault(tf: &mut TrapFrame) {
let addr: usize;
unsafe { asm!("mov %cr2, $0" : "=r" (addr)); }
unsafe {
asm!("mov %cr2, $0" : "=r" (addr));
}
bitflags! {
struct PageError: u8 {
@ -209,7 +215,7 @@ fn error(tf: &TrapFrame) {
}
#[no_mangle]
pub unsafe extern fn set_return_rsp(tf: *const TrapFrame) {
pub unsafe extern "C" fn set_return_rsp(tf: *const TrapFrame) {
use crate::arch::gdt::Cpu;
Cpu::current().set_ring0_rsp(tf.add(1) as usize);
}

@ -1,12 +1,12 @@
pub mod consts;
pub mod fast_syscall;
mod handler;
mod trapframe;
pub mod fast_syscall;
pub use self::trapframe::*;
pub use self::handler::*;
use apic::*;
pub use self::trapframe::*;
use crate::consts::KERNEL_OFFSET;
use apic::*;
#[inline(always)]
pub unsafe fn enable() {

@ -1,5 +1,5 @@
use core::fmt;
use core::default::Default;
use core::fmt;
#[derive(Clone)]
#[repr(C)]
@ -17,7 +17,6 @@ impl Default for FpState {
}
}
#[derive(Debug, Clone, Default)]
#[repr(C)]
pub struct TrapFrame {
@ -62,7 +61,7 @@ pub struct TrapFrame {
/// 用于在内核栈中构造新线程的中断帧
impl TrapFrame {
fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, rsp: usize) -> Self {
fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, rsp: usize) -> Self {
use crate::arch::gdt;
let mut tf = TrapFrame::default();
tf.rdi = arg;
@ -77,7 +76,11 @@ impl TrapFrame {
fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self {
use crate::arch::gdt;
let mut tf = TrapFrame::default();
tf.cs = if is32 { gdt::UCODE32_SELECTOR.0 } else { gdt::UCODE_SELECTOR.0 } as usize;
tf.cs = if is32 {
gdt::UCODE32_SELECTOR.0
} else {
gdt::UCODE_SELECTOR.0
} as usize;
tf.rip = entry_addr;
tf.ss = gdt::UDATA32_SELECTOR.0 as usize;
tf.rsp = rsp;
@ -105,7 +108,11 @@ struct ContextData {
impl ContextData {
fn new(cr3: usize) -> Self {
ContextData { rip: trap_ret as usize, cr3, ..ContextData::default() }
ContextData {
rip: trap_ret as usize,
cr3,
..ContextData::default()
}
}
}
@ -125,7 +132,7 @@ impl InitStack {
}
}
extern {
extern "C" {
fn trap_ret();
}
@ -142,7 +149,7 @@ impl Context {
/// Pop all callee-saved registers, then return to the target.
#[naked]
#[inline(never)]
pub unsafe extern fn switch(&mut self, _target: &mut Self) {
pub unsafe extern "C" fn switch(&mut self, _target: &mut Self) {
asm!(
"
// push rip (by caller)
@ -180,17 +187,30 @@ impl Context {
Context(0)
}
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, cr3: usize) -> Self {
pub unsafe fn new_kernel_thread(
entry: extern "C" fn(usize) -> !,
arg: usize,
kstack_top: usize,
cr3: usize,
) -> Self {
InitStack {
context: ContextData::new(cr3),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top)
}
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize) -> Self {
.push_at(kstack_top)
}
pub unsafe fn new_user_thread(
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
is32: bool,
cr3: usize,
) -> Self {
InitStack {
context: ContextData::new(cr3),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top, is32),
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {
InitStack {
@ -200,9 +220,16 @@ impl Context {
tf.rax = 0;
tf
},
}.push_at(kstack_top)
}
pub unsafe fn new_clone(tf: &TrapFrame, ustack_top: usize, kstack_top: usize, cr3: usize, tls: usize) -> Self {
.push_at(kstack_top)
}
pub unsafe fn new_clone(
tf: &TrapFrame,
ustack_top: usize,
kstack_top: usize,
cr3: usize,
tls: usize,
) -> Self {
InitStack {
context: ContextData::new(cr3),
tf: {
@ -212,7 +239,8 @@ impl Context {
tf.rax = 0;
tf
},
}.push_at(kstack_top)
}
.push_at(kstack_top)
}
/// Called at a new user context
/// To get the init TrapFrame in sys_exec

@ -3,19 +3,25 @@ use super::driver::vga::VGA_WRITER;
use core::fmt::{Arguments, Write};
pub fn getchar() -> char {
unsafe { COM1.force_unlock(); }
unsafe {
COM1.force_unlock();
}
COM1.lock().receive() as char
}
pub fn putfmt(fmt: Arguments) {
#[cfg(feature = "nographic")]
{
unsafe { COM1.force_unlock(); }
unsafe {
COM1.force_unlock();
}
COM1.lock().write_fmt(fmt).unwrap();
}
#[cfg(not(feature = "nographic"))]
{
unsafe { VGA_WRITER.force_unlock(); }
unsafe {
VGA_WRITER.force_unlock();
}
VGA_WRITER.lock().write_fmt(fmt).unwrap();
}
}

@ -1,11 +1,11 @@
use bit_allocator::BitAlloc;
use crate::consts::KERNEL_OFFSET;
use bit_allocator::BitAlloc;
// Depends on kernel
use crate::memory::{FRAME_ALLOCATOR, init_heap, active_table};
use super::{BootInfo, MemoryRegionType};
use rcore_memory::paging::*;
use once::*;
use crate::memory::{active_table, init_heap, FRAME_ALLOCATOR};
use log::*;
use once::*;
use rcore_memory::paging::*;
pub fn init(boot_info: &BootInfo) {
assert_has_not_been_called!("memory::init must be called only once");
@ -20,7 +20,9 @@ fn init_frame_allocator(boot_info: &BootInfo) {
let mut ba = FRAME_ALLOCATOR.lock();
for region in boot_info.memory_map.iter() {
if region.region_type == MemoryRegionType::Usable {
ba.insert(region.range.start_frame_number as usize..region.range.end_frame_number as usize);
ba.insert(
region.range.start_frame_number as usize..region.range.end_frame_number as usize,
);
}
}
}
@ -28,7 +30,11 @@ fn init_frame_allocator(boot_info: &BootInfo) {
fn init_device_vm_map() {
let mut page_table = active_table();
// IOAPIC
page_table.map(KERNEL_OFFSET + 0xfec00000, 0xfec00000).update();
page_table
.map(KERNEL_OFFSET + 0xfec00000, 0xfec00000)
.update();
// LocalAPIC
page_table.map(KERNEL_OFFSET + 0xfee00000, 0xfee00000).update();
page_table
.map(KERNEL_OFFSET + 0xfee00000, 0xfee00000)
.update();
}

@ -2,18 +2,18 @@ use bootloader::bootinfo::{BootInfo, MemoryRegionType};
use core::sync::atomic::*;
use log::*;
pub mod driver;
pub mod consts;
pub mod cpu;
pub mod interrupt;
pub mod paging;
pub mod driver;
pub mod gdt;
pub mod idt;
pub mod memory;
pub mod interrupt;
pub mod io;
pub mod consts;
pub mod timer;
pub mod syscall;
pub mod memory;
pub mod paging;
pub mod rand;
pub mod syscall;
pub mod timer;
static AP_CAN_INIT: AtomicBool = ATOMIC_BOOL_INIT;

@ -1,18 +1,18 @@
// Depends on kernel
use crate::consts::KERNEL_OFFSET;
use crate::memory::{active_table, alloc_frame, dealloc_frame};
use log::*;
use rcore_memory::paging::*;
use x86_64::instructions::tlb;
use x86_64::PhysAddr;
use x86_64::registers::control::{Cr3, Cr3Flags};
use x86_64::structures::paging::{
page_table::{PageTable as x86PageTable, PageTableEntry, PageTableFlags as EF},
frame::PhysFrame as Frame,
mapper::{Mapper, RecursivePageTable},
page::{Page, PageRange, Size4KiB},
frame::PhysFrame as Frame,
FrameAllocator, FrameDeallocator
page_table::{PageTable as x86PageTable, PageTableEntry, PageTableFlags as EF},
FrameAllocator, FrameDeallocator,
};
use crate::consts::KERNEL_OFFSET;
use log::*;
use x86_64::PhysAddr;
pub trait PageExt {
fn of_addr(address: usize) -> Self;
@ -47,7 +47,12 @@ impl PageTable for ActivePageTable {
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
let flags = EF::PRESENT | EF::WRITABLE | EF::NO_EXECUTE;
unsafe {
if let Ok(flush) = self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, &mut FrameAllocatorForX86) {
if let Ok(flush) = self.0.map_to(
Page::of_addr(addr),
Frame::of_addr(target),
flags,
&mut FrameAllocatorForX86,
) {
flush.flush();
}
}
@ -64,7 +69,9 @@ impl PageTable for ActivePageTable {
fn get_entry(&mut self, addr: usize) -> Option<&mut Entry> {
for level in 0..3 {
let entry = get_entry_ptr(addr, 4 - level);
if unsafe { !(*entry).present() } { return None; }
if unsafe { !(*entry).present() } {
return None;
}
}
unsafe { Some(&mut *(get_entry_ptr(addr, 1))) }
}
@ -82,34 +89,64 @@ impl ActivePageTable {
impl Entry for PageEntry {
fn update(&mut self) {
use x86_64::{VirtAddr, instructions::tlb::flush};
use x86_64::{instructions::tlb::flush, VirtAddr};
let addr = VirtAddr::new_unchecked((self as *const _ as u64) << 9);
flush(addr);
}
fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) }
fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) }
fn present(&self) -> bool { self.0.flags().contains(EF::PRESENT) }
fn clear_accessed(&mut self) { self.as_flags().remove(EF::ACCESSED); }
fn clear_dirty(&mut self) { self.as_flags().remove(EF::DIRTY); }
fn set_writable(&mut self, value: bool) { self.as_flags().set(EF::WRITABLE, value); }
fn set_present(&mut self, value: bool) { self.as_flags().set(EF::PRESENT, value); }
fn target(&self) -> usize { self.0.addr().as_u64() as usize }
fn accessed(&self) -> bool {
self.0.flags().contains(EF::ACCESSED)
}
fn dirty(&self) -> bool {
self.0.flags().contains(EF::DIRTY)
}
fn writable(&self) -> bool {
self.0.flags().contains(EF::WRITABLE)
}
fn present(&self) -> bool {
self.0.flags().contains(EF::PRESENT)
}
fn clear_accessed(&mut self) {
self.as_flags().remove(EF::ACCESSED);
}
fn clear_dirty(&mut self) {
self.as_flags().remove(EF::DIRTY);
}
fn set_writable(&mut self, value: bool) {
self.as_flags().set(EF::WRITABLE, value);
}
fn set_present(&mut self, value: bool) {
self.as_flags().set(EF::PRESENT, value);
}
fn target(&self) -> usize {
self.0.addr().as_u64() as usize
}
fn set_target(&mut self, target: usize) {
let flags = self.0.flags();
self.0.set_addr(PhysAddr::new(target as u64), flags);
}
fn writable_shared(&self) -> bool { self.0.flags().contains(EF::BIT_10) }
fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::BIT_9) }
fn writable_shared(&self) -> bool {
self.0.flags().contains(EF::BIT_10)
}
fn readonly_shared(&self) -> bool {
self.0.flags().contains(EF::BIT_9)
}
fn set_shared(&mut self, writable: bool) {
let flags = self.as_flags();
flags.set(EF::BIT_10, writable);
flags.set(EF::BIT_9, !writable);
}
fn clear_shared(&mut self) { self.as_flags().remove(EF::BIT_9 | EF::BIT_10); }
fn swapped(&self) -> bool { self.0.flags().contains(EF::BIT_11) }
fn set_swapped(&mut self, value: bool) { self.as_flags().set(EF::BIT_11, value); }
fn user(&self) -> bool { self.0.flags().contains(EF::USER_ACCESSIBLE) }
fn clear_shared(&mut self) {
self.as_flags().remove(EF::BIT_9 | EF::BIT_10);
}
fn swapped(&self) -> bool {
self.0.flags().contains(EF::BIT_11)
}
fn set_swapped(&mut self, value: bool) {
self.as_flags().set(EF::BIT_11, value);
}
fn user(&self) -> bool {
self.0.flags().contains(EF::USER_ACCESSIBLE)
}
fn set_user(&mut self, value: bool) {
self.as_flags().set(EF::USER_ACCESSIBLE, value);
if value {
@ -122,9 +159,15 @@ impl Entry for PageEntry {
}
}
}
fn execute(&self) -> bool { !self.0.flags().contains(EF::NO_EXECUTE) }
fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::NO_EXECUTE, !value); }
fn mmio(&self) -> u8 { 0 }
fn execute(&self) -> bool {
!self.0.flags().contains(EF::NO_EXECUTE)
}
fn set_execute(&mut self, value: bool) {
self.as_flags().set(EF::NO_EXECUTE, !value);
}
fn mmio(&self) -> u8 {
0
}
fn set_mmio(&mut self, _value: u8) {}
}
@ -176,7 +219,10 @@ impl InactivePageTable for InactivePageTable0 {
}
unsafe fn set_token(token: usize) {
Cr3::write(Frame::containing_address(PhysAddr::new(token as u64)), Cr3Flags::empty());
Cr3::write(
Frame::containing_address(PhysAddr::new(token as u64)),
Cr3Flags::empty(),
);
}
fn active_token() -> usize {

@ -52,8 +52,16 @@ pub fn backtrace() {
let mut current_pc = lr();
let mut current_fp = fp();
let mut stack_num = 0;
while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 {
println!("#{} {:#018X} fp {:#018X}", stack_num, current_pc - size_of::<usize>(), current_fp);
while current_pc >= stext as usize
&& current_pc <= etext as usize
&& current_fp as usize != 0
{
println!(
"#{} {:#018X} fp {:#018X}",
stack_num,
current_pc - size_of::<usize>(),
current_fp
);
stack_num = stack_num + 1;
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
{
@ -72,8 +80,9 @@ pub fn backtrace() {
// Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate)
// size = 512 pages
current_fp = *(current_fp as *const usize).offset(0);
if current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::<usize>() &&
current_fp <= 0xffff_ff00_0000_0000 {
if current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::<usize>()
&& current_fp <= 0xffff_ff00_0000_0000
{
break;
}
current_pc = *(current_fp as *const usize).offset(1);

@ -1,5 +1,5 @@
use core::slice;
use alloc::string::String;
use core::slice;
use device_tree::{DeviceTree, Node};

@ -1,7 +1,7 @@
//! Implement Device
use spin::RwLock;
use rcore_fs::dev::*;
use spin::RwLock;
#[cfg(target_arch = "x86_64")]
use crate::arch::driver::ide;
@ -9,9 +9,12 @@ use crate::arch::driver::ide;
pub struct MemBuf(RwLock<&'static mut [u8]>);
impl MemBuf {
pub unsafe fn new(begin: unsafe extern fn(), end: unsafe extern fn()) -> Self {
pub unsafe fn new(begin: unsafe extern "C" fn(), end: unsafe extern "C" fn()) -> Self {
use core::slice;
MemBuf(RwLock::new(slice::from_raw_parts_mut(begin as *mut u8, end as usize - begin as usize)))
MemBuf(RwLock::new(slice::from_raw_parts_mut(
begin as *mut u8,
end as usize - begin as usize,
)))
}
}
@ -36,7 +39,8 @@ impl BlockDevice for ide::IDE {
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> bool {
use core::slice;
assert!(buf.len() >= ide::BLOCK_SIZE);
let buf = unsafe { slice::from_raw_parts_mut(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
let buf =
unsafe { slice::from_raw_parts_mut(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
self.read(block_id as u64, 1, buf).is_ok()
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> bool {

@ -2,7 +2,7 @@
use alloc::{string::String, sync::Arc};
use rcore_fs::vfs::{Metadata, INode, Result, FsError};
use rcore_fs::vfs::{FsError, INode, Metadata, Result};
#[derive(Clone)]
pub struct FileHandle {

@ -7,24 +7,28 @@ use rcore_fs_sfs::SimpleFileSystem;
use crate::arch::driver::ide;
pub use self::file::*;
pub use self::stdio::{STDIN, STDOUT};
pub use self::pipe::Pipe;
pub use self::stdio::{STDIN, STDOUT};
mod file;
mod stdio;
mod device;
mod file;
mod pipe;
mod stdio;
/// Hard link user programs
#[cfg(feature = "link_user")]
global_asm!(concat!(r#"
global_asm!(concat!(
r#"
.section .data
.global _user_img_start
.global _user_img_end
_user_img_start:
.incbin ""#, env!("SFSIMG"), r#""
.incbin ""#,
env!("SFSIMG"),
r#""
_user_img_end:
"#));
"#
));
lazy_static! {
/// The root of file system
@ -66,7 +70,9 @@ impl INodeExt for INode {
fn read_as_vec(&self) -> Result<Vec<u8>> {
let size = self.metadata()?.size;
let mut buf = Vec::with_capacity(size);
unsafe { buf.set_len(size); }
unsafe {
buf.set_len(size);
}
self.read_at(0, buf.as_mut_slice())?;
Ok(buf)
}

@ -67,12 +67,16 @@ impl INode for Stdin {
buf[0] = self.pop() as u8;
Ok(1)
}
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> { unimplemented!() }
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
unimplemented!()
}
impl_inode!();
}
impl INode for Stdout {
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> { unimplemented!() }
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
unimplemented!()
}
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
use core::str;
//we do not care the utf-8 things, we just want to print it!

@ -1,19 +1,20 @@
// Rust language features implementations
use core::panic::PanicInfo;
use crate::backtrace;
use core::alloc::Layout;
use core::panic::PanicInfo;
use log::*;
use crate::backtrace;
#[lang = "eh_personality"]
extern fn eh_personality() {
}
extern "C" fn eh_personality() {}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
error!("\n\n{}", info);
backtrace::backtrace();
loop { crate::arch::cpu::halt() }
loop {
crate::arch::cpu::halt()
}
}
#[lang = "oom"]

@ -16,25 +16,25 @@ extern crate log;
#[macro_use]
extern crate lazy_static;
pub use crate::process::{processor, new_kernel_context};
use rcore_thread::std_thread as thread;
pub use crate::process::{new_kernel_context, processor};
use buddy_system_allocator::LockedHeap;
use rcore_thread::std_thread as thread;
#[macro_use] // print!
mod logging;
mod memory;
mod lang;
mod util;
mod backtrace;
mod consts;
mod process;
mod syscall;
mod drivers;
mod fs;
mod lang;
mod memory;
mod net;
mod process;
mod shell;
mod sync;
mod syscall;
mod trap;
mod shell;
mod drivers;
mod net;
mod backtrace;
mod util;
#[allow(dead_code)]
#[cfg(target_arch = "x86_64")]

@ -64,12 +64,14 @@ impl Log for SimpleLogger {
true
}
fn log(&self, record: &Record) {
static DISABLED_TARGET: &[&str] = &[
];
static DISABLED_TARGET: &[&str] = &[];
if self.enabled(record.metadata()) && !DISABLED_TARGET.contains(&record.target()) {
// let target = record.target();
// let begin = target.as_bytes().iter().rposition(|&c| c == b':').map(|i| i + 1).unwrap_or(0);
print_in_color(format_args!("[{:>5}] {}\n", record.level(), record.args()), ConsoleColor::from(record.level()));
print_in_color(
format_args!("[{:>5}] {}\n", record.level(), record.args()),
ConsoleColor::from(record.level()),
);
}
}
fn flush(&self) {}

@ -1,14 +1,14 @@
use super::HEAP_ALLOCATOR;
pub use crate::arch::paging::*;
use bit_allocator::BitAlloc;
use crate::consts::MEMORY_OFFSET;
use super::HEAP_ALLOCATOR;
use rcore_memory::*;
pub use rcore_memory::memory_set::{MemoryArea, MemoryAttr, handler::*};
use crate::process::process_unsafe;
use crate::sync::SpinNoIrqLock;
use bit_allocator::BitAlloc;
use buddy_system_allocator::LockedHeap;
use lazy_static::*;
use log::*;
use buddy_system_allocator::LockedHeap;
pub use rcore_memory::memory_set::{handler::*, MemoryArea, MemoryAttr};
use rcore_memory::*;
pub type MemorySet = rcore_memory::memory_set::MemorySet<InactivePageTable0>;
@ -25,7 +25,8 @@ pub type FrameAlloc = bit_allocator::BitAlloc4K;
pub type FrameAlloc = bit_allocator::BitAlloc1M;
lazy_static! {
pub static ref FRAME_ALLOCATOR: SpinNoIrqLock<FrameAlloc> = SpinNoIrqLock::new(FrameAlloc::default());
pub static ref FRAME_ALLOCATOR: SpinNoIrqLock<FrameAlloc> =
SpinNoIrqLock::new(FrameAlloc::default());
}
/// The only way to get active page table
@ -46,21 +47,25 @@ pub fn active_table() -> ActivePageTable {
unsafe { ActivePageTable::new() }
}
#[derive(Debug, Clone, Copy)]
pub struct GlobalFrameAlloc;
impl FrameAllocator for GlobalFrameAlloc {
fn alloc(&self) -> Option<usize> {
// get the real address of the alloc frame
let ret = FRAME_ALLOCATOR.lock().alloc().map(|id| id * PAGE_SIZE + MEMORY_OFFSET);
let ret = FRAME_ALLOCATOR
.lock()
.alloc()
.map(|id| id * PAGE_SIZE + MEMORY_OFFSET);
trace!("Allocate frame: {:x?}", ret);
ret
// TODO: try to swap out when alloc failed
}
fn dealloc(&self, target: usize) {
trace!("Deallocate frame: {:x}", target);
FRAME_ALLOCATOR.lock().dealloc((target - MEMORY_OFFSET) / PAGE_SIZE);
FRAME_ALLOCATOR
.lock()
.dealloc((target - MEMORY_OFFSET) / PAGE_SIZE);
}
}
@ -77,7 +82,8 @@ const STACK_SIZE: usize = 0x8000;
impl KernelStack {
pub fn new() -> Self {
use alloc::alloc::{alloc, Layout};
let bottom = unsafe{ alloc(Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap()) } as usize;
let bottom =
unsafe { alloc(Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap()) } as usize;
KernelStack(bottom)
}
pub fn top(&self) -> usize {
@ -88,10 +94,14 @@ impl KernelStack {
impl Drop for KernelStack {
fn drop(&mut self) {
use alloc::alloc::{dealloc, Layout};
unsafe{ dealloc(self.0 as _, Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap()); }
unsafe {
dealloc(
self.0 as _,
Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap(),
);
}
}
}
/// Handle page fault at `addr`.
/// Return true to continue, false to halt.
@ -99,15 +109,17 @@ pub fn handle_page_fault(addr: usize) -> bool {
debug!("page fault @ {:#x}", addr);
// This is safe as long as page fault never happens in page fault handler
unsafe {
process_unsafe().vm.handle_page_fault(addr)
}
unsafe { process_unsafe().vm.handle_page_fault(addr) }
}
pub fn init_heap() {
use crate::consts::KERNEL_HEAP_SIZE;
static mut HEAP: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE];
unsafe { HEAP_ALLOCATOR.lock().init(HEAP.as_ptr() as usize, KERNEL_HEAP_SIZE); }
unsafe {
HEAP_ALLOCATOR
.lock()
.init(HEAP.as_ptr() as usize, KERNEL_HEAP_SIZE);
}
info!("heap init end");
}

@ -1,8 +1,8 @@
use alloc::sync::Arc;
use crate::arch::rand;
use crate::drivers::{NET_DRIVERS, SOCKET_ACTIVITY};
use crate::sync::SpinNoIrqLock as Mutex;
use crate::syscall::*;
use alloc::sync::Arc;
use smoltcp::socket::*;
use smoltcp::wire::*;

@ -1,6 +1,6 @@
use alloc::collections::btree_map::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use alloc::collections::btree_map::BTreeMap;
use core::ptr::null;
pub struct ProcInitInfo {
@ -16,17 +16,25 @@ impl ProcInitInfo {
// program name
writer.push_str(&self.args[0]);
// environment strings
let envs: Vec<_> = self.envs.iter().map(|(key, value)| {
let envs: Vec<_> = self
.envs
.iter()
.map(|(key, value)| {
writer.push_str(value.as_str());
writer.push_slice(&[b"="]);
writer.push_slice(key.as_bytes());
writer.sp
}).collect();
})
.collect();
// argv strings
let argv: Vec<_> = self.args.iter().map(|arg| {
let argv: Vec<_> = self
.args
.iter()
.map(|arg| {
writer.push_str(arg.as_str());
writer.sp
}).collect();
})
.collect();
// auxiliary vector entries
writer.push_slice(&[null::<u8>(), null::<u8>()]);
for (&type_, &value) in self.auxv.iter() {
@ -50,11 +58,13 @@ struct StackWriter {
impl StackWriter {
fn push_slice<T: Copy>(&mut self, vs: &[T]) {
use core::{mem::{size_of, align_of}, slice};
use core::{
mem::{align_of, size_of},
slice,
};
self.sp -= vs.len() * size_of::<T>();
self.sp -= self.sp % align_of::<T>();
unsafe { slice::from_raw_parts_mut(self.sp as *mut T, vs.len()) }
.copy_from_slice(vs);
unsafe { slice::from_raw_parts_mut(self.sp as *mut T, vs.len()) }.copy_from_slice(vs);
}
fn push_str(&mut self, s: &str) {
self.push_slice(&[b'\0']);

@ -1,13 +1,13 @@
pub use self::structs::*;
pub use rcore_thread::*;
use crate::consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use crate::arch::cpu;
use crate::consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use alloc::{boxed::Box, sync::Arc};
use spin::MutexGuard;
use log::*;
pub use rcore_thread::*;
use spin::MutexGuard;
pub mod structs;
mod abi;
pub mod structs;
pub fn init() {
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
@ -25,7 +25,16 @@ pub fn init() {
info!("process: init end");
}
static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new()];
static PROCESSORS: [Processor; MAX_CPU_NUM] = [
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
];
/// Get current process
pub fn process() -> MutexGuard<'static, Process> {
@ -45,13 +54,10 @@ pub unsafe fn process_unsafe() -> MutexGuard<'static, Process> {
/// FIXME: It's obviously unsafe to get &mut !
pub fn current_thread() -> &'static mut Thread {
use core::mem::transmute;
let (process, _): (&mut Thread, *const ()) = unsafe {
transmute(processor().context())
};
let (process, _): (&mut Thread, *const ()) = unsafe { transmute(processor().context()) };
process
}
// Implement dependencies for std::thread
#[no_mangle]
@ -60,6 +66,6 @@ pub fn processor() -> &'static Processor {
}
#[no_mangle]
pub fn new_kernel_context(entry: extern fn(usize) -> !, arg: usize) -> Box<Context> {
pub fn new_kernel_context(entry: extern "C" fn(usize) -> !, arg: usize) -> Box<Context> {
Thread::new_kernel(entry, arg)
}

@ -1,18 +1,22 @@
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::Vec, sync::Weak};
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec};
use core::fmt;
use core::str;
use log::*;
use spin::{Mutex, RwLock};
use xmas_elf::{ElfFile, header, program::{Flags, Type, SegmentData}};
use rcore_memory::PAGE_SIZE;
use rcore_thread::Tid;
use core::str;
use spin::{Mutex, RwLock};
use xmas_elf::{
header,
program::{Flags, SegmentData, Type},
ElfFile,
};
use crate::arch::interrupt::{Context, TrapFrame};
use crate::fs::{FileHandle, INodeExt, OpenOptions, FOLLOW_MAX_DEPTH};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::fs::{FileHandle, OpenOptions, INodeExt, FOLLOW_MAX_DEPTH};
use crate::sync::Condvar;
use crate::net::{SocketWrapper, SOCKETS};
use crate::sync::Condvar;
use super::abi::{self, ProcInitInfo};
@ -26,20 +30,17 @@ pub struct Thread {
pub proc: Arc<Mutex<Process>>,
}
#[derive(Clone)]
pub enum FileLike {
File(FileHandle),
Socket(SocketWrapper)
Socket(SocketWrapper),
}
impl fmt::Debug for FileLike {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FileLike::File(_) => write!(f, "File"),
FileLike::Socket(wrapper) => {
write!(f, "{:?}", wrapper)
},
FileLike::Socket(wrapper) => write!(f, "{:?}", wrapper),
}
}
}
@ -104,7 +105,8 @@ pub struct Process {
/// Records the mapping between pid and Process struct.
lazy_static! {
pub static ref PROCESSES: RwLock<BTreeMap<usize, Weak<Mutex<Process>>>> = RwLock::new(BTreeMap::new());
pub static ref PROCESSES: RwLock<BTreeMap<usize, Weak<Mutex<Process>>>> =
RwLock::new(BTreeMap::new());
}
/// Let `rcore_thread` can switch between our `Thread`
@ -128,7 +130,9 @@ impl rcore_thread::Context for Thread {
}
// add it to threads
proc.threads.push(tid);
PROCESSES.write().insert(proc.pid.get(), Arc::downgrade(&self.proc));
PROCESSES
.write()
.insert(proc.pid.get(), Arc::downgrade(&self.proc));
}
}
@ -156,7 +160,7 @@ impl Thread {
}
/// Make a new kernel thread starting from `entry` with `arg`
pub fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Box<Thread> {
pub fn new_kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Box<Thread> {
let vm = MemorySet::new();
let kstack = KernelStack::new();
Box::new(Thread {
@ -174,14 +178,15 @@ impl Thread {
children: Vec::new(),
threads: Vec::new(),
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new()
child_exit_code: BTreeMap::new(),
})),
})
}
/// Make a new user process from ELF `data`
pub fn new_user<'a, Iter>(data: &[u8], args: Iter) -> Box<Thread>
where Iter: Iterator<Item=&'a str>
where
Iter: Iterator<Item = &'a str>,
{
// Parse ELF
let elf = ElfFile::new(data).expect("failed to read elf");
@ -192,8 +197,8 @@ impl Thread {
// Check ELF type
match elf.header.pt2.type_().as_type() {
header::Type::Executable => {},
header::Type::SharedObject => {},
header::Type::Executable => {}
header::Type::SharedObject => {}
_ => panic!("ELF is not executable or shared object"),
}
@ -220,13 +225,19 @@ impl Thread {
let mut vm = elf.make_memory_set();
// User stack
use crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
use crate::consts::{USER32_STACK_OFFSET, USER_STACK_OFFSET, USER_STACK_SIZE};
let mut ustack_top = {
let (ustack_buttom, ustack_top) = match is32 {
true => (USER32_STACK_OFFSET, USER32_STACK_OFFSET + USER_STACK_SIZE),
false => (USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE),
};
vm.push(ustack_buttom, ustack_top, MemoryAttr::default().user(), ByFrame::new(GlobalFrameAlloc), "user_stack");
vm.push(
ustack_buttom,
ustack_top,
MemoryAttr::default().user(),
ByFrame::new(GlobalFrameAlloc),
"user_stack",
);
ustack_top
};
@ -246,7 +257,7 @@ impl Thread {
},
};
unsafe {
vm.with(|| { ustack_top = init_info.push_at(ustack_top) });
vm.with(|| ustack_top = init_info.push_at(ustack_top));
}
trace!("{:#x?}", vm);
@ -254,16 +265,45 @@ impl Thread {
let kstack = KernelStack::new();
let mut files = BTreeMap::new();
files.insert(0, FileLike::File(FileHandle::new(crate::fs::STDIN.clone(), OpenOptions { read: true, write: false, append: false })));
files.insert(1, FileLike::File(FileHandle::new(crate::fs::STDOUT.clone(), OpenOptions { read: false, write: true, append: false })));
files.insert(2, FileLike::File(FileHandle::new(crate::fs::STDOUT.clone(), OpenOptions { read: false, write: true, append: false })));
files.insert(
0,
FileLike::File(FileHandle::new(
crate::fs::STDIN.clone(),
OpenOptions {
read: true,
write: false,
append: false,
},
)),
);
files.insert(
1,
FileLike::File(FileHandle::new(
crate::fs::STDOUT.clone(),
OpenOptions {
read: false,
write: true,
append: false,
},
)),
);
files.insert(
2,
FileLike::File(FileHandle::new(
crate::fs::STDOUT.clone(),
OpenOptions {
read: false,
write: true,
append: false,
},
)),
);
let entry_addr = elf.header.pt2.entry_point() as usize;
Box::new(Thread {
context: unsafe {
Context::new_user_thread(
entry_addr, ustack_top, kstack.top(), is32, vm.token())
Context::new_user_thread(entry_addr, ustack_top, kstack.top(), is32, vm.token())
},
kstack,
clear_child_tid: 0,
@ -277,7 +317,7 @@ impl Thread {
children: Vec::new(),
threads: Vec::new(),
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new()
child_exit_code: BTreeMap::new(),
})),
})
}
@ -297,9 +337,7 @@ impl Thread {
// NoMMU: coping data has been done in `vm.clone()`
for area in vm.iter() {
let data = Vec::<u8>::from(unsafe { area.as_slice() });
unsafe { vm.with(|| {
area.as_slice_mut().copy_from_slice(data.as_slice())
}) }
unsafe { vm.with(|| area.as_slice_mut().copy_from_slice(data.as_slice())) }
}
debug!("fork: temporary copy data!");
@ -326,13 +364,19 @@ impl Thread {
children: Vec::new(),
threads: Vec::new(),
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new()
child_exit_code: BTreeMap::new(),
})),
})
}
/// Create a new thread in the same process.
pub fn clone(&self, tf: &TrapFrame, stack_top: usize, tls: usize, clear_child_tid: usize) -> Box<Thread> {
pub fn clone(
&self,
tf: &TrapFrame,
stack_top: usize,
tls: usize,
clear_child_tid: usize,
) -> Box<Thread> {
let kstack = KernelStack::new();
let token = self.proc.lock().vm.token();
Box::new(Thread {
@ -371,7 +415,9 @@ impl ToMemoryAttr for Flags {
fn to_attr(&self) -> MemoryAttr {
let mut flags = MemoryAttr::default().user();
// FIXME: handle readonly
if self.is_execute() { flags = flags.execute(); }
if self.is_execute() {
flags = flags.execute();
}
flags
}
}
@ -406,7 +452,13 @@ impl ElfExt for ElfFile<'_> {
// Get target slice
let target = {
ms.push(virt_addr, virt_addr + mem_size, ph.flags().to_attr(), ByFrame::new(GlobalFrameAlloc), "");
ms.push(
virt_addr,
virt_addr + mem_size,
ph.flags().to_attr(),
ByFrame::new(GlobalFrameAlloc),
"",
);
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
};
// Copy data
@ -423,9 +475,11 @@ impl ElfExt for ElfFile<'_> {
}
fn get_interpreter(&self) -> Result<&str, &str> {
let header = self.program_iter()
let header = self
.program_iter()
.filter(|ph| ph.get_type() == Ok(Type::Interp))
.next().ok_or("no interp header")?;
.next()
.ok_or("no interp header")?;
let mut data = match header.get_data(self)? {
SegmentData::Undefined(data) => data,
_ => unreachable!(),
@ -434,18 +488,21 @@ impl ElfExt for ElfFile<'_> {
while let Some(0) = data.last() {
data = &data[..data.len() - 1];
}
let path = str::from_utf8(data)
.map_err(|_| "failed to convert to utf8")?;
let path = str::from_utf8(data).map_err(|_| "failed to convert to utf8")?;
Ok(path)
}
fn get_phdr_vaddr(&self) -> Option<u64> {
if let Some(phdr) = self.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Phdr)) {
if let Some(phdr) = self
.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Phdr))
{
// if phdr exists in program header, use it
Some(phdr.virtual_addr())
} else if let Some(elf_addr) = self.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Load) && ph.offset() == 0) {
} else if let Some(elf_addr) = self
.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Load) && ph.offset() == 0)
{
// otherwise, check if elf is loaded from the beginning, then phdr can be inferred.
Some(elf_addr.virtual_addr() + self.header.pt2.ph_offset())
} else {

@ -1,16 +1,18 @@
//! Kernel shell
use crate::drivers::CMDLINE;
use crate::fs::{INodeExt, ROOT_INODE};
use crate::process::*;
use alloc::string::String;
use alloc::vec::Vec;
use crate::fs::{ROOT_INODE, INodeExt};
use crate::process::*;
use crate::drivers::CMDLINE;
#[cfg(not(feature = "run_cmdline"))]
pub fn run_user_shell() {
if let Ok(inode) = ROOT_INODE.lookup("rust/sh") {
let data = inode.read_as_vec().unwrap();
processor().manager().add(Thread::new_user(data.as_slice(), "sh".split(' ')));
processor()
.manager()
.add(Thread::new_user(data.as_slice(), "sh".split(' ')));
} else {
processor().manager().add(Thread::new_kernel(shell, 0));
}
@ -21,10 +23,12 @@ pub fn run_user_shell() {
let cmdline = CMDLINE.read();
let inode = ROOT_INODE.lookup(&cmdline).unwrap();
let data = inode.read_as_vec().unwrap();
processor().manager().add(Thread::new_user(data.as_slice(), cmdline.split(' ')));
processor()
.manager()
.add(Thread::new_user(data.as_slice(), cmdline.split(' ')));
}
pub extern fn shell(_arg: usize) -> ! {
pub extern "C" fn shell(_arg: usize) -> ! {
let files = ROOT_INODE.list().unwrap();
println!("Available programs: {:?}", files);
let mut history = Vec::new();
@ -38,7 +42,9 @@ pub extern fn shell(_arg: usize) -> ! {
let name = cmd.trim().split(' ').next().unwrap();
if let Ok(file) = ROOT_INODE.lookup(name) {
let data = file.read_as_vec().unwrap();
let _pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' ')));
let _pid = processor()
.manager()
.add(Thread::new_user(data.as_slice(), cmd.split(' ')));
// TODO: wait until process exits, or use user land shell completely
//unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap();
} else {

@ -1,6 +1,6 @@
use alloc::collections::VecDeque;
use super::*;
use crate::thread;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use alloc::vec::Vec;
@ -47,7 +47,8 @@ impl Condvar {
}
pub fn wait<'a, T, S>(&self, guard: MutexGuard<'a, T, S>) -> MutexGuard<'a, T, S>
where S: MutexSupport
where
S: MutexSupport,
{
let mutex = guard.mutex;
drop(guard);

@ -54,8 +54,8 @@ pub use self::condvar::*;
pub use self::mutex::*;
pub use self::semaphore::*;
mod mutex;
mod condvar;
mod semaphore;
pub mod mpsc;
mod mutex;
mod semaphore;
pub mod test;

@ -1,6 +1,6 @@
use alloc::{sync::Arc, sync::Weak, collections::VecDeque};
use super::Condvar;
use super::SpinLock as Mutex;
use alloc::{collections::VecDeque, sync::Arc, sync::Weak};
struct Channel<T> {
deque: Mutex<VecDeque<T>>,
@ -78,7 +78,9 @@ impl<T> Sender<T> {
/// Creates a new asynchronous channel, returning the sender/receiver halves.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let channel = Arc::new(Channel::<T>::default());
let sender = Sender { inner: Arc::downgrade(&channel) };
let sender = Sender {
inner: Arc::downgrade(&channel),
};
let receiver = Receiver { inner: channel };
(sender, receiver)
}
@ -86,9 +88,9 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
pub mod test {
//! Copied from std::mpsc::test
use alloc::boxed::Box;
use super::*;
use crate::thread;
use alloc::boxed::Box;
fn smoke() {
let (tx, rx) = channel::<i32>();

@ -26,19 +26,18 @@
//! `MutexSupport`提供了若干接口,它们会在操作锁的不同时间点被调用。
//! 注意这个接口实际是取了几种实现的并集,并不是很通用。
use super::Condvar;
use crate::arch::interrupt;
use core::cell::UnsafeCell;
use core::fmt;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering};
use super::Condvar;
pub type SpinLock<T> = Mutex<T, Spin>;
pub type SpinNoIrqLock<T> = Mutex<T, SpinNoIrq>;
pub type ThreadLock<T> = Mutex<T, Condvar>;
pub struct Mutex<T: ?Sized, S: MutexSupport>
{
pub struct Mutex<T: ?Sized, S: MutexSupport> {
lock: AtomicBool,
support: S,
data: UnsafeCell<T>,
@ -47,8 +46,7 @@ pub struct Mutex<T: ?Sized, S: MutexSupport>
/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
pub struct MutexGuard<'a, T: ?Sized + 'a, S: MutexSupport + 'a>
{
pub struct MutexGuard<'a, T: ?Sized + 'a, S: MutexSupport + 'a> {
pub(super) mutex: &'a Mutex<T, S>,
support_guard: S::GuardData,
}
@ -58,8 +56,7 @@ unsafe impl<T: ?Sized + Send, S: MutexSupport> Sync for Mutex<T, S> {}
unsafe impl<T: ?Sized + Send, S: MutexSupport> Send for Mutex<T, S> {}
impl<T, S: MutexSupport> Mutex<T, S>
{
impl<T, S: MutexSupport> Mutex<T, S> {
/// Creates a new spinlock wrapping the supplied data.
///
/// May be used statically:
@ -93,8 +90,7 @@ impl<T, S: MutexSupport> Mutex<T, S>
}
}
impl<T: ?Sized, S: MutexSupport> Mutex<T, S>
{
impl<T: ?Sized, S: MutexSupport> Mutex<T, S> {
fn obtain_lock(&self) {
while self.lock.compare_and_swap(false, true, Ordering::Acquire) != false {
// Wait until the lock looks unlocked before retrying
@ -119,8 +115,7 @@ impl<T: ?Sized, S: MutexSupport> Mutex<T, S>
/// }
///
/// ```
pub fn lock(&self) -> MutexGuard<T, S>
{
pub fn lock(&self) -> MutexGuard<T, S> {
let support_guard = S::before_lock();
self.obtain_lock();
MutexGuard {
@ -155,11 +150,14 @@ impl<T: ?Sized, S: MutexSupport> Mutex<T, S>
}
}
impl<T: ?Sized + fmt::Debug, S: MutexSupport + fmt::Debug> fmt::Debug for Mutex<T, S>
{
impl<T: ?Sized + fmt::Debug, S: MutexSupport + fmt::Debug> fmt::Debug for Mutex<T, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.try_lock() {
Some(guard) => write!(f, "Mutex {{ data: {:?}, support: {:?} }}", &*guard, self.support),
Some(guard) => write!(
f,
"Mutex {{ data: {:?}, support: {:?} }}",
&*guard, self.support
),
None => write!(f, "Mutex {{ <locked>, support: {:?} }}", self.support),
}
}
@ -171,19 +169,20 @@ impl<T: ?Sized + Default, S: MutexSupport> Default for Mutex<T, S> {
}
}
impl<'a, T: ?Sized, S: MutexSupport> Deref for MutexGuard<'a, T, S>
{
impl<'a, T: ?Sized, S: MutexSupport> Deref for MutexGuard<'a, T, S> {
type Target = T;
fn deref(&self) -> &T { unsafe { &*self.mutex.data.get() } }
fn deref(&self) -> &T {
unsafe { &*self.mutex.data.get() }
}
}
impl<'a, T: ?Sized, S: MutexSupport> DerefMut for MutexGuard<'a, T, S>
{
fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.mutex.data.get() } }
impl<'a, T: ?Sized, S: MutexSupport> DerefMut for MutexGuard<'a, T, S> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.data.get() }
}
}
impl<'a, T: ?Sized, S: MutexSupport> Drop for MutexGuard<'a, T, S>
{
impl<'a, T: ?Sized, S: MutexSupport> Drop for MutexGuard<'a, T, S> {
/// The dropping of the MutexGuard will release the lock it was created from.
fn drop(&mut self) {
self.mutex.lock.store(false, Ordering::Release);
@ -210,7 +209,9 @@ pub struct Spin;
impl MutexSupport for Spin {
type GuardData = ();
fn new() -> Self { Spin }
fn new() -> Self {
Spin
}
fn cpu_relax(&self) {
unsafe {
#[cfg(target_arch = "x86_64")]

@ -2,12 +2,12 @@
//!
//! The code is borrowed from [RustDoc - Dining Philosophers](https://doc.rust-lang.org/1.6.0/book/dining-philosophers.html)
use alloc::{sync::Arc, vec::Vec};
use core::time::Duration;
use crate::sync::Condvar;
use crate::sync::ThreadLock as Mutex;
use crate::thread;
use alloc::vec;
use alloc::{sync::Arc, vec::Vec};
use core::time::Duration;
use log::*;
struct Philosopher {
@ -18,11 +18,7 @@ struct Philosopher {
impl Philosopher {
fn new(name: &'static str, left: usize, right: usize) -> Philosopher {
Philosopher {
name,
left,
right,
}
Philosopher { name, left, right }
}
fn eat(&self, table: &Arc<Table>) {
@ -92,7 +88,9 @@ fn philosopher(table: Arc<Table>) {
Philosopher::new("5", 0, 4),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let handles: Vec<_> = philosophers
.into_iter()
.map(|p| {
let table = table.clone();
trace!("philosopher start");
@ -103,7 +101,8 @@ fn philosopher(table: Arc<Table>) {
println!("{} iter {} end.", p.name, i);
}
})
}).collect();
})
.collect();
trace!("philosopher starting finish");
for h in handles {
@ -116,7 +115,13 @@ pub fn philosopher_using_mutex() {
println!("philosophers using mutex");
let table = Arc::new(MutexTable {
forks: vec![Mutex::new(()), Mutex::new(()), Mutex::new(()), Mutex::new(()), Mutex::new(())]
forks: vec![
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
],
});
philosopher(table);
}
@ -126,7 +131,13 @@ pub fn philosopher_using_monitor() {
let table = Arc::new(MonitorTable {
fork_status: Mutex::new(vec![false; 5]),
fork_condvar: vec![Condvar::new(), Condvar::new(), Condvar::new(), Condvar::new(), Condvar::new()],
fork_condvar: vec![
Condvar::new(),
Condvar::new(),
Condvar::new(),
Condvar::new(),
Condvar::new(),
],
});
philosopher(table);
}

@ -1,7 +1,7 @@
//! Custom nonstandard syscalls
use super::*;
use rcore_memory::memory_set::handler::Linear;
use rcore_memory::memory_set::MemoryAttr;
use super::*;
/// Allocate this PCI device to user space
/// The kernel driver using the PCI device will be unloaded
@ -13,15 +13,13 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
vendor, product
);
let tag = pci::find_device(vendor as u32, product as u32)
.ok_or(SysError::ENOENT)?;
let tag = pci::find_device(vendor as u32, product as u32).ok_or(SysError::ENOENT)?;
if pci::detach_driver(&tag) {
info!("Kernel driver detached");
}
// Get BAR0 memory
let (base, len) = unsafe { tag.get_bar_mem(0) }
.ok_or(SysError::ENOENT)?;
let (base, len) = unsafe { tag.get_bar_mem(0) }.ok_or(SysError::ENOENT)?;
let mut proc = process();
let virt_addr = proc.vm.find_free_area(0, len);

@ -1,14 +1,14 @@
//! Syscalls for file system
use core::mem::size_of;
use core::cmp::min;
use core::cell::UnsafeCell;
use core::cmp::min;
use core::mem::size_of;
use rcore_fs::vfs::Timespec;
use crate::drivers::SOCKET_ACTIVITY;
use crate::fs::*;
use crate::memory::MemorySet;
use crate::sync::Condvar;
use crate::drivers::SOCKET_ACTIVITY;
use super::*;
@ -22,7 +22,7 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
match proc.files.get(&fd) {
Some(FileLike::File(_)) => sys_read_file(&mut proc, fd, base, len),
Some(FileLike::Socket(_)) => sys_read_socket(&mut proc, fd, base, len),
None => Err(SysError::EINVAL)
None => Err(SysError::EINVAL),
}
}
@ -37,12 +37,15 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
match proc.files.get(&fd) {
Some(FileLike::File(_)) => sys_write_file(&mut proc, fd, base, len),
Some(FileLike::Socket(_)) => sys_write_socket(&mut proc, fd, base, len),
None => Err(SysError::EINVAL)
None => Err(SysError::EINVAL),
}
}
pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResult {
info!("pread: fd: {}, base: {:?}, len: {}, offset: {}", fd, base, len, offset);
info!(
"pread: fd: {}, base: {:?}, len: {}, offset: {}",
fd, base, len, offset
);
let mut proc = process();
proc.vm.check_write_array(base, len)?;
@ -52,7 +55,10 @@ pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResu
}
pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysResult {
info!("pwrite: fd: {}, base: {:?}, len: {}, offset: {}", fd, base, len, offset);
info!(
"pwrite: fd: {}, base: {:?}, len: {}, offset: {}",
fd, base, len, offset
);
let mut proc = process();
proc.vm.check_read_array(base, len)?;
@ -74,7 +80,10 @@ pub fn sys_write_file(proc: &mut Process, fd: usize, base: *const u8, len: usize
}
pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
info!("poll: ufds: {:?}, nfds: {}, timeout_msecs: {:#x}", ufds, nfds, timeout_msecs);
info!(
"poll: ufds: {:?}, nfds: {}, timeout_msecs: {:#x}",
ufds, nfds, timeout_msecs
);
let proc = process();
proc.vm.check_write_array(ufds, nfds)?;
@ -100,7 +109,7 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu
poll.revents = poll.revents | PE::IN;
events = events + 1;
}
},
}
Some(FileLike::Socket(wrapper)) => {
let (input, output, err) = poll_socket(&wrapper);
if err {
@ -143,7 +152,7 @@ const MAX_FDSET_SIZE: usize = 1024 / FD_PER_ITEM;
struct FdSet {
addr: *mut u32,
nfds: usize,
saved: [u32; MAX_FDSET_SIZE]
saved: [u32; MAX_FDSET_SIZE],
}
impl FdSet {
@ -166,11 +175,7 @@ impl FdSet {
}
}
Ok(FdSet {
addr,
nfds,
saved
})
Ok(FdSet { addr, nfds, saved })
}
/// Try to set fd in `FdSet`
@ -196,8 +201,17 @@ impl FdSet {
}
}
pub fn sys_select(nfds: usize, read: *mut u32, write: *mut u32, err: *mut u32, timeout: *const TimeVal) -> SysResult {
info!("select: nfds: {}, read: {:?}, write: {:?}, err: {:?}, timeout: {:?}", nfds, read, write, err, timeout);
pub fn sys_select(
nfds: usize,
read: *mut u32,
write: *mut u32,
err: *mut u32,
timeout: *const TimeVal,
) -> SysResult {
info!(
"select: nfds: {}, read: {:?}, write: {:?}, err: {:?}, timeout: {:?}",
nfds, read, write, err, timeout
);
let proc = process();
let mut read_fds = FdSet::new(&proc.vm, read, nfds)?;
@ -227,7 +241,7 @@ pub fn sys_select(nfds: usize, read: *mut u32, write: *mut u32, err: *mut u32, t
events = events + 1;
}
}
},
}
FileLike::Socket(wrapper) => {
let (input, output, err) = poll_socket(&wrapper);
if err && err_fds.is_set(*fd) {
@ -268,7 +282,10 @@ pub fn sys_select(nfds: usize, read: *mut u32, write: *mut u32, err: *mut u32, t
}
pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
info!("readv: fd: {}, iov: {:?}, count: {}", fd, iov_ptr, iov_count);
info!(
"readv: fd: {}, iov: {:?}, count: {}",
fd, iov_ptr, iov_count
);
let mut proc = process();
let mut iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)?;
@ -282,7 +299,10 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul
}
pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
info!("writev: fd: {}, iov: {:?}, count: {}", fd, iov_ptr, iov_count);
info!(
"writev: fd: {}, iov: {:?}, count: {}",
fd, iov_ptr, iov_count
);
let mut proc = process();
let iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)?;
@ -292,7 +312,7 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu
match proc.files.get(&fd) {
Some(FileLike::File(_)) => sys_write_file(&mut proc, fd, buf.as_ptr(), len),
Some(FileLike::Socket(_)) => sys_write_socket(&mut proc, fd, buf.as_ptr(), len),
None => Err(SysError::EINVAL)
None => Err(SysError::EINVAL),
}
}
@ -306,10 +326,12 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
let mut proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = OpenFlags::from_bits_truncate(flags);
info!("openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}", dir_fd as isize, path, flags, mode);
info!(
"openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}",
dir_fd as isize, path, flags, mode
);
let inode =
if dir_fd == AT_FDCWD {
let inode = if dir_fd == AT_FDCWD {
// from process cwd
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
@ -321,7 +343,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
return Err(SysError::EEXIST);
}
file_inode
},
}
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
@ -343,7 +365,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
return Err(SysError::EEXIST);
}
file_inode
},
}
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
@ -390,9 +412,7 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
if proc.cwd.len() + 1 > len {
return Err(SysError::ERANGE);
}
unsafe {
util::write_cstr(buf, &proc.cwd)
}
unsafe { util::write_cstr(buf, &proc.cwd) }
Ok(buf as usize)
}
@ -408,7 +428,9 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
let file = proc.get_file(fd)?;
let stat = Stat::from(file.metadata()?);
// TODO: handle symlink
unsafe { stat_ptr.write(stat); }
unsafe {
stat_ptr.write(stat);
}
Ok(0)
}
@ -420,7 +442,9 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
let inode = proc.lookup_inode(&path)?;
let stat = Stat::from(inode.metadata()?);
unsafe { stat_ptr.write(stat); }
unsafe {
stat_ptr.write(stat);
}
Ok(0)
}
@ -483,7 +507,10 @@ pub fn sys_ftruncate(fd: usize, len: usize) -> SysResult {
}
pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult {
info!("getdents64: fd: {}, ptr: {:?}, buf_size: {}", fd, buf, buf_size);
info!(
"getdents64: fd: {}, ptr: {:?}, buf_size: {}",
fd, buf, buf_size
);
let mut proc = process();
proc.vm.check_write_array(buf as *mut u8, buf_size)?;
let file = proc.get_file(fd)?;
@ -499,7 +526,9 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy
}?;
// TODO: get ino from dirent
let ok = writer.try_write(0, DirentType::from_type(&info.type_).bits(), &name);
if !ok { break; }
if !ok {
break;
}
}
Ok(writer.written_size)
}
@ -515,12 +544,12 @@ pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult {
let new_file = FileLike::File(file.clone());
proc.files.insert(fd2, new_file);
Ok(fd2)
},
}
Some(FileLike::Socket(wrapper)) => {
let new_wrapper = wrapper.clone();
sys_dup2_socket(&mut proc, new_wrapper, fd2)
},
None => Err(SysError::EINVAL)
}
None => Err(SysError::EINVAL),
}
}
@ -552,23 +581,33 @@ pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult {
sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath)
}
pub fn sys_renameat(olddirfd: usize, oldpath: *const u8, newdirfd: usize, newpath: *const u8) -> SysResult {
pub fn sys_renameat(
olddirfd: usize,
oldpath: *const u8,
newdirfd: usize,
newpath: *const u8,
) -> SysResult {
let mut proc = process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
info!("renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}", olddirfd, oldpath, newdirfd, newpath);
info!(
"renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}",
olddirfd, oldpath, newdirfd, newpath
);
let (old_dir_path, old_file_name) = split_path(&oldpath);
let (new_dir_path, new_file_name) = split_path(&newpath);
let old_dir_inode = if olddirfd == AT_FDCWD {
proc.lookup_inode(old_dir_path)?
} else {
proc.get_file(olddirfd)?.lookup_follow(old_dir_path, FOLLOW_MAX_DEPTH)?
proc.get_file(olddirfd)?
.lookup_follow(old_dir_path, FOLLOW_MAX_DEPTH)?
};
let new_dir_inode = if newdirfd == AT_FDCWD {
proc.lookup_inode(new_dir_path)?
} else {
proc.get_file(newdirfd)?.lookup_follow(new_dir_path, FOLLOW_MAX_DEPTH)?
proc.get_file(newdirfd)?
.lookup_follow(new_dir_path, FOLLOW_MAX_DEPTH)?
};
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
Ok(0)
@ -640,10 +679,30 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
let (read, write) = Pipe::create_pair();
let read_fd = proc.get_free_fd();
proc.files.insert(read_fd, FileLike::File(FileHandle::new(Arc::new(read), OpenOptions { read: true, write: false, append: false })));
proc.files.insert(
read_fd,
FileLike::File(FileHandle::new(
Arc::new(read),
OpenOptions {
read: true,
write: false,
append: false,
},
)),
);
let write_fd = proc.get_free_fd();
proc.files.insert(write_fd, FileLike::File(FileHandle::new(Arc::new(write), OpenOptions { read: false, write: true, append: false })));
proc.files.insert(
write_fd,
FileLike::File(FileHandle::new(
Arc::new(write),
OpenOptions {
read: false,
write: true,
append: false,
},
)),
);
unsafe {
*fds = read_fd as u32;
@ -661,7 +720,10 @@ pub fn sys_sync() -> SysResult {
}
pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usize) -> SysResult {
info!("sendfile: out: {}, in: {}, offset: {:?}, count: {}", out_fd, in_fd, offset, count);
info!(
"sendfile: out: {}, in: {}, offset: {:?}, count: {}",
out_fd, in_fd, offset, count
);
let proc = process();
// We know it's save, pacify the borrow checker
let proc_cell = UnsafeCell::new(proc);
@ -695,9 +757,7 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz
} else {
let proc_mem = unsafe { &mut *proc_cell.get() };
proc_mem.vm.check_read_ptr(offset)?;
let mut read_offset = unsafe {
*offset
};
let mut read_offset = unsafe { *offset };
// read from specified offset and write new offset back
let mut bytes_read = 0;
while bytes_read < count {
@ -726,16 +786,19 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz
impl Process {
pub fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> {
self.files.get_mut(&fd).ok_or(SysError::EBADF).and_then(|f| {
match f {
self.files
.get_mut(&fd)
.ok_or(SysError::EBADF)
.and_then(|f| match f {
FileLike::File(file) => Ok(file),
_ => Err(SysError::EBADF)
}
_ => Err(SysError::EBADF),
})
}
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, SysError> {
debug!("lookup_inode: cwd {} path {}", self.cwd, path);
Ok(ROOT_INODE.lookup(&self.cwd)?.lookup_follow(path, FOLLOW_MAX_DEPTH)?)
Ok(ROOT_INODE
.lookup(&self.cwd)?
.lookup_follow(path, FOLLOW_MAX_DEPTH)?)
}
}
@ -1058,7 +1121,7 @@ impl From<Metadata> for Stat {
atime: info.atime,
mtime: info.mtime,
ctime: info.ctime,
_pad0: 0
_pad0: 0,
}
}
@ -1079,7 +1142,7 @@ impl From<Metadata> for Stat {
mtime: info.mtime,
ctime: info.ctime,
__pad: 0,
__pad2: 0
__pad2: 0,
}
}
}
@ -1102,7 +1165,12 @@ pub struct IoVec {
struct IoVecs(Vec<&'static mut [u8]>);
impl IoVecs {
fn check_and_new(iov_ptr: *const IoVec, iov_count: usize, vm: &MemorySet, readv: bool) -> Result<Self, SysError> {
fn check_and_new(
iov_ptr: *const IoVec,
iov_count: usize,
vm: &MemorySet,
readv: bool,
) -> Result<Self, SysError> {
vm.check_read_array(iov_ptr, iov_count)?;
let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec();
// check all bufs in iov
@ -1116,7 +1184,10 @@ impl IoVecs {
}
}
}
let slices = iovs.iter().map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len as usize) }).collect();
let slices = iovs
.iter()
.map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len as usize) })
.collect();
Ok(IoVecs(slices))
}
@ -1148,7 +1219,9 @@ impl IoVecs {
let total_len = self.0.iter().map(|slice| slice.len()).sum::<usize>();
let mut buf = Vec::with_capacity(total_len);
if set_len {
unsafe { buf.set_len(total_len); }
unsafe {
buf.set_len(total_len);
}
}
buf
}

@ -1,4 +1,4 @@
use rcore_memory::memory_set::handler::{Delay, ByFrame};
use rcore_memory::memory_set::handler::{ByFrame, Delay};
use rcore_memory::memory_set::MemoryAttr;
use rcore_memory::paging::PageTable;
use rcore_memory::Page;
@ -85,7 +85,10 @@ pub fn sys_mprotect(addr: usize, len: usize, prot: usize) -> SysResult {
// FIXME: properly set the attribute of the area
// now some mut ptr check is fault
let memory_area = proc.vm.iter().find(|area| area.is_overlap_with(addr, addr + len));
let memory_area = proc
.vm
.iter()
.find(|area| area.is_overlap_with(addr, addr + len));
if memory_area.is_none() {
return Err(SysError::ENOMEM);
}

@ -1,7 +1,7 @@
use super::*;
use crate::arch::cpu;
use core::mem::size_of;
use core::sync::atomic::{AtomicI32, Ordering};
use crate::arch::cpu;
pub fn sys_arch_prctl(code: i32, addr: usize, tf: &mut TrapFrame) -> SysResult {
const ARCH_SET_FS: i32 = 0x1002;
@ -22,8 +22,7 @@ pub fn sys_uname(buf: *mut u8) -> SysResult {
let offset = 65;
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
let proc = process();
proc.vm
.check_write_array(buf, strings.len() * offset)?;
proc.vm.check_write_array(buf, strings.len() * offset)?;
for i in 0..strings.len() {
unsafe {
@ -39,8 +38,7 @@ pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResu
pid, size, mask
);
let proc = process();
proc.vm
.check_write_array(mask, size / size_of::<u32>())?;
proc.vm.check_write_array(mask, size / size_of::<u32>())?;
// we only have 4 cpu at most.
// so just set it.
@ -75,9 +73,7 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
if uaddr % size_of::<u32>() != 0 {
return Err(SysError::EINVAL);
}
process()
.vm
.check_write_ptr(uaddr as *mut AtomicI32)?;
process().vm.check_write_ptr(uaddr as *mut AtomicI32)?;
let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) };
let _timeout = if timeout.is_null() {
None
@ -112,7 +108,6 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
}
}
const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123;
pub fn sys_reboot(_magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysResult {
// we will skip verifying magic

@ -1,35 +1,35 @@
//! System call
use alloc::{string::String, sync::Arc, vec::Vec};
use core::{slice, str, fmt};
use core::{fmt, slice, str};
use bitflags::bitflags;
use rcore_memory::VMError;
use rcore_fs::vfs::{FileType, FsError, INode, Metadata};
use rcore_memory::VMError;
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::sync::Condvar;
use crate::arch::syscall::*;
use crate::process::*;
use crate::sync::Condvar;
use crate::thread;
use crate::util;
use crate::arch::cpu;
use crate::arch::syscall::*;
use self::custom::*;
use self::fs::*;
use self::mem::*;
use self::misc::*;
use self::net::*;
use self::proc::*;
use self::time::*;
use self::net::*;
use self::misc::*;
use self::custom::*;
mod custom;
mod fs;
mod mem;
mod misc;
mod net;
mod proc;
mod time;
mod net;
mod misc;
mod custom;
/// System call dispatcher
// This #[deny(unreachable_patterns)] checks if each match arm is defined
@ -37,9 +37,7 @@ mod custom;
#[deny(unreachable_patterns)]
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
let cid = cpu::id();
let pid = {
process().pid.clone()
};
let pid = { process().pid.clone() };
let tid = processor().tid();
if !pid.is_init() {
// we trust pid 0 process
@ -97,8 +95,22 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
SYS_SOCKET => sys_socket(args[0], args[1], args[2]),
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, args[2]),
SYS_ACCEPT => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_SENDTO => sys_sendto(args[0], args[1] as *const u8, args[2], args[3], args[4] as *const SockAddr, args[5]),
SYS_RECVFROM => sys_recvfrom(args[0], args[1] as *mut u8, args[2], args[3], args[4] as *mut SockAddr, args[5] as *mut u32),
SYS_SENDTO => sys_sendto(
args[0],
args[1] as *const u8,
args[2],
args[3],
args[4] as *const SockAddr,
args[5],
),
SYS_RECVFROM => sys_recvfrom(
args[0],
args[1] as *mut u8,
args[2],
args[3],
args[4] as *mut SockAddr,
args[5] as *mut u32,
),
// SYS_SENDMSG => sys_sendmsg(),
// SYS_RECVMSG => sys_recvmsg(),
SYS_SHUTDOWN => sys_shutdown(args[0], args[1]),
@ -108,9 +120,27 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
SYS_GETSOCKNAME => sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_GETPEERNAME => sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_SETSOCKOPT => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
SYS_GETSOCKOPT => sys_getsockopt(args[0], args[1], args[2], args[3] as *mut u8, args[4] as *mut u32),
SYS_CLONE => sys_clone(args[0], args[1], args[2] as *mut u32, args[3] as *mut u32, args[4], tf),
SYS_EXECVE => sys_exec(args[0] as *const u8, args[1] as *const *const u8, args[2] as *const *const u8, tf),
SYS_GETSOCKOPT => sys_getsockopt(
args[0],
args[1],
args[2],
args[3] as *mut u8,
args[4] as *mut u32,
),
SYS_CLONE => sys_clone(
args[0],
args[1],
args[2] as *mut u32,
args[3] as *mut u32,
args[4],
tf,
),
SYS_EXECVE => sys_exec(
args[0] as *const u8,
args[1] as *const *const u8,
args[2] as *const *const u8,
tf,
),
// 60
SYS_EXIT => sys_exit(args[0] as usize),
SYS_WAIT4 => sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4
@ -192,9 +222,19 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
warn!("umount2 is unimplemented");
Err(SysError::EACCES)
}
SYS_REBOOT => sys_reboot(args[0] as u32, args[1] as u32, args[2] as u32, args[3] as *const u8),
SYS_REBOOT => sys_reboot(
args[0] as u32,
args[1] as u32,
args[2] as u32,
args[3] as *const u8,
),
SYS_GETTID => sys_gettid(),
SYS_FUTEX => sys_futex(args[0], args[1] as u32, args[2] as i32, args[3] as *const TimeSpec),
SYS_FUTEX => sys_futex(
args[0],
args[1] as u32,
args[2] as i32,
args[3] as *const TimeSpec,
),
SYS_SCHED_GETAFFINITY => sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
SYS_GETDENTS64 => sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
SYS_SET_TID_ADDRESS => {
@ -210,7 +250,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
SYS_FCHOWNAT => {
warn!("sys_fchownat is unimplemented");
Ok(0)
},
}
SYS_NEWFSTATAT => sys_stat(args[1] as *const u8, args[2] as *mut Stat), // TODO: handle `dfd`, `flag`
SYS_UNLINKAT => sys_unlink(args[1] as *const u8), // TODO: handle `dfd`, `flag`
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`
@ -253,7 +293,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
};
if !pid.is_init() {
// we trust pid 0 process
debug!("{}:{}:{} syscall id {} ret with {:x?}", cid, pid, tid, id, ret);
debug!(
"{}:{}:{} syscall id {} ret with {:x?}",
cid, pid, tid, id, ret
);
}
match ret {
Ok(code) => code as isize,
@ -270,7 +313,13 @@ fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<Sys
SYS_POLL => sys_poll(args[0] as *mut PollFd, args[1], args[2]),
SYS_ACCESS => sys_access(args[0] as *const u8, args[1]),
SYS_PIPE => sys_pipe(args[0] as *mut u32),
SYS_SELECT => sys_select(args[0], args[1] as *mut u32, args[2] as *mut u32, args[3] as *mut u32, args[4] as *const TimeVal),
SYS_SELECT => sys_select(
args[0],
args[1] as *mut u32,
args[2] as *mut u32,
args[3] as *mut u32,
args[4] as *const TimeVal,
),
SYS_DUP2 => sys_dup2(args[0], args[1]),
// SYS_PAUSE => sys_pause(),
SYS_FORK => sys_fork(tf),
@ -363,7 +412,9 @@ pub enum SysError {
impl fmt::Display for SysError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::SysError::*;
write!(f, "{}",
write!(
f,
"{}",
match self {
EPERM => "Operation not permitted",
ENOENT => "No such file or directory",
@ -424,7 +475,6 @@ impl From<VMError> for SysError {
}
}
const SPIN_WAIT_TIMES: usize = 100;
pub fn spin_and_wait<T>(condvars: &[&Condvar], mut action: impl FnMut() -> Option<T>) -> T {
@ -440,4 +490,3 @@ pub fn spin_and_wait<T>(condvars: &[&Condvar], mut action: impl FnMut() -> Optio
Condvar::wait_any(&condvars);
}
}

@ -16,9 +16,18 @@ pub fn sys_fork(tf: &TrapFrame) -> SysResult {
/// and thread pointer will be set to `newtls`.
/// The child tid will be stored at both `parent_tid` and `child_tid`.
/// This is partially implemented for musl only.
pub fn sys_clone(flags: usize, newsp: usize, parent_tid: *mut u32, child_tid: *mut u32, newtls: usize, tf: &TrapFrame) -> SysResult {
info!("clone: flags: {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
flags, newsp, parent_tid, child_tid, newtls);
pub fn sys_clone(
flags: usize,
newsp: usize,
parent_tid: *mut u32,
child_tid: *mut u32,
newtls: usize,
tf: &TrapFrame,
) -> SysResult {
info!(
"clone: flags: {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
flags, newsp, parent_tid, child_tid, newtls
);
if flags == 0x4111 {
warn!("sys_clone is calling sys_fork instead, ignoring other args");
return sys_fork(tf);
@ -64,41 +73,61 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
let mut proc = process();
// check child_exit_code
let find = match target {
WaitFor::AnyChild => proc.child_exit_code
.iter().next().map(|(&pid, &code)| (pid, code)),
WaitFor::Pid(pid) => proc.child_exit_code
.get(&pid).map(|&code| (pid, code)),
WaitFor::AnyChild => proc
.child_exit_code
.iter()
.next()
.map(|(&pid, &code)| (pid, code)),
WaitFor::Pid(pid) => proc.child_exit_code.get(&pid).map(|&code| (pid, code)),
};
// if found, return
if let Some((pid, exit_code)) = find {
proc.child_exit_code.remove(&pid);
if !wstatus.is_null() {
unsafe { wstatus.write(exit_code as i32); }
unsafe {
wstatus.write(exit_code as i32);
}
}
return Ok(pid);
}
// if not, check pid
let children: Vec<_> = proc.children.iter()
let children: Vec<_> = proc
.children
.iter()
.filter_map(|weak| weak.upgrade())
.collect();
let invalid = match target {
WaitFor::AnyChild => children.len() == 0,
WaitFor::Pid(pid) => children.iter().find(|p| p.lock().pid.get() == pid).is_none(),
WaitFor::Pid(pid) => children
.iter()
.find(|p| p.lock().pid.get() == pid)
.is_none(),
};
if invalid {
return Err(SysError::ECHILD);
}
info!("wait: thread {} -> {:?}, sleep", thread::current().id(), target);
info!(
"wait: thread {} -> {:?}, sleep",
thread::current().id(),
target
);
let condvar = proc.child_exit.clone();
drop(proc); // must release lock of current process
condvar._wait();
}
}
pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8, tf: &mut TrapFrame) -> SysResult {
pub fn sys_exec(
name: *const u8,
argv: *const *const u8,
envp: *const *const u8,
tf: &mut TrapFrame,
) -> SysResult {
info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp);
let proc = process();
let _name = if name.is_null() { String::from("") } else {
let _name = if name.is_null() {
String::from("")
} else {
unsafe { proc.vm.check_and_clone_cstr(name)? }
};
@ -129,7 +158,9 @@ pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8,
thread.proc.lock().clone_for_exec(&proc);
// Activate new page table
unsafe { thread.proc.lock().vm.activate(); }
unsafe {
thread.proc.lock().vm.activate();
}
// Modify the TrapFrame
*tf = unsafe { thread.context.get_init_tf() };
@ -148,7 +179,12 @@ pub fn sys_yield() -> SysResult {
/// Kill the process
pub fn sys_kill(pid: usize, sig: usize) -> SysResult {
info!("kill: {} killed: {} with sig {}", thread::current().id(), pid, sig);
info!(
"kill: {} killed: {} with sig {}",
thread::current().id(),
pid,
sig
);
let current_pid = process().pid.get().clone();
if current_pid == pid {
// killing myself
@ -223,7 +259,9 @@ pub fn sys_exit(exit_code: usize) -> ! {
// it has memory access so we can't move it to Thread::drop?
let clear_child_tid = current_thread().clear_child_tid;
if clear_child_tid != 0 {
unsafe { (clear_child_tid as *mut u32).write(0); }
unsafe {
(clear_child_tid as *mut u32).write(0);
}
let queue = process().get_futex(clear_child_tid);
queue.notify_one();
}

@ -116,7 +116,7 @@ pub fn sys_time(time: *mut u64) -> SysResult {
#[repr(C)]
pub struct RUsage {
utime: TimeVal,
stime: TimeVal
stime: TimeVal,
}
pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
@ -136,10 +136,8 @@ pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
stime: TimeVal {
sec: usec / USEC_PER_SEC,
usec: usec % USEC_PER_SEC,
}
};
unsafe {
*rusage = new_rusage
},
};
unsafe { *rusage = new_rusage };
Ok(0)
}

@ -1,6 +1,6 @@
use crate::process::*;
use crate::arch::interrupt::TrapFrame;
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::process::*;
use log::*;
pub static mut TICK: usize = 0;
@ -11,7 +11,9 @@ pub fn uptime_msec() -> usize {
pub fn timer() {
if cpu::id() == 0 {
unsafe { TICK += 1; }
unsafe {
TICK += 1;
}
}
processor().tick();
}

@ -1,9 +1,9 @@
//! ANSI escape sequences parser
//! (ref: https://en.wikipedia.org/wiki/ANSI_escape_code)
use heapless::Vec;
use heapless::consts::U8;
use super::color::ConsoleColor;
use heapless::consts::U8;
use heapless::Vec;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
@ -44,7 +44,9 @@ impl CharacterAttribute {
27 => self.reverse = false,
29 => self.strikethrough = false,
30...37 | 90...97 => self.foreground = ConsoleColor::from_console_code(code).unwrap(),
40...47 | 100...107 => self.background = ConsoleColor::from_console_code(code - 10).unwrap(),
40...47 | 100...107 => {
self.background = ConsoleColor::from_console_code(code - 10).unwrap()
}
_ => { /* unimplemented!() */ }
}
}

@ -3,7 +3,7 @@ pub mod escape_parser;
/// Convert C string to Rust string
pub unsafe fn from_cstr(s: *const u8) -> &'static str {
use core::{str, slice};
use core::{slice, str};
let len = (0usize..).find(|&i| *s.add(i) == 0).unwrap();
str::from_utf8(slice::from_raw_parts(s, len)).unwrap()
}

Loading…
Cancel
Save