Compare commits

...

11 Commits

20 changed files with 336 additions and 95 deletions

View File

@ -1,5 +1,5 @@
use crate::entry::HART_ID; use crate::entry::HART_ID;
use crate::objects::tcb::TcbObject; use crate::objects::*;
use crate::plat::console::CONSOLE; use crate::plat::console::CONSOLE;
use crate::plat::timer::{Timer, TimerOps}; use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapContextOps, TrapOps}; use crate::plat::trap::{Trap, TrapContextOps, TrapOps};

View File

@ -1,6 +1,6 @@
use super::{alloc_page, install_pagetable, map_range, RAM_ALLOCATOR}; use super::{alloc_page, install_pagetable, map_range, RAM_ALLOCATOR};
use crate::{arch::layout::*, vspace::*}; use crate::{arch::layout::*, vspace::*};
use log::{debug, info}; use log::{debug, info, trace};
use spin::Mutex; use spin::Mutex;
use utils::{addr::*, size::*}; use utils::{addr::*, size::*};
@ -32,14 +32,14 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
// Exclude memory occupied by UEFI // Exclude memory occupied by UEFI
for region in fdt.memory_reservations() { for region in fdt.memory_reservations() {
debug!( debug!(
"Reserving memory:\tstart: {:x?}, size: {:x?}", "Reserving UEFI memory:\tstart: {:x?}, size: {:x?}",
region.address(), region.address(),
region.size() region.size()
); );
mem.reserve(PhysAddr::from(region.address()), align_up(region.size(), PAGE_SIZE)); mem.reserve(PhysAddr::from(region.address()), align_up(region.size(), PAGE_SIZE));
} }
// Exclude memory occupied by OpenSBI // Exclude memory in /reserved-memory
let reserved_memory = fdt let reserved_memory = fdt
.find_node("/reserved-memory") .find_node("/reserved-memory")
.map(|node| node.children()) .map(|node| node.children())
@ -47,7 +47,7 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
for child in reserved_memory { for child in reserved_memory {
let region = child.reg().unwrap().next().unwrap(); let region = child.reg().unwrap().next().unwrap();
debug!( debug!(
"Reserving memory:\tstart: {:x?}, size: {:x?}", "Reserving memory marked in /reserved-memory:\tstart: {:x?}, size: {:x?}",
region.starting_address, region.size region.starting_address, region.size
); );
mem.reserve( mem.reserve(
@ -56,6 +56,19 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
); );
} }
// Exclude memory in mmode_resv
fdt.all_nodes().filter(|n| n.name.starts_with("mmode_resv")).for_each(|node| {
let region = node.reg().unwrap().next().unwrap();
debug!(
"Reserving memory marked in /mmode_resv:\tstart: {:x?}, size: {:x?}",
region.starting_address, region.size
);
mem.reserve(
PhysAddr::from(region.starting_address),
align_up(region.size.unwrap(), PAGE_SIZE),
);
});
// Exclude kernel memory // Exclude kernel memory
let kernel_start = kernel_virt_to_phys(KERNEL_START.as_virt_addr()); let kernel_start = kernel_virt_to_phys(KERNEL_START.as_virt_addr());
let kernel_end = kernel_virt_to_phys(KERNEL_END.as_virt_addr()).align_up(PAGE_SIZE); let kernel_end = kernel_virt_to_phys(KERNEL_END.as_virt_addr()).align_up(PAGE_SIZE);
@ -65,8 +78,30 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
// Exclude FDT table // Exclude FDT table
let fdt_addr = PhysAddr::from(fdt_addr); let fdt_addr = PhysAddr::from(fdt_addr);
let fdt_size = align_up(fdt.total_size(), PAGE_SIZE); let fdt_size = align_up(fdt.total_size(), PAGE_SIZE);
debug!("Reserving FDT memory:\tstart: {:x?}, size: {:x?}", fdt_addr, fdt_size); debug!("Reserving FDT table memory:\tstart: {:x?}, size: {:#x?}", fdt_addr, fdt_size);
mem.reserve(fdt_addr, fdt_size); mem.reserve(fdt_addr, fdt_size);
// Exclude memory for initrd
if let Some(chosen) = fdt.find_node("/chosen") {
let initrd_start = chosen
.properties()
.find(|n| n.name == "linux,initrd-start")
.and_then(|prop| prop.as_usize());
let initrd_end = chosen
.properties()
.find(|n| n.name == "linux,initrd-end")
.and_then(|prop| prop.as_usize());
if let (Some(initrd_start), Some(initrd_end)) = (initrd_start, initrd_end) {
let start = PhysAddr::from(initrd_start);
let size = align_up(initrd_end - initrd_start, PAGE_SIZE);
debug!("Reserving initrd memory:\tstart: {:x?}, size: {:#x?}", start, size);
mem.reserve(start, size);
}
}
trace!("Memory setup complete, memory info:\n{:#x?}", mem);
} }
pub unsafe fn setup_kernel_paging() { pub unsafe fn setup_kernel_paging() {
@ -107,7 +142,7 @@ pub unsafe fn setup_kernel_paging() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
let count = ALLOC_COUNT.load(core::sync::atomic::Ordering::Acquire); let count = ALLOC_COUNT.load(core::sync::atomic::Ordering::Acquire);
log::trace!("Kernel page table size: {:?}", count); trace!("Kernel page table size: {:?}", count);
assert!(KERNEL_PAGETABLE_SIZE == count, "Kernel page table size mismatch"); assert!(KERNEL_PAGETABLE_SIZE == count, "Kernel page table size mismatch");
} }

View File

@ -90,7 +90,7 @@ fn page_table_mode() -> riscv::register::satp::Mode {
} }
pub unsafe fn install_pagetable(pt: &Table<Level0>) { pub unsafe fn install_pagetable(pt: &Table<Level0>) {
let root_pt = PhysAddr::from(pt.entries as *const _ as *const usize); let root_pt = PhysAddr::from(pt.entries.as_ptr());
riscv::register::satp::set(page_table_mode(), 0, root_pt.extract_ppn()); riscv::register::satp::set(page_table_mode(), 0, root_pt.extract_ppn());
riscv::asm::sfence_vma_all(); riscv::asm::sfence_vma_all();

View File

@ -1,5 +1,6 @@
use crate::objects::null::NullCap; use crate::objects::*;
use core::cell::Cell; use core::cell::Cell;
use core::fmt::{write, Debug};
use uapi::cap::ObjectType; use uapi::cap::ObjectType;
use utils::addr::PhysAddr; use utils::addr::PhysAddr;
use utils::{ use utils::{
@ -20,8 +21,6 @@ pub struct RawCap {
pub ptr: PhysAddr, pub ptr: PhysAddr,
/// cap_type: every capability links to one specific object /// cap_type: every capability links to one specific object
pub cap_type: ObjectType, pub cap_type: ObjectType,
/// _padding: padding to align the size of RawCap to power of 2
pub _padding: [usize; 2],
} }
impl RawCap { impl RawCap {
@ -30,7 +29,6 @@ impl RawCap {
args: [arg0, arg1], args: [arg0, arg1],
ptr, ptr,
cap_type, cap_type,
_padding: [0, 0],
} }
} }
} }
@ -42,8 +40,6 @@ pub struct CapEntry {
LinkHelperImpl!(CapEntry: link); LinkHelperImpl!(CapEntry: link);
const_assert_eq!(core::mem::size_of::<CapEntry>(), ObjectType::CNode.size(0));
impl CapEntry { impl CapEntry {
pub fn new(cap: RawCap) -> Self { pub fn new(cap: RawCap) -> Self {
Self { Self {
@ -71,3 +67,18 @@ impl From<RawCap> for CapEntry {
Self::new(value) Self::new(value)
} }
} }
impl Debug for CapEntry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let cap_type = self.cap.get().cap_type;
match cap_type {
ObjectType::CNode => write!(f, "{:?}", CNodeCap::try_from(self)),
ObjectType::Frame => write!(f, "{:?}", FrameCap::try_from(self)),
ObjectType::Null => write!(f, "{:?}", NullCap::try_from(self)),
ObjectType::PageTable => write!(f, "{:?}", TableCap::try_from(self)),
ObjectType::TCB => write!(f, "{:?}", TcbCap::try_from(self)),
ObjectType::Untyped => write!(f, "{:?}", UntypedCap::try_from(self)),
_ => write!(f, "UnknownCap"),
}
}
}

View File

@ -3,14 +3,17 @@ use super::{
Cap, KernelObject, Cap, KernelObject,
}; };
use crate::arch::layout::mmap_phys_to_virt; use crate::arch::layout::mmap_phys_to_virt;
use uapi::{cap::ObjectType, error::CapFault}; use core::fmt::Debug;
use uapi::{cap::ObjectType, fault::LookupFailure};
use utils::addr::{AddressOps, PhysAddr}; use utils::addr::{AddressOps, PhysAddr};
use utils::MASK; use utils::MASK;
/// CNodeObject is a array of Capabilities (`RawCap`) /// CNodeObject is a array of Capabilities (`CapEntry`)
/// The size of the array is stored in CNodeCap /// The size of the array is stored in CNodeCap
pub type CNodeObject = [CapEntry]; pub type CNodeObject = [CapEntry];
const_assert!(core::mem::size_of::<CapEntry>() <= ObjectType::CNode.size(0));
impl KernelObject for CNodeObject { impl KernelObject for CNodeObject {
const OBJ_TYPE: ObjectType = ObjectType::CNode; const OBJ_TYPE: ObjectType = ObjectType::CNode;
} }
@ -22,7 +25,7 @@ impl KernelObject for CNodeObject {
* > args[1]: guard * > args[1]: guard
* *
* in our implementation, CNodeCap layout: * in our implementation, CNodeCap layout:
* > args[0]: [guard_size, radix] * > args[0]: [guard_bits, radix_bits]
* > args[1]: guard * > args[1]: guard
* > ptr: cnode_ptr * > ptr: cnode_ptr
* > cap_type: cap_tag * > cap_type: cap_tag
@ -38,9 +41,9 @@ impl<'a> CNodeCap<'a> {
const RADIX_MASK: usize = MASK!(Self::RADIX_BITS); const RADIX_MASK: usize = MASK!(Self::RADIX_BITS);
const RADIX_OFFSET: usize = 0; const RADIX_OFFSET: usize = 0;
pub fn mint(radix: usize, guard_size: usize, guard: usize, ptr: PhysAddr) -> RawCap { pub fn mint(radix_bits: usize, guard_bits: usize, guard: usize, ptr: PhysAddr) -> RawCap {
let arg0 = ((radix & Self::RADIX_MASK) << Self::RADIX_OFFSET) let arg0 = ((radix_bits & Self::RADIX_MASK) << Self::RADIX_OFFSET)
| ((guard_size & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET); | ((guard_bits & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET);
let arg1 = guard; let arg1 = guard;
let cap: RawCap = RawCap::new(arg0, arg1, ptr, ObjectType::CNode); let cap: RawCap = RawCap::new(arg0, arg1, ptr, ObjectType::CNode);
@ -55,11 +58,11 @@ impl<'a> CNodeCap<'a> {
cap cap
} }
fn radix(&self) -> usize { fn radix_bits(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK (self.cte.cap.get().args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK
} }
fn guard_size(&self) -> usize { fn guard_bits(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK (self.cte.cap.get().args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK
} }
@ -72,7 +75,7 @@ impl<'a> CNodeCap<'a> {
// Return the limited size of the CNode, Rust will help us to check the boundary :) // Return the limited size of the CNode, Rust will help us to check the boundary :)
// > the kernel then uses the next most-significant `radix` bits of the // > the kernel then uses the next most-significant `radix` bits of the
// > capability address as an `index` into the CNode to which the CNode capability refers // > capability address as an `index` into the CNode to which the CNode capability refers
1 << self.radix() 1 << self.radix_bits()
} }
pub fn as_object(&self) -> &CNodeObject { pub fn as_object(&self) -> &CNodeObject {
@ -89,20 +92,20 @@ impl<'a> CNodeCap<'a> {
} }
} }
pub fn resolve_address_bits(&self, cap_ptr: usize, n_bits: usize) -> Result<&CapEntry, CapFault> { pub fn resolve_address_bits(&self, cap_ptr: usize, n_bits: usize) -> Result<&CapEntry, LookupFailure> {
let mut bits_remaining = n_bits; let mut bits_remaining = n_bits;
let mut slot = self.cte; let mut slot = self.cte;
while let Ok(cnode) = CNodeCap::try_from(slot) { while let Ok(cnode) = CNodeCap::try_from(slot) {
let radix_bits = cnode.radix(); let radix_bits = cnode.radix_bits();
let guard_bits = cnode.guard_size(); let guard_bits = cnode.guard_bits();
let level_bits = radix_bits + guard_bits; let level_bits = radix_bits + guard_bits;
let cap_guard = cnode.guard(); let cap_guard = cnode.guard();
assert_ne!(level_bits, 0); assert_ne!(level_bits, 0);
if level_bits > bits_remaining { if level_bits > bits_remaining {
return Err(CapFault::DepthMismatch { return Err(LookupFailure::DepthMismatch {
bits_found: level_bits, bits_found: level_bits,
bits_left: bits_remaining, bits_left: bits_remaining,
}); });
@ -110,7 +113,7 @@ impl<'a> CNodeCap<'a> {
let get_guard = || (cap_ptr >> (bits_remaining - guard_bits)) & MASK!(guard_bits); let get_guard = || (cap_ptr >> (bits_remaining - guard_bits)) & MASK!(guard_bits);
if guard_bits > bits_remaining || get_guard() != cap_guard { if guard_bits > bits_remaining || get_guard() != cap_guard {
return Err(CapFault::GuardMismatch { return Err(LookupFailure::GuardMismatch {
bits_left: bits_remaining, bits_left: bits_remaining,
guard_found: cap_guard, guard_found: cap_guard,
guard_size: guard_bits, guard_size: guard_bits,
@ -128,28 +131,39 @@ impl<'a> CNodeCap<'a> {
} }
if CNodeCap::try_from(slot).is_err() { if CNodeCap::try_from(slot).is_err() {
return Err(CapFault::InvalidRoot); return Err(LookupFailure::InvalidRoot);
} }
Ok(slot) Ok(slot)
} }
} }
impl Debug for CNodeCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("CNodeCap")
.field("radix_bits", &self.radix_bits())
.field("guard_bits", &self.guard_bits())
.field("guard", &self.guard())
.field("length", &self.length())
.field("ptr", &self.cte.cap.get().ptr)
.finish()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::arch::vspace::RAM_ALLOCATOR; use crate::arch::vspace::RAM_ALLOCATOR;
use crate::objects::cap::CapEntry; use crate::objects::*;
use crate::objects::null::NullCap;
use core::alloc::Layout; use core::alloc::Layout;
use log::info; use log::info;
#[test_case] #[test_case]
fn test_cnode_resolve() { fn test_cnode_resolve() {
let create_cnode = |radix: usize, guard_size: usize, guard: usize| { let create_cnode = |radix_bits: usize, guard_bits: usize, guard: usize| {
let size = ObjectType::CNode.size(radix); let size = ObjectType::CNode.size(radix_bits);
let layout = Layout::from_size_align(size, 1).unwrap(); let layout = Layout::from_size_align(size, 1).unwrap();
let ptr = RAM_ALLOCATOR.lock().alloc(layout).unwrap(); let ptr = RAM_ALLOCATOR.lock().alloc(layout).unwrap();
let raw = CNodeCap::mint(radix, guard_size, guard, ptr); let raw = CNodeCap::mint(radix_bits, guard_bits, guard, ptr);
CapEntry::new(raw) CapEntry::new(raw)
}; };
@ -228,7 +242,7 @@ mod tests {
info!("Testing invalid depth (1)"); info!("Testing invalid depth (1)");
let result = root.resolve_address_bits(0x96, 8 - 1); let result = root.resolve_address_bits(0x96, 8 - 1);
match result { match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => { Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 8); assert_eq!(bits_found, 8);
assert_eq!(bits_left, 7); assert_eq!(bits_left, 7);
}, },
@ -241,7 +255,7 @@ mod tests {
info!("Testing invalid depth (2)"); info!("Testing invalid depth (2)");
let result = root.resolve_address_bits(0x4b31 >> 1, 15 - 1); let result = root.resolve_address_bits(0x4b31 >> 1, 15 - 1);
match result { match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => { Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 7); assert_eq!(bits_found, 7);
assert_eq!(bits_left, 6); assert_eq!(bits_left, 6);
}, },
@ -256,7 +270,7 @@ mod tests {
info!("Testing guard mismatch"); info!("Testing guard mismatch");
let result = root.resolve_address_bits(0x4b71, 15); let result = root.resolve_address_bits(0x4b71, 15);
match result { match result {
Err(CapFault::GuardMismatch { Err(LookupFailure::GuardMismatch {
bits_left, bits_left,
guard_found, guard_found,
guard_size, guard_size,
@ -274,7 +288,7 @@ mod tests {
info!("Testing extra bits"); info!("Testing extra bits");
let result = root.resolve_address_bits(0x96 << 1, 8 + 1); let result = root.resolve_address_bits(0x96 << 1, 8 + 1);
match result { match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => { Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 7); assert_eq!(bits_found, 7);
assert_eq!(bits_left, 1); assert_eq!(bits_left, 1);
}, },

View File

@ -4,6 +4,7 @@ use crate::{
objects::cap::CapEntry, objects::cap::CapEntry,
vspace::*, vspace::*,
}; };
use core::fmt::Debug;
use uapi::{ use uapi::{
cap::ObjectType, cap::ObjectType,
error::{SysError, SysResult}, error::{SysError, SysResult},
@ -161,3 +162,16 @@ impl<'a> FrameCap<'a> {
} }
} }
} }
impl Debug for FrameCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FrameCap")
.field("ptr", &self.cte.cap.get().ptr)
.field("size", &self.size())
.field("attr", &self.attr())
.field("is_device", &self.is_device())
.field("mapped_asid", &self.mapped_asid())
.field("mapped_vaddr", &self.mapped_vaddr())
.finish()
}
}

View File

@ -14,7 +14,6 @@
*/ */
use cap::CapEntry;
use core::{marker::PhantomData, ptr::NonNull}; use core::{marker::PhantomData, ptr::NonNull};
use uapi::{ use uapi::{
cap::ObjectType, cap::ObjectType,
@ -29,6 +28,14 @@ pub mod table;
pub mod tcb; pub mod tcb;
pub mod untyped; pub mod untyped;
pub use cap::{CapEntry, RawCap};
pub use cnode::{CNodeCap, CNodeObject};
pub use frame::{FrameCap, FrameObject};
pub use null::{NullCap, NullObject};
pub use table::{TableCap, TableObject};
pub use tcb::{TcbCap, TcbObject};
pub use untyped::{UntypedCap, UntypedObject};
/// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust) /// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust)
/// For the typed objects, we should bound it with an empty traits `KernelObject` /// For the typed objects, we should bound it with an empty traits `KernelObject`
/// And for those objects, at least implement `mint` method and `decodeInvocation` (not enforcing in `KernelObject` for complexity) /// And for those objects, at least implement `mint` method and `decodeInvocation` (not enforcing in `KernelObject` for complexity)

View File

@ -1,5 +1,6 @@
use super::cap::RawCap; use super::cap::RawCap;
use super::{Cap, KernelObject}; use super::{Cap, KernelObject};
use core::fmt::Debug;
use uapi::cap::ObjectType; use uapi::cap::ObjectType;
use utils::addr::PhysAddr; use utils::addr::PhysAddr;
@ -15,3 +16,9 @@ impl<'a> NullCap<'a> {
RawCap::new(0, 0, PhysAddr(0), ObjectType::Null) RawCap::new(0, 0, PhysAddr(0), ObjectType::Null)
} }
} }
impl Debug for NullCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NullCap")
}
}

View File

@ -1,5 +1,6 @@
use super::{cap::RawCap, Cap, KernelObject}; use super::{cap::RawCap, Cap, KernelObject};
use crate::{arch::layout::mmap_phys_to_virt, vspace::*}; use crate::{arch::layout::mmap_phys_to_virt, vspace::*};
use core::fmt::Debug;
use uapi::{ use uapi::{
cap::ObjectType, cap::ObjectType,
error::{SysError, SysResult}, error::{SysError, SysResult},
@ -7,7 +8,7 @@ use uapi::{
use utils::{addr::*, MASK}; use utils::{addr::*, MASK};
/// TableObject is an object that represents a page table /// TableObject is an object that represents a page table
pub struct TableObject([usize]); pub struct TableObject([u8]);
impl KernelObject for TableObject { impl KernelObject for TableObject {
const OBJ_TYPE: ObjectType = ObjectType::PageTable; const OBJ_TYPE: ObjectType = ObjectType::PageTable;
} }
@ -130,3 +131,9 @@ impl<'a> TableCap<'a> {
} }
} }
} }
impl Debug for TableCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TableCap").field("ptr", &self.cte.cap.get().ptr).finish()
}
}

View File

@ -1,5 +1,6 @@
use super::{ use super::{
cap::{CapEntry, RawCap}, cap::{CapEntry, RawCap},
cnode::CNodeCap,
null::NullCap, null::NullCap,
Cap, KernelObject, Cap, KernelObject,
}; };
@ -7,14 +8,15 @@ use crate::{
arch::{layout::mmap_phys_to_virt, trap::TrapContext}, arch::{layout::mmap_phys_to_virt, trap::TrapContext},
plat::trap::TrapContextOps, plat::trap::TrapContextOps,
}; };
use uapi::cap::ObjectType; use core::fmt::Debug;
use uapi::{cap::ObjectType, error::SysResult, fault::Fault, syscall::MessageInfo};
use utils::{ use utils::{
addr::*, addr::*,
linked_list::{Link, LinkHelper}, linked_list::{Link, LinkHelper},
LinkHelperImpl, LinkHelperImpl,
}; };
#[derive(Clone, Copy)] #[derive(Clone, Copy, Debug)]
pub enum ThreadState { pub enum ThreadState {
Inactive, Inactive,
Running, Running,
@ -29,8 +31,11 @@ pub struct TcbObject {
cspace: CapEntry, cspace: CapEntry,
vspace: CapEntry, vspace: CapEntry,
notification: CapEntry,
buffer: CapEntry, // CapFrame
fault: Fault,
fault_handler: CapEntry,
// TODO: add reply, buffer, fault, caller ... priority, dom
state: ThreadState, state: ThreadState,
time_tick: usize, time_tick: usize,
pub link: Link<Self>, pub link: Link<Self>,
@ -38,12 +43,19 @@ pub struct TcbObject {
LinkHelperImpl!(TcbObject:link); LinkHelperImpl!(TcbObject:link);
const_assert_eq!(ObjectType::TCB.size(0), ObjectType::TCB.size(0x42));
const_assert!(core::mem::size_of::<TcbObject>() <= ObjectType::TCB.size(0));
impl TcbObject { impl TcbObject {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
trapframe: TrapContext::default(), trapframe: TrapContext::default(),
cspace: CapEntry::new(NullCap::mint()), cspace: CapEntry::new(NullCap::mint()),
vspace: CapEntry::new(NullCap::mint()), vspace: CapEntry::new(NullCap::mint()),
notification: CapEntry::new(NullCap::mint()),
buffer: CapEntry::new(NullCap::mint()),
fault: Fault::Null,
fault_handler: CapEntry::new(NullCap::mint()),
state: ThreadState::Inactive, state: ThreadState::Inactive,
time_tick: 0, time_tick: 0,
link: Link::default(), link: Link::default(),
@ -55,6 +67,14 @@ impl TcbObject {
self.state = ThreadState::Idle; self.state = ThreadState::Idle;
} }
pub fn state(&self) -> ThreadState {
self.state
}
pub fn set_state(&mut self, state: ThreadState) {
self.state = state;
}
pub fn timetick(&self) -> usize { pub fn timetick(&self) -> usize {
self.time_tick self.time_tick
} }
@ -79,7 +99,19 @@ impl TcbObject {
} }
pub fn handle_syscall(&mut self) { pub fn handle_syscall(&mut self) {
todo!("TcbObject::handle_syscall"); let handle_syscall_inner = || -> SysResult {
let info = MessageInfo::try_from(self.trapframe.get_reg(0))?;
let cspace = CNodeCap::try_from(&self.cspace)?;
let cap_ptr = self.trapframe.get_reg(1);
let cap = cspace.resolve_address_bits(cap_ptr, usize::BITS as usize);
todo!("handle_syscall");
Ok(())
};
handle_syscall_inner().unwrap();
} }
} }
@ -108,3 +140,19 @@ impl<'a> TcbCap<'a> {
} }
} }
} }
impl Debug for TcbCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let obj = self.as_object();
f.debug_struct("TcbCap")
.field("cspace", &obj.cspace)
.field("vspace", &obj.vspace)
.field("notification", &obj.notification)
.field("buffer", &obj.buffer)
.field("fault", &obj.fault)
.field("fault_handler", &obj.fault_handler)
.field("state", &obj.state)
.field("time_tick", &obj.time_tick)
.finish()
}
}

View File

@ -2,6 +2,7 @@ use super::cap::RawCap;
use super::cnode::{CNodeCap, CNodeObject}; use super::cnode::{CNodeCap, CNodeObject};
use super::null::NullCap; use super::null::NullCap;
use super::{Cap, KernelObject}; use super::{Cap, KernelObject};
use core::fmt::Debug;
use uapi::cap::ObjectType; use uapi::cap::ObjectType;
use uapi::error::{SysError, SysResult}; use uapi::error::{SysError, SysResult};
use utils::addr::{align_up, PhysAddr}; use utils::addr::{align_up, PhysAddr};
@ -131,6 +132,17 @@ impl UntypedCap<'_> {
} }
} }
impl Debug for UntypedCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UntypedCap")
.field("free_offset", &self.free_offset())
.field("block_bits", &self.block_bits())
.field("is_device", &self.is_device())
.field("ptr", &self.cte.cap.get().ptr)
.finish()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1,4 +1,4 @@
use crate::objects::tcb::TcbObject; use crate::objects::*;
pub struct Trap; pub struct Trap;

View File

@ -1,4 +1,4 @@
use crate::objects::tcb::TcbObject; use crate::objects::*;
use core::ptr::NonNull; use core::ptr::NonNull;
use log::error; use log::error;
use spin::lazy::Lazy; use spin::lazy::Lazy;
@ -50,6 +50,7 @@ impl Scheduler {
} }
// put to the end of the queue // put to the end of the queue
// todo: only move blocked and time expired threads to the end
next.link.detach(); next.link.detach();
self.head.prepend(next); self.head.prepend(next);
} }

View File

@ -3,17 +3,21 @@ use core::cmp::min;
use utils::addr::{AddressOps, PhysAddr}; use utils::addr::{AddressOps, PhysAddr};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct Block { pub struct Block {
start: PhysAddr, start: PhysAddr,
size: usize, size: usize,
} }
impl Block { impl Block {
fn start_addr(&self) -> PhysAddr { pub fn start_addr(&self) -> PhysAddr {
self.start self.start
} }
fn end_addr(&self) -> PhysAddr { pub fn size(&self) -> usize {
self.size
}
pub fn end_addr(&self) -> PhysAddr {
self.start + self.size self.start + self.size
} }
@ -137,6 +141,14 @@ impl<const N: usize> RamBlock<N> {
} }
} }
} }
pub fn blocks(&self) -> &[Option<Block>; N] {
&self.blocks
}
pub fn blocks_mut(&mut self) -> &mut [Option<Block>; N] {
&mut self.blocks
}
} }
impl<const N: usize> Default for RamBlock<N> { impl<const N: usize> Default for RamBlock<N> {

View File

@ -14,6 +14,15 @@ pub fn align_down(addr: usize, align: usize) -> usize {
addr & !(align - 1) addr & !(align - 1)
} }
#[inline(always)]
pub fn is_aligned(addr: usize, align: usize) -> bool {
if align.is_power_of_two() {
addr & (align - 1) == 0
} else {
false
}
}
#[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)] #[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct PhysAddr(pub usize); pub struct PhysAddr(pub usize);
@ -37,11 +46,7 @@ pub trait AddressOps: Copy + Clone + Default + Eq + Ord + PartialOrd + PartialEq
where T: Into<usize>; where T: Into<usize>;
fn is_aligned<T>(&self, align: T) -> bool fn is_aligned<T>(&self, align: T) -> bool
where T: Into<usize> + Copy { where T: Into<usize> + Copy {
if align.into().is_power_of_two() { is_aligned(self.as_usize(), align.into())
self.as_usize() & (align.into() - 1) == 0
} else {
false
}
} }
} }
@ -219,6 +224,19 @@ impl From<usize> for PhysAddr {
} }
} }
impl From<u32> for PhysAddr {
fn from(addr: u32) -> Self {
PhysAddr(addr as usize)
}
}
#[cfg(target_pointer_width = "64")]
impl From<u64> for PhysAddr {
fn from(addr: u64) -> Self {
PhysAddr(addr as usize)
}
}
impl From<NonZeroUsize> for PhysAddr { impl From<NonZeroUsize> for PhysAddr {
fn from(addr: NonZeroUsize) -> Self { fn from(addr: NonZeroUsize) -> Self {
PhysAddr(addr.get()) PhysAddr(addr.get())
@ -261,6 +279,19 @@ impl From<usize> for VirtAddr {
} }
} }
impl From<u32> for VirtAddr {
fn from(addr: u32) -> Self {
VirtAddr(addr as usize)
}
}
#[cfg(target_pointer_width = "64")]
impl From<u64> for VirtAddr {
fn from(addr: u64) -> Self {
VirtAddr(addr as usize)
}
}
impl From<NonZeroUsize> for VirtAddr { impl From<NonZeroUsize> for VirtAddr {
fn from(addr: NonZeroUsize) -> Self { fn from(addr: NonZeroUsize) -> Self {
VirtAddr(addr.get()) VirtAddr(addr.get())

View File

@ -3,14 +3,13 @@ pub enum ObjectType {
Null = 0, Null = 0,
CNode = 1, CNode = 1,
TCB = 2, TCB = 2,
SchedCtx = 3, Endpoint = 3,
Endpoint = 4, Reply = 4,
Reply = 5, Notification = 5,
Notification = 6, Frame = 6,
Frame = 7, PageTable = 7,
PageTable = 8, Interrupt = 8,
Interrupt = 9, Untyped = 9,
Untyped = 10,
} }
impl Default for ObjectType { impl Default for ObjectType {
@ -20,7 +19,8 @@ impl Default for ObjectType {
} }
impl ObjectType { impl ObjectType {
const CNODE_BITS: usize = 6; const CNODE_BITS: usize = 6; // 48 bytes
const TCB_BITS: usize = 10; // 672 bytes
pub const fn size(&self, user_obj_bits: usize) -> usize { pub const fn size(&self, user_obj_bits: usize) -> usize {
1 << self.bits(user_obj_bits) 1 << self.bits(user_obj_bits)
@ -29,15 +29,14 @@ impl ObjectType {
pub const fn bits(&self, user_obj_bits: usize) -> usize { pub const fn bits(&self, user_obj_bits: usize) -> usize {
#![rustfmt::skip] #![rustfmt::skip]
match self { match self {
ObjectType::Null => 0, // TODO: fill it! ObjectType::Null => 0,
ObjectType::CNode => Self::CNODE_BITS + user_obj_bits, ObjectType::CNode => Self::CNODE_BITS + user_obj_bits,
ObjectType::TCB => 0, // TODO: fill it! ObjectType::TCB => Self::TCB_BITS,
ObjectType::SchedCtx => 0, // TODO: fill it!
ObjectType::Endpoint => 0, // TODO: fill it! ObjectType::Endpoint => 0, // TODO: fill it!
ObjectType::Reply => 0, // TODO: fill it! ObjectType::Reply => 0, // TODO: fill it!
ObjectType::Notification => 0, // TODO: fill it! ObjectType::Notification => 0, // TODO: fill it!
ObjectType::Frame => 0, // TODO: fill it! ObjectType::Frame => user_obj_bits,
ObjectType::PageTable => 0, // TODO: fill it! ObjectType::PageTable => user_obj_bits, // arch dependent page table size
ObjectType::Interrupt => 0, // TODO: fill it! ObjectType::Interrupt => 0, // TODO: fill it!
ObjectType::Untyped => user_obj_bits, ObjectType::Untyped => user_obj_bits,
} }

View File

@ -1,20 +1,3 @@
#[derive(Clone, Copy, Debug)]
pub enum CapFault {
InvalidRoot,
MissingCapability {
bits_left: usize,
},
DepthMismatch {
bits_found: usize,
bits_left: usize,
},
GuardMismatch {
bits_left: usize,
guard_found: usize,
guard_size: usize,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)] #[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
pub enum SysError { pub enum SysError {
Ok, Ok,

52
uapi/src/fault.rs Normal file
View File

@ -0,0 +1,52 @@
use utils::addr::VirtAddr;
#[derive(Clone, Copy, Debug)]
pub enum LookupFailure {
InvalidRoot,
MissingCapability {
bits_left: usize,
},
DepthMismatch {
bits_found: usize,
bits_left: usize,
},
GuardMismatch {
bits_left: usize,
guard_found: usize,
guard_size: usize,
},
}
#[derive(Clone, Copy, Debug)]
pub struct CapFault {
address: usize,
in_receive_phase: bool,
lookup_failure: LookupFailure,
}
#[derive(Clone, Copy, Debug)]
pub struct UnknownSyscall {
fault_ip: VirtAddr,
syscall: usize,
}
#[derive(Clone, Copy, Debug)]
pub struct UserException {
fault_ip: VirtAddr,
number: usize,
code: usize,
}
#[derive(Clone, Copy, Debug)]
pub struct VMFault {
ip: VirtAddr,
}
#[derive(Clone, Copy, Debug)]
pub enum Fault {
Null,
CapFault(CapFault),
UnknownSyscall(UnknownSyscall),
UserException(UserException),
VMFault(VMFault),
}

View File

@ -6,5 +6,6 @@ extern crate num_derive;
pub mod cap; pub mod cap;
pub mod error; pub mod error;
pub mod fault;
pub mod syscall; pub mod syscall;
pub mod vspace; pub mod vspace;

View File

@ -8,6 +8,13 @@ use crate::error::SysError;
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)] #[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
pub enum Syscall { pub enum Syscall {
Invalid = 0, Invalid = 0,
DebugPutChar = 1,
Yield = 2,
Identify = 3,
Send = 4,
Recv = 5,
Call = 6,
Reply = 7,
} }
/* in vanilla seL4, MessageInfo layout: /* in vanilla seL4, MessageInfo layout:
@ -22,7 +29,7 @@ pub enum Syscall {
* > Call: * > Call:
* > > [a0]: MessageInfo * > > [a0]: MessageInfo
* > > [a1]: Capability Pointer * > > [a1]: Capability Pointer
* > > [a3..a7]: extra arguments * > > [a2..a7]: extra arguments
* > > length = (a0..a?).len() * > > length = (a0..a?).len()
* > Reply: * > Reply:
* > TODO: figure out how vanilla seL4 handle reply * > TODO: figure out how vanilla seL4 handle reply