mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35:19 +08:00
Compare commits
11 Commits
d53fa7b93e
...
c013478d0b
Author | SHA1 | Date | |
---|---|---|---|
c013478d0b | |||
3b3c68a203 | |||
9f4be01153 | |||
a58110f013 | |||
77283b47ef | |||
7fa26c109f | |||
d36c534a92 | |||
fb94285028 | |||
9c1b39b6d7 | |||
a007e299d2 | |||
95713e2af4 |
@ -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};
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::objects::tcb::TcbObject;
|
||||
use crate::objects::*;
|
||||
|
||||
pub struct Trap;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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
52
uapi/src/fault.rs
Normal 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),
|
||||
}
|
@ -6,5 +6,6 @@ extern crate num_derive;
|
||||
|
||||
pub mod cap;
|
||||
pub mod error;
|
||||
pub mod fault;
|
||||
pub mod syscall;
|
||||
pub mod vspace;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user