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::objects::tcb::TcbObject;
use crate::objects::*;
use crate::plat::console::CONSOLE;
use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapContextOps, TrapOps};

View File

@ -1,6 +1,6 @@
use super::{alloc_page, install_pagetable, map_range, RAM_ALLOCATOR};
use crate::{arch::layout::*, vspace::*};
use log::{debug, info};
use log::{debug, info, trace};
use spin::Mutex;
use utils::{addr::*, size::*};
@ -32,14 +32,14 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
// Exclude memory occupied by UEFI
for region in fdt.memory_reservations() {
debug!(
"Reserving memory:\tstart: {:x?}, size: {:x?}",
"Reserving UEFI memory:\tstart: {:x?}, size: {:x?}",
region.address(),
region.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
.find_node("/reserved-memory")
.map(|node| node.children())
@ -47,7 +47,7 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
for child in reserved_memory {
let region = child.reg().unwrap().next().unwrap();
debug!(
"Reserving memory:\tstart: {:x?}, size: {:x?}",
"Reserving memory marked in /reserved-memory:\tstart: {:x?}, size: {:x?}",
region.starting_address, region.size
);
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
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);
@ -65,8 +78,30 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
// Exclude FDT table
let fdt_addr = PhysAddr::from(fdt_addr);
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);
// 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() {
@ -107,7 +142,7 @@ pub unsafe fn setup_kernel_paging() {
#[cfg(debug_assertions)]
{
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");
}

View File

@ -90,7 +90,7 @@ fn page_table_mode() -> riscv::register::satp::Mode {
}
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::asm::sfence_vma_all();

View File

@ -1,5 +1,6 @@
use crate::objects::null::NullCap;
use crate::objects::*;
use core::cell::Cell;
use core::fmt::{write, Debug};
use uapi::cap::ObjectType;
use utils::addr::PhysAddr;
use utils::{
@ -20,8 +21,6 @@ pub struct RawCap {
pub ptr: PhysAddr,
/// cap_type: every capability links to one specific object
pub cap_type: ObjectType,
/// _padding: padding to align the size of RawCap to power of 2
pub _padding: [usize; 2],
}
impl RawCap {
@ -30,7 +29,6 @@ impl RawCap {
args: [arg0, arg1],
ptr,
cap_type,
_padding: [0, 0],
}
}
}
@ -42,8 +40,6 @@ pub struct CapEntry {
LinkHelperImpl!(CapEntry: link);
const_assert_eq!(core::mem::size_of::<CapEntry>(), ObjectType::CNode.size(0));
impl CapEntry {
pub fn new(cap: RawCap) -> Self {
Self {
@ -71,3 +67,18 @@ impl From<RawCap> for CapEntry {
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,
};
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::MASK;
/// CNodeObject is a array of Capabilities (`RawCap`)
/// CNodeObject is a array of Capabilities (`CapEntry`)
/// The size of the array is stored in CNodeCap
pub type CNodeObject = [CapEntry];
const_assert!(core::mem::size_of::<CapEntry>() <= ObjectType::CNode.size(0));
impl KernelObject for CNodeObject {
const OBJ_TYPE: ObjectType = ObjectType::CNode;
}
@ -22,7 +25,7 @@ impl KernelObject for CNodeObject {
* > args[1]: guard
*
* in our implementation, CNodeCap layout:
* > args[0]: [guard_size, radix]
* > args[0]: [guard_bits, radix_bits]
* > args[1]: guard
* > ptr: cnode_ptr
* > cap_type: cap_tag
@ -38,9 +41,9 @@ impl<'a> CNodeCap<'a> {
const RADIX_MASK: usize = MASK!(Self::RADIX_BITS);
const RADIX_OFFSET: usize = 0;
pub fn mint(radix: usize, guard_size: usize, guard: usize, ptr: PhysAddr) -> RawCap {
let arg0 = ((radix & Self::RADIX_MASK) << Self::RADIX_OFFSET)
| ((guard_size & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET);
pub fn mint(radix_bits: usize, guard_bits: usize, guard: usize, ptr: PhysAddr) -> RawCap {
let arg0 = ((radix_bits & Self::RADIX_MASK) << Self::RADIX_OFFSET)
| ((guard_bits & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET);
let arg1 = guard;
let cap: RawCap = RawCap::new(arg0, arg1, ptr, ObjectType::CNode);
@ -55,11 +58,11 @@ impl<'a> CNodeCap<'a> {
cap
}
fn radix(&self) -> usize {
fn radix_bits(&self) -> usize {
(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
}
@ -72,7 +75,7 @@ impl<'a> CNodeCap<'a> {
// 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
// > 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 {
@ -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 slot = self.cte;
while let Ok(cnode) = CNodeCap::try_from(slot) {
let radix_bits = cnode.radix();
let guard_bits = cnode.guard_size();
let radix_bits = cnode.radix_bits();
let guard_bits = cnode.guard_bits();
let level_bits = radix_bits + guard_bits;
let cap_guard = cnode.guard();
assert_ne!(level_bits, 0);
if level_bits > bits_remaining {
return Err(CapFault::DepthMismatch {
return Err(LookupFailure::DepthMismatch {
bits_found: level_bits,
bits_left: bits_remaining,
});
@ -110,7 +113,7 @@ impl<'a> CNodeCap<'a> {
let get_guard = || (cap_ptr >> (bits_remaining - guard_bits)) & MASK!(guard_bits);
if guard_bits > bits_remaining || get_guard() != cap_guard {
return Err(CapFault::GuardMismatch {
return Err(LookupFailure::GuardMismatch {
bits_left: bits_remaining,
guard_found: cap_guard,
guard_size: guard_bits,
@ -128,28 +131,39 @@ impl<'a> CNodeCap<'a> {
}
if CNodeCap::try_from(slot).is_err() {
return Err(CapFault::InvalidRoot);
return Err(LookupFailure::InvalidRoot);
}
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)]
mod tests {
use super::*;
use crate::arch::vspace::RAM_ALLOCATOR;
use crate::objects::cap::CapEntry;
use crate::objects::null::NullCap;
use crate::objects::*;
use core::alloc::Layout;
use log::info;
#[test_case]
fn test_cnode_resolve() {
let create_cnode = |radix: usize, guard_size: usize, guard: usize| {
let size = ObjectType::CNode.size(radix);
let create_cnode = |radix_bits: usize, guard_bits: usize, guard: usize| {
let size = ObjectType::CNode.size(radix_bits);
let layout = Layout::from_size_align(size, 1).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)
};
@ -228,7 +242,7 @@ mod tests {
info!("Testing invalid depth (1)");
let result = root.resolve_address_bits(0x96, 8 - 1);
match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => {
Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 8);
assert_eq!(bits_left, 7);
},
@ -241,7 +255,7 @@ mod tests {
info!("Testing invalid depth (2)");
let result = root.resolve_address_bits(0x4b31 >> 1, 15 - 1);
match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => {
Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 7);
assert_eq!(bits_left, 6);
},
@ -256,7 +270,7 @@ mod tests {
info!("Testing guard mismatch");
let result = root.resolve_address_bits(0x4b71, 15);
match result {
Err(CapFault::GuardMismatch {
Err(LookupFailure::GuardMismatch {
bits_left,
guard_found,
guard_size,
@ -274,7 +288,7 @@ mod tests {
info!("Testing extra bits");
let result = root.resolve_address_bits(0x96 << 1, 8 + 1);
match result {
Err(CapFault::DepthMismatch { bits_found, bits_left }) => {
Err(LookupFailure::DepthMismatch { bits_found, bits_left }) => {
assert_eq!(bits_found, 7);
assert_eq!(bits_left, 1);
},

View File

@ -4,6 +4,7 @@ use crate::{
objects::cap::CapEntry,
vspace::*,
};
use core::fmt::Debug;
use uapi::{
cap::ObjectType,
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 uapi::{
cap::ObjectType,
@ -29,6 +28,14 @@ pub mod table;
pub mod tcb;
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)
/// 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)

View File

@ -1,5 +1,6 @@
use super::cap::RawCap;
use super::{Cap, KernelObject};
use core::fmt::Debug;
use uapi::cap::ObjectType;
use utils::addr::PhysAddr;
@ -15,3 +16,9 @@ impl<'a> NullCap<'a> {
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 crate::{arch::layout::mmap_phys_to_virt, vspace::*};
use core::fmt::Debug;
use uapi::{
cap::ObjectType,
error::{SysError, SysResult},
@ -7,7 +8,7 @@ use uapi::{
use utils::{addr::*, MASK};
/// TableObject is an object that represents a page table
pub struct TableObject([usize]);
pub struct TableObject([u8]);
impl KernelObject for TableObject {
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::{
cap::{CapEntry, RawCap},
cnode::CNodeCap,
null::NullCap,
Cap, KernelObject,
};
@ -7,14 +8,15 @@ use crate::{
arch::{layout::mmap_phys_to_virt, trap::TrapContext},
plat::trap::TrapContextOps,
};
use uapi::cap::ObjectType;
use core::fmt::Debug;
use uapi::{cap::ObjectType, error::SysResult, fault::Fault, syscall::MessageInfo};
use utils::{
addr::*,
linked_list::{Link, LinkHelper},
LinkHelperImpl,
};
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub enum ThreadState {
Inactive,
Running,
@ -27,10 +29,13 @@ pub enum ThreadState {
pub struct TcbObject {
pub trapframe: TrapContext, // must be the first field
cspace: CapEntry,
vspace: CapEntry,
cspace: CapEntry,
vspace: CapEntry,
notification: CapEntry,
buffer: CapEntry, // CapFrame
fault: Fault,
fault_handler: CapEntry,
// TODO: add reply, buffer, fault, caller ... priority, dom
state: ThreadState,
time_tick: usize,
pub link: Link<Self>,
@ -38,15 +43,22 @@ pub struct TcbObject {
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 {
pub fn new() -> Self {
Self {
trapframe: TrapContext::default(),
cspace: CapEntry::new(NullCap::mint()),
vspace: CapEntry::new(NullCap::mint()),
state: ThreadState::Inactive,
time_tick: 0,
link: Link::default(),
trapframe: TrapContext::default(),
cspace: 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,
time_tick: 0,
link: Link::default(),
}
}
@ -55,6 +67,14 @@ impl TcbObject {
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 {
self.time_tick
}
@ -79,7 +99,19 @@ impl TcbObject {
}
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::null::NullCap;
use super::{Cap, KernelObject};
use core::fmt::Debug;
use uapi::cap::ObjectType;
use uapi::error::{SysError, SysResult};
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)]
mod tests {
use super::*;

View File

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

View File

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

View File

@ -3,17 +3,21 @@ use core::cmp::min;
use utils::addr::{AddressOps, PhysAddr};
#[derive(Copy, Clone, Debug)]
struct Block {
pub struct Block {
start: PhysAddr,
size: usize,
}
impl Block {
fn start_addr(&self) -> PhysAddr {
pub fn start_addr(&self) -> PhysAddr {
self.start
}
fn end_addr(&self) -> PhysAddr {
pub fn size(&self) -> usize {
self.size
}
pub fn end_addr(&self) -> PhysAddr {
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> {

View File

@ -14,6 +14,15 @@ pub fn align_down(addr: usize, align: usize) -> usize {
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)]
pub struct PhysAddr(pub usize);
@ -37,11 +46,7 @@ pub trait AddressOps: Copy + Clone + Default + Eq + Ord + PartialOrd + PartialEq
where T: Into<usize>;
fn is_aligned<T>(&self, align: T) -> bool
where T: Into<usize> + Copy {
if align.into().is_power_of_two() {
self.as_usize() & (align.into() - 1) == 0
} else {
false
}
is_aligned(self.as_usize(), align.into())
}
}
@ -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 {
fn from(addr: NonZeroUsize) -> Self {
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 {
fn from(addr: NonZeroUsize) -> Self {
VirtAddr(addr.get())

View File

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

View File

@ -7,7 +7,14 @@ use crate::error::SysError;
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
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:
@ -22,7 +29,7 @@ pub enum Syscall {
* > Call:
* > > [a0]: MessageInfo
* > > [a1]: Capability Pointer
* > > [a3..a7]: extra arguments
* > > [a2..a7]: extra arguments
* > > length = (a0..a?).len()
* > Reply:
* > TODO: figure out how vanilla seL4 handle reply