diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 8fd3125..dfcea95 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,6 +2,7 @@ #![no_std] #![no_main] // Features +#![feature(cell_update)] #![feature(concat_idents)] #![feature(iter_array_chunks)] #![feature(let_chains)] diff --git a/kernel/src/objects/cap.rs b/kernel/src/objects/cap.rs index eb143ff..30bcfc0 100644 --- a/kernel/src/objects/cap.rs +++ b/kernel/src/objects/cap.rs @@ -1,11 +1,7 @@ use crate::objects::*; -use core::fmt::Debug; +use core::{cell::Cell, fmt::Debug}; use uapi::cap::ObjectType; use utils::addr::PhysAddr; -use utils::{ - linked_list::{Link, LinkHelper}, - LinkHelperImpl, -}; /// RawCap is the specific implementation of capability which stores in CNode #[derive(Copy, Clone, Default, PartialEq, Eq)] @@ -30,46 +26,22 @@ impl RawCap { cap_type, } } - - /// modify the capability - /// # Safety - /// This function breaks the safety rules of Rust, race condition may occur - pub unsafe fn update(&self, f: F) -> &Self - where F: FnOnce(&mut Self) { - #[allow(invalid_reference_casting)] - f(unsafe { &mut *(self as *const _ as *mut Self) }); - self - } } pub const CAP_ENTRY_LINK_ID: usize = 1; +#[derive(Clone)] pub struct CapEntry { - pub cap: RawCap, - pub link: Link, + pub cap: Cell, } -LinkHelperImpl!(CapEntry { link } => CAP_ENTRY_LINK_ID); - impl CapEntry { pub fn new(cap: RawCap) -> Self { - Self { - cap, - link: Link::default(), - } + Self { cap: Cell::new(cap) } } pub fn init(&mut self) { - self.cap = NullCap::mint(); - self.link = Link::default(); - } -} - -impl Clone for CapEntry { - fn clone(&self) -> Self { - let mut cte = Self::new(self.cap); - cte.link = self.link.clone(); - cte + self.cap.replace(NullCap::mint()); } } @@ -81,9 +53,10 @@ impl From for CapEntry { impl Debug for CapEntry { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let cap_type = self.cap.cap_type; + let cap_type = self.cap.get().cap_type; match cap_type { ObjectType::CNode => write!(f, "{:?}", CNodeCap::try_from(self)), + ObjectType::Endpoint => write!(f, "{:?}", EndpointCap::try_from(self)), ObjectType::Frame => write!(f, "{:?}", FrameCap::try_from(self)), ObjectType::Null => write!(f, "{:?}", NullCap::try_from(self)), ObjectType::Table => write!(f, "{:?}", TableCap::try_from(self)), diff --git a/kernel/src/objects/cnode.rs b/kernel/src/objects/cnode.rs index d1b2349..b3afb6f 100644 --- a/kernel/src/objects/cnode.rs +++ b/kernel/src/objects/cnode.rs @@ -56,15 +56,15 @@ impl<'a> CNodeCap<'a> { } fn radix_bits(&self) -> usize { - (self.cte.cap.args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK + (self.cap().get().args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK } fn guard_bits(&self) -> usize { - (self.cte.cap.args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK + (self.cap().get().args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK } fn guard(&self) -> usize { - self.cte.cap.args[1] + self.cap().get().args[1] } /// CNodeObject length @@ -77,14 +77,14 @@ impl<'a> CNodeCap<'a> { pub fn as_object(&self) -> &CNodeObject { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); core::slice::from_raw_parts(virt.as_const_ptr(), self.length()) } } pub fn as_object_mut(&mut self) -> &mut CNodeObject { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.length()) } } @@ -142,7 +142,7 @@ impl Debug for CNodeCap<'_> { .field("guard_bits", &self.guard_bits()) .field("guard", &self.guard()) .field("length", &self.length()) - .field("ptr", &self.cte.cap.ptr) + .field("ptr", &self.cap().get().ptr) .finish() } } @@ -175,18 +175,17 @@ mod tests { cnode1.as_object_mut()[6] = cte2.clone(); cnode2.as_object_mut()[1] = cte3.clone(); cnode3.as_object_mut()[2] = NullCap::mint().into(); - unsafe { - cnode3.as_object_mut()[2].cap.update(|cap| { - cap.args[0] = 0xdeadbeef; - cap.args[1] = 0xaa55aa55; - }); - } + cnode3.as_object_mut()[2].cap.update(|mut cap| { + cap.args[0] = 0xdeadbeef; + cap.args[1] = 0xaa55aa55; + cap + }); { // cte2.clone() cte3.clone() should not modify cte itself info!("Testing whether RawCap and Cap held the same cap"); - assert!(cnode2.cte.cap == cte2.cap); - assert!(cnode3.cte.cap == cte3.cap); + assert!(cnode2.cap().get() == cte2.cap.get()); + assert!(cnode3.cap().get() == cte3.cap.get()); } let root = cnode1; @@ -231,8 +230,8 @@ mod tests { // * target length = 21 info!("Testing resolve to target"); let target = root.resolve_address_bits(0x12cc6a, 21).unwrap(); - assert!(target.cap.args[0] == 0xdeadbeef); - assert!(target.cap.args[1] == 0xaa55aa55); + assert!(target.cap.get().args[0] == 0xdeadbeef); + assert!(target.cap.get().args[1] == 0xaa55aa55); } { diff --git a/kernel/src/objects/endpoint.rs b/kernel/src/objects/endpoint.rs index bb0c525..982fddd 100644 --- a/kernel/src/objects/endpoint.rs +++ b/kernel/src/objects/endpoint.rs @@ -1,5 +1,5 @@ use crate::{objects::*, plat::trap::TrapContextOps}; -use core::cmp::min; +use core::{cmp::min, fmt::Debug}; use tcb::{ThreadState, EP_QUEUE_LINK_ID}; use uapi::{cap::ObjectType, fault::Fault, syscall::*}; use utils::{addr::*, array::*, linked_list::Link}; @@ -25,8 +25,8 @@ impl KernelObject for EndpointObject { * in vanilla seL4, EndpointCap layout: * > args[0]: | cap_tag | can_grant_reply | can_grant | can_recv | can_send | base_ptr | * > | [63:59] | [58:58] | [57:57] | [56:56] | [55:55] | [54:0] | - * > args[1]: | badge | - * > | [63::0] | + * > args[1]: | badge | + * > | [63:0] | * * in our implementation, EndpointCap layout: * > args[0]: badge @@ -43,15 +43,15 @@ impl<'a> EndpointCap<'a> { } pub fn can_send(&self) -> bool { - self.cte.cap.args[0] & 0x2 != 0 + self.cap().get().args[0] & 0x2 != 0 } pub fn can_recv(&self) -> bool { - self.cte.cap.args[0] & 0x1 != 0 + self.cap().get().args[0] & 0x1 != 0 } pub fn badge(&self) -> usize { - self.cte.cap.args[1] + self.cap().get().args[1] } pub fn state(&self) -> EndpointState { @@ -130,6 +130,18 @@ impl<'a> EndpointCap<'a> { } } +impl Debug for EndpointCap<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("EndpointCap") + .field("ptr", &self.cap().get().ptr) + .field("badge", &self.badge()) + .field("can_send", &self.can_send()) + .field("can_recv", &self.can_recv()) + .field("state", &self.state()) + .finish() + } +} + fn copy_message(send: &mut TcbObject, send_msg: MessageInfo, recv: &mut TcbObject, recv_msg: MessageInfo) -> SysResult<()> { let send_len = send_msg.length() - if send_msg.transfer_cap() { 2 } else { 0 }; let recv_len = recv_msg.length() - if recv_msg.transfer_cap() { 2 } else { 0 }; @@ -184,9 +196,8 @@ fn transfer_cap(send: &mut TcbObject, send_msg: MessageInfo, recv: &mut TcbObjec let recv_cap = recv_cspace.resolve_address_bits(recv_cptr, recv_bits)?; let dest = NullCap::try_from(recv_cap)?; - dest.override_cap(send_cap.cap); - - unsafe { send_cap.cap.update(|cap| *cap = NullCap::mint()) }; + dest.override_cap(send_cap.cap.get()); + send_cap.cap.replace(NullCap::mint()); Ok(()) } diff --git a/kernel/src/objects/frame.rs b/kernel/src/objects/frame.rs index a530f84..64b1d1f 100644 --- a/kernel/src/objects/frame.rs +++ b/kernel/src/objects/frame.rs @@ -64,56 +64,54 @@ impl<'a> FrameCap<'a> { } pub fn attr(&self) -> MapAttr { - let bits = (self.cte.cap.args[0] >> Self::VM_RIGHT_OFFSET) & Self::VM_RIGHT_MASK; + let bits = (self.cap().get().args[0] >> Self::VM_RIGHT_OFFSET) & Self::VM_RIGHT_MASK; MapAttr::from_bits_truncate(bits) } pub fn is_device(&self) -> bool { - let bits = (self.cte.cap.args[0] >> Self::IS_DEVICE_OFFSET) & Self::IS_DEVICE_MASK; + let bits = (self.cap().get().args[0] >> Self::IS_DEVICE_OFFSET) & Self::IS_DEVICE_MASK; bits != 0 } pub fn size(&self) -> usize { - let bits = (self.cte.cap.args[0] >> Self::FRAME_SIZE_OFFSET) & Self::FRAME_SIZE_MASK; + let bits = (self.cap().get().args[0] >> Self::FRAME_SIZE_OFFSET) & Self::FRAME_SIZE_MASK; 1 << bits } pub fn mapped_asid(&self) -> usize { - (self.cte.cap.args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK + (self.cap().get().args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK } pub fn set_mapped_asid(&self, asid: usize) { - unsafe { - self.cte.cap.update(|cap| { - let asid = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; - let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); - cap.args[0] = arg0 | asid; - }) - }; + self.cap().update(|mut cap| { + let asid = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; + let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); + cap.args[0] = arg0 | asid; + cap + }); } pub fn mapped_vaddr(&self) -> VirtAddr { - VirtAddr(self.cte.cap.args[1]) + VirtAddr(self.cap().get().args[1]) } pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) { - unsafe { - self.cte.cap.update(|cap| { - cap.args[1] = vaddr.0; - }) - }; + self.cap().update(|mut cap| { + cap.args[1] = vaddr.0; + cap + }); } pub fn as_object(&self) -> &FrameObject { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); core::slice::from_raw_parts(virt.as_const_ptr(), self.size()) } } pub fn as_object_mut(&mut self) -> &mut FrameObject { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.size()) } } @@ -128,7 +126,7 @@ impl<'a> FrameCap<'a> { pub fn map(&self, root: &mut Table, vaddr: VirtAddr, attr: MapAttr) -> SysResult { let masked_attr = attr & self.attr(); - root.map(vaddr, self.cte.cap.ptr, masked_attr)?; + root.map(vaddr, self.cap().get().ptr, masked_attr)?; self.set_mapped_asid(0); self.set_mapped_vaddr(vaddr); @@ -143,7 +141,7 @@ impl<'a> FrameCap<'a> { } match root.lookup_mut(vaddr) { - Some(entry) if entry.is_leaf() && entry.paddr() == self.cte.cap.ptr => { + Some(entry) if entry.is_leaf() && entry.paddr() == self.cap().get().ptr => { entry.set_paddr(PhysAddr::default()); entry.set_attr(MapAttr::empty()); @@ -161,7 +159,7 @@ 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.ptr) + .field("ptr", &self.cap().get().ptr) .field("size", &self.size()) .field("attr", &self.attr()) .field("is_device", &self.is_device()) diff --git a/kernel/src/objects/mod.rs b/kernel/src/objects/mod.rs index 9fea7bf..a2de23c 100644 --- a/kernel/src/objects/mod.rs +++ b/kernel/src/objects/mod.rs @@ -15,7 +15,7 @@ */ use crate::arch::layout::mmap_phys_to_virt; -use core::marker::PhantomData; +use core::{cell::Cell, marker::PhantomData}; use uapi::{ cap::ObjectType, error::{SysError, SysResult}, @@ -33,7 +33,7 @@ pub mod untyped; pub use cap::{CapEntry, RawCap}; pub use cnode::{CNodeCap, CNodeObject}; -pub use endpoint::{EndpointCap, EndpointObject}; +pub use endpoint::EndpointCap; pub use frame::{FrameCap, FrameObject}; pub use null::NullCap; pub use table::{TableCap, TableObject}; @@ -52,7 +52,7 @@ impl<'a, T: KernelObject + ?Sized> TryFrom<&'a CapEntry> for Cap<'a, T> { type Error = SysError; fn try_from(new: &'a CapEntry) -> SysResult { - if new.cap.cap_type != T::OBJ_TYPE { + if new.cap.get().cap_type != T::OBJ_TYPE { Err(SysError::CapTypeMismatch) } else { Ok(Self { @@ -64,22 +64,22 @@ impl<'a, T: KernelObject + ?Sized> TryFrom<&'a CapEntry> for Cap<'a, T> { } impl<'a, T: KernelObject + ?Sized> Cap<'a, T> { - pub fn append(&mut self, new: &mut CapEntry) { - self.cte.link.append(new) + pub fn cap(&self) -> &Cell { + &self.cte.cap } } impl<'a, T: KernelObject> Cap<'a, T> { pub fn as_object(&self) -> &T { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); &*(virt.as_const_ptr()) } } pub fn as_object_mut(&mut self) -> &mut T { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); &mut *(virt.as_mut_ptr()) } } diff --git a/kernel/src/objects/null.rs b/kernel/src/objects/null.rs index 18491ae..6b79c64 100644 --- a/kernel/src/objects/null.rs +++ b/kernel/src/objects/null.rs @@ -16,7 +16,7 @@ impl<'a> NullCap<'a> { } pub fn override_cap(&self, new: RawCap) { - unsafe { self.cte.cap.update(|cap| *cap = new) }; + self.cap().replace(new); } } diff --git a/kernel/src/objects/table.rs b/kernel/src/objects/table.rs index 879f171..cf6093e 100644 --- a/kernel/src/objects/table.rs +++ b/kernel/src/objects/table.rs @@ -43,50 +43,47 @@ impl<'a> TableCap<'a> { } pub fn is_mapped(&self) -> bool { - let bits = (self.cte.cap.args[0] >> Self::IS_MAPPED_OFFSET) & Self::IS_MAPPED_MASK; + let bits = (self.cap().get().args[0] >> Self::IS_MAPPED_OFFSET) & Self::IS_MAPPED_MASK; bits != 0 } pub fn set_mapped(&self, mapped: bool) { - unsafe { - self.cte.cap.update(|cap| { - let is_mapped = if mapped { 1 } else { 0 }; - let bits = (is_mapped & Self::IS_MAPPED_MASK) << Self::IS_MAPPED_OFFSET; - let arg0 = cap.args[0] & !(Self::IS_MAPPED_MASK << Self::IS_MAPPED_OFFSET); - cap.args[0] = arg0 | bits; - }) - }; + self.cap().update(|mut cap| { + let is_mapped = if mapped { 1 } else { 0 }; + let bits = (is_mapped & Self::IS_MAPPED_MASK) << Self::IS_MAPPED_OFFSET; + let arg0 = cap.args[0] & !(Self::IS_MAPPED_MASK << Self::IS_MAPPED_OFFSET); + cap.args[0] = arg0 | bits; + cap + }); } pub fn asid(&self) -> usize { - (self.cte.cap.args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK + (self.cap().get().args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK } pub fn set_mapped_asid(&self, asid: usize) { - unsafe { - self.cte.cap.update(|cap| { - let bits = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; - let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); - cap.args[0] = arg0 | bits; - }) - }; + self.cap().update(|mut cap| { + let bits = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; + let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); + cap.args[0] = arg0 | bits; + cap + }); } pub fn mapped_vaddr(&self) -> VirtAddr { - VirtAddr(self.cte.cap.args[1]) + VirtAddr(self.cap().get().args[1]) } pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) { - unsafe { - self.cte.cap.update(|cap| { - cap.args[1] = vaddr.0; - }) - }; + self.cap().update(|mut cap| { + cap.args[1] = vaddr.0; + cap + }); } pub fn as_object(&self) -> Table { unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); Table::new(virt) } } @@ -97,14 +94,14 @@ impl<'a> TableCap<'a> { pub fn clear(&self) { let array: &mut [u8] = unsafe { - let virt = mmap_phys_to_virt(self.cte.cap.ptr); + let virt = mmap_phys_to_virt(self.cap().get().ptr); core::slice::from_raw_parts_mut(virt.as_mut_ptr(), T::ENTRIES * core::mem::size_of::()) }; array.fill(0); } pub fn map(&self, root: &mut Table, vaddr: VirtAddr) -> SysResult { - root.map(vaddr, self.cte.cap.ptr, MapAttr::PAGE_TABLE)?; + root.map(vaddr, self.cap().get().ptr, MapAttr::PAGE_TABLE)?; self.set_mapped_asid(0); self.set_mapped_vaddr(vaddr); @@ -119,7 +116,7 @@ impl<'a> TableCap<'a> { } match root.lookup_mut(vaddr) { - Some(entry) if !entry.is_leaf() && entry.paddr() == self.cte.cap.ptr => { + Some(entry) if !entry.is_leaf() && entry.paddr() == self.cap().get().ptr => { entry.set_paddr(PhysAddr::default()); entry.set_attr(MapAttr::empty()); @@ -136,6 +133,6 @@ 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.ptr).finish() + f.debug_struct("TableCap").field("ptr", &self.cap().get().ptr).finish() } } diff --git a/kernel/src/objects/untyped.rs b/kernel/src/objects/untyped.rs index 4a4d88e..121b9b7 100644 --- a/kernel/src/objects/untyped.rs +++ b/kernel/src/objects/untyped.rs @@ -42,23 +42,22 @@ impl UntypedCap<'_> { } fn free_offset(&self) -> usize { - self.cte.cap.args[0] + self.cap().get().args[0] } fn set_free_offset(&mut self, free_offset: usize) { - unsafe { - self.cte.cap.update(|c| { - c.args[0] = free_offset; - }) - }; + self.cap().update(|mut cap| { + cap.args[0] = free_offset; + cap + }); } pub fn is_device(&self) -> bool { - (self.cte.cap.args[1] >> 6) & 1 == 1 + (self.cap().get().args[1] >> 6) & 1 == 1 } fn block_bits(&self) -> usize { - self.cte.cap.args[1] & MASK!(6) + self.cap().get().args[1] & MASK!(6) } fn block_size(&self) -> usize { @@ -111,7 +110,7 @@ impl UntypedCap<'_> { // Create new capabilities in slot for (i, slot) in slots.iter_mut().enumerate() { - let addr = self.cte.cap.ptr + start_offset + i * obj_size; + let addr = self.cap().get().ptr + start_offset + i * obj_size; let new_cap = match obj_type { ObjectType::Untyped => UntypedCap::mint(0, obj_type.bits(user_obj_bits), self.is_device(), addr), ObjectType::CNode => CNodeCap::mint(user_obj_bits, 0, 0, addr), @@ -122,8 +121,7 @@ impl UntypedCap<'_> { _ => return Err(SysError::InvalidArgument), }; - slot.cap = new_cap; - self.append(slot); + slot.cap.replace(new_cap); } // Update free_offset @@ -139,7 +137,7 @@ impl Debug for UntypedCap<'_> { .field("free_offset", &self.free_offset()) .field("block_bits", &self.block_bits()) .field("is_device", &self.is_device()) - .field("ptr", &self.cte.cap.ptr) + .field("ptr", &self.cap().get().ptr) .finish() } }