merge: merge branch try/no-cell into dev

This commit is contained in:
Paul Pan 2024-08-05 15:30:15 +08:00
commit 7ab1c29eaa
7 changed files with 97 additions and 81 deletions

View File

@ -1,5 +1,4 @@
use crate::objects::*; use crate::objects::*;
use core::cell::Cell;
use core::fmt::Debug; use core::fmt::Debug;
use uapi::cap::ObjectType; use uapi::cap::ObjectType;
use utils::addr::PhysAddr; use utils::addr::PhysAddr;
@ -31,10 +30,20 @@ impl RawCap {
cap_type, cap_type,
} }
} }
/// modify the capability
/// # Safety
/// This function breaks the safety rules of Rust, race condition may occur
pub unsafe fn update<F>(&self, f: F) -> &Self
where F: FnOnce(&mut Self) {
#[allow(invalid_reference_casting)]
f(unsafe { &mut *(self as *const _ as *mut Self) });
self
}
} }
pub struct CapEntry { pub struct CapEntry {
pub cap: Cell<RawCap>, pub cap: RawCap,
pub link: Link<Self>, pub link: Link<Self>,
} }
@ -43,20 +52,20 @@ LinkHelperImpl!(CapEntry: link);
impl CapEntry { impl CapEntry {
pub fn new(cap: RawCap) -> Self { pub fn new(cap: RawCap) -> Self {
Self { Self {
cap: Cell::new(cap), cap,
link: Link::default(), link: Link::default(),
} }
} }
pub fn init(&mut self) { pub fn init(&mut self) {
self.cap = Cell::new(NullCap::mint()); self.cap = NullCap::mint();
self.link = Link::default(); self.link = Link::default();
} }
} }
impl Clone for CapEntry { impl Clone for CapEntry {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut cte = Self::new(self.cap.get()); let mut cte = Self::new(self.cap);
cte.link = self.link.clone(); cte.link = self.link.clone();
cte cte
} }
@ -70,7 +79,7 @@ impl From<RawCap> for CapEntry {
impl Debug for CapEntry { impl Debug for CapEntry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let cap_type = self.cap.get().cap_type; let cap_type = self.cap.cap_type;
match cap_type { match cap_type {
ObjectType::CNode => write!(f, "{:?}", CNodeCap::try_from(self)), ObjectType::CNode => write!(f, "{:?}", CNodeCap::try_from(self)),
ObjectType::Frame => write!(f, "{:?}", FrameCap::try_from(self)), ObjectType::Frame => write!(f, "{:?}", FrameCap::try_from(self)),

View File

@ -56,15 +56,15 @@ impl<'a> CNodeCap<'a> {
} }
fn radix_bits(&self) -> usize { fn radix_bits(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK (self.cte.cap.args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK
} }
fn guard_bits(&self) -> usize { fn guard_bits(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK (self.cte.cap.args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK
} }
fn guard(&self) -> usize { fn guard(&self) -> usize {
self.cte.cap.get().args[1] self.cte.cap.args[1]
} }
/// CNodeObject length /// CNodeObject length
@ -77,14 +77,14 @@ impl<'a> CNodeCap<'a> {
pub fn as_object(&self) -> &CNodeObject { pub fn as_object(&self) -> &CNodeObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
core::slice::from_raw_parts(virt.as_const_ptr(), self.length()) core::slice::from_raw_parts(virt.as_const_ptr(), self.length())
} }
} }
pub fn as_object_mut(&mut self) -> &mut CNodeObject { pub fn as_object_mut(&mut self) -> &mut CNodeObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.length()) 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_bits", &self.guard_bits())
.field("guard", &self.guard()) .field("guard", &self.guard())
.field("length", &self.length()) .field("length", &self.length())
.field("ptr", &self.cte.cap.get().ptr) .field("ptr", &self.cte.cap.ptr)
.finish() .finish()
} }
} }
@ -175,17 +175,18 @@ mod tests {
cnode1.as_object_mut()[6] = cte2.clone(); cnode1.as_object_mut()[6] = cte2.clone();
cnode2.as_object_mut()[1] = cte3.clone(); cnode2.as_object_mut()[1] = cte3.clone();
cnode3.as_object_mut()[2] = NullCap::mint().into(); cnode3.as_object_mut()[2] = NullCap::mint().into();
cnode3.as_object_mut()[2].cap.update(|mut cap| { unsafe {
cap.args[0] = 0xdeadbeef; cnode3.as_object_mut()[2].cap.update(|cap| {
cap.args[1] = 0xaa55aa55; cap.args[0] = 0xdeadbeef;
cap cap.args[1] = 0xaa55aa55;
}); });
}
{ {
// cte2.clone() cte3.clone() should not modify cte itself // cte2.clone() cte3.clone() should not modify cte itself
info!("Testing whether RawCap and Cap held the same cap"); info!("Testing whether RawCap and Cap held the same cap");
assert!(cnode2.cte.cap.get() == cte2.cap.get()); assert!(cnode2.cte.cap == cte2.cap);
assert!(cnode3.cte.cap.get() == cte3.cap.get()); assert!(cnode3.cte.cap == cte3.cap);
} }
let root = cnode1; let root = cnode1;
@ -212,7 +213,7 @@ mod tests {
// * cnode2 length = 8 // * cnode2 length = 8
info!("Testing resolve to cte2"); info!("Testing resolve to cte2");
let target = root.resolve_address_bits(0x96, 8).unwrap(); let target = root.resolve_address_bits(0x96, 8).unwrap();
assert!(target.cap.get() == cte2.cap.get()); assert!(target.cap == cte2.cap);
} }
{ {
@ -221,7 +222,7 @@ mod tests {
// * cnode3 length = 15 // * cnode3 length = 15
info!("Testing resolve to cte3"); info!("Testing resolve to cte3");
let target = root.resolve_address_bits(0x4b31, 15).unwrap(); let target = root.resolve_address_bits(0x4b31, 15).unwrap();
assert!(target.cap.get() == cte3.cap.get()); assert!(target.cap == cte3.cap);
} }
{ {
@ -230,8 +231,8 @@ mod tests {
// * target length = 21 // * target length = 21
info!("Testing resolve to target"); info!("Testing resolve to target");
let target = root.resolve_address_bits(0x12cc6a, 21).unwrap(); let target = root.resolve_address_bits(0x12cc6a, 21).unwrap();
assert!(target.cap.get().args[0] == 0xdeadbeef); assert!(target.cap.args[0] == 0xdeadbeef);
assert!(target.cap.get().args[1] == 0xaa55aa55); assert!(target.cap.args[1] == 0xaa55aa55);
} }
{ {

View File

@ -64,54 +64,56 @@ impl<'a> FrameCap<'a> {
} }
pub fn attr(&self) -> MapAttr { pub fn attr(&self) -> MapAttr {
let bits = (self.cte.cap.get().args[0] >> Self::VM_RIGHT_OFFSET) & Self::VM_RIGHT_MASK; let bits = (self.cte.cap.args[0] >> Self::VM_RIGHT_OFFSET) & Self::VM_RIGHT_MASK;
MapAttr::from_bits_truncate(bits) MapAttr::from_bits_truncate(bits)
} }
pub fn is_device(&self) -> bool { pub fn is_device(&self) -> bool {
let bits = (self.cte.cap.get().args[0] >> Self::IS_DEVICE_OFFSET) & Self::IS_DEVICE_MASK; let bits = (self.cte.cap.args[0] >> Self::IS_DEVICE_OFFSET) & Self::IS_DEVICE_MASK;
bits != 0 bits != 0
} }
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
let bits = (self.cte.cap.get().args[0] >> Self::FRAME_SIZE_OFFSET) & Self::FRAME_SIZE_MASK; let bits = (self.cte.cap.args[0] >> Self::FRAME_SIZE_OFFSET) & Self::FRAME_SIZE_MASK;
1 << bits 1 << bits
} }
pub fn mapped_asid(&self) -> usize { pub fn mapped_asid(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK (self.cte.cap.args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK
} }
pub fn set_mapped_asid(&self, asid: usize) { pub fn set_mapped_asid(&self, asid: usize) {
self.cte.cap.update(|mut cap| { unsafe {
let asid = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; self.cte.cap.update(|cap| {
let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); let asid = (asid & Self::ASID_MASK) << Self::ASID_OFFSET;
cap.args[0] = arg0 | asid; let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET);
cap cap.args[0] = arg0 | asid;
}); })
};
} }
pub fn mapped_vaddr(&self) -> VirtAddr { pub fn mapped_vaddr(&self) -> VirtAddr {
VirtAddr(self.cte.cap.get().args[1]) VirtAddr(self.cte.cap.args[1])
} }
pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) { pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) {
self.cte.cap.update(|mut cap| { unsafe {
cap.args[1] = vaddr.0; self.cte.cap.update(|cap| {
cap cap.args[1] = vaddr.0;
}); })
};
} }
pub fn as_object(&self) -> &FrameObject { pub fn as_object(&self) -> &FrameObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
core::slice::from_raw_parts(virt.as_const_ptr(), self.size()) core::slice::from_raw_parts(virt.as_const_ptr(), self.size())
} }
} }
pub fn as_object_mut(&mut self) -> &mut FrameObject { pub fn as_object_mut(&mut self) -> &mut FrameObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.size()) core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.size())
} }
} }
@ -126,7 +128,7 @@ impl<'a> FrameCap<'a> {
pub fn map<T: TableLevel>(&self, root: &mut Table<T>, vaddr: VirtAddr, attr: MapAttr) -> SysResult { pub fn map<T: TableLevel>(&self, root: &mut Table<T>, vaddr: VirtAddr, attr: MapAttr) -> SysResult {
let masked_attr = attr & self.attr(); let masked_attr = attr & self.attr();
root.map(vaddr, self.cte.cap.get().ptr, masked_attr)?; root.map(vaddr, self.cte.cap.ptr, masked_attr)?;
self.set_mapped_asid(0); self.set_mapped_asid(0);
self.set_mapped_vaddr(vaddr); self.set_mapped_vaddr(vaddr);
@ -141,7 +143,7 @@ impl<'a> FrameCap<'a> {
} }
match root.lookup_mut(vaddr) { match root.lookup_mut(vaddr) {
Some(entry) if entry.is_leaf() && entry.paddr() == self.cte.cap.get().ptr => { Some(entry) if entry.is_leaf() && entry.paddr() == self.cte.cap.ptr => {
entry.set_paddr(PhysAddr::default()); entry.set_paddr(PhysAddr::default());
entry.set_attr(MapAttr::empty()); entry.set_attr(MapAttr::empty());
@ -159,7 +161,7 @@ impl<'a> FrameCap<'a> {
impl Debug for FrameCap<'_> { impl Debug for FrameCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FrameCap") f.debug_struct("FrameCap")
.field("ptr", &self.cte.cap.get().ptr) .field("ptr", &self.cte.cap.ptr)
.field("size", &self.size()) .field("size", &self.size())
.field("attr", &self.attr()) .field("attr", &self.attr())
.field("is_device", &self.is_device()) .field("is_device", &self.is_device())

View File

@ -48,7 +48,7 @@ impl<'a, T: KernelObject + ?Sized> TryFrom<&'a CapEntry> for Cap<'a, T> {
type Error = SysError; type Error = SysError;
fn try_from(new: &'a CapEntry) -> SysResult<Self> { fn try_from(new: &'a CapEntry) -> SysResult<Self> {
if new.cap.get().cap_type != T::OBJ_TYPE { if new.cap.cap_type != T::OBJ_TYPE {
Err(SysError::CapTypeMismatch) Err(SysError::CapTypeMismatch)
} else { } else {
Ok(Self { Ok(Self {

View File

@ -43,47 +43,50 @@ impl<'a> TableCap<'a> {
} }
pub fn is_mapped(&self) -> bool { pub fn is_mapped(&self) -> bool {
let bits = (self.cte.cap.get().args[0] >> Self::IS_MAPPED_OFFSET) & Self::IS_MAPPED_MASK; let bits = (self.cte.cap.args[0] >> Self::IS_MAPPED_OFFSET) & Self::IS_MAPPED_MASK;
bits != 0 bits != 0
} }
pub fn set_mapped(&self, mapped: bool) { pub fn set_mapped(&self, mapped: bool) {
self.cte.cap.update(|mut cap| { unsafe {
let is_mapped = if mapped { 1 } else { 0 }; self.cte.cap.update(|cap| {
let bits = (is_mapped & Self::IS_MAPPED_MASK) << Self::IS_MAPPED_OFFSET; let is_mapped = if mapped { 1 } else { 0 };
let arg0 = cap.args[0] & !(Self::IS_MAPPED_MASK << Self::IS_MAPPED_OFFSET); let bits = (is_mapped & Self::IS_MAPPED_MASK) << Self::IS_MAPPED_OFFSET;
cap.args[0] = arg0 | bits; let arg0 = cap.args[0] & !(Self::IS_MAPPED_MASK << Self::IS_MAPPED_OFFSET);
cap cap.args[0] = arg0 | bits;
}); })
};
} }
pub fn asid(&self) -> usize { pub fn asid(&self) -> usize {
(self.cte.cap.get().args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK (self.cte.cap.args[0] >> Self::ASID_OFFSET) & Self::ASID_MASK
} }
pub fn set_mapped_asid(&self, asid: usize) { pub fn set_mapped_asid(&self, asid: usize) {
self.cte.cap.update(|mut cap| { unsafe {
let bits = (asid & Self::ASID_MASK) << Self::ASID_OFFSET; self.cte.cap.update(|cap| {
let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET); let bits = (asid & Self::ASID_MASK) << Self::ASID_OFFSET;
cap.args[0] = arg0 | bits; let arg0 = cap.args[0] & !(Self::ASID_MASK << Self::ASID_OFFSET);
cap cap.args[0] = arg0 | bits;
}); })
};
} }
pub fn mapped_vaddr(&self) -> VirtAddr { pub fn mapped_vaddr(&self) -> VirtAddr {
VirtAddr(self.cte.cap.get().args[1]) VirtAddr(self.cte.cap.args[1])
} }
pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) { pub fn set_mapped_vaddr(&self, vaddr: VirtAddr) {
self.cte.cap.update(|mut cap| { unsafe {
cap.args[1] = vaddr.0; self.cte.cap.update(|cap| {
cap cap.args[1] = vaddr.0;
}); })
};
} }
pub fn as_object<T: TableLevel>(&self) -> Table<T> { pub fn as_object<T: TableLevel>(&self) -> Table<T> {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
Table::new(virt) Table::new(virt)
} }
} }
@ -94,14 +97,14 @@ impl<'a> TableCap<'a> {
pub fn clear<T: TableLevel>(&self) { pub fn clear<T: TableLevel>(&self) {
let array: &mut [u8] = unsafe { let array: &mut [u8] = unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
core::slice::from_raw_parts_mut(virt.as_mut_ptr(), T::ENTRIES * core::mem::size_of::<T::Entry>()) core::slice::from_raw_parts_mut(virt.as_mut_ptr(), T::ENTRIES * core::mem::size_of::<T::Entry>())
}; };
array.fill(0); array.fill(0);
} }
pub fn map<T: TableLevel>(&self, root: &mut Table<T>, vaddr: VirtAddr) -> SysResult { pub fn map<T: TableLevel>(&self, root: &mut Table<T>, vaddr: VirtAddr) -> SysResult {
root.map(vaddr, self.cte.cap.get().ptr, MapAttr::PAGE_TABLE)?; root.map(vaddr, self.cte.cap.ptr, MapAttr::PAGE_TABLE)?;
self.set_mapped_asid(0); self.set_mapped_asid(0);
self.set_mapped_vaddr(vaddr); self.set_mapped_vaddr(vaddr);
@ -116,7 +119,7 @@ impl<'a> TableCap<'a> {
} }
match root.lookup_mut(vaddr) { match root.lookup_mut(vaddr) {
Some(entry) if !entry.is_leaf() && entry.paddr() == self.cte.cap.get().ptr => { Some(entry) if !entry.is_leaf() && entry.paddr() == self.cte.cap.ptr => {
entry.set_paddr(PhysAddr::default()); entry.set_paddr(PhysAddr::default());
entry.set_attr(MapAttr::empty()); entry.set_attr(MapAttr::empty());
@ -133,6 +136,6 @@ impl<'a> TableCap<'a> {
impl Debug for TableCap<'_> { impl Debug for TableCap<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TableCap").field("ptr", &self.cte.cap.get().ptr).finish() f.debug_struct("TableCap").field("ptr", &self.cte.cap.ptr).finish()
} }
} }

View File

@ -149,14 +149,14 @@ impl<'a> TcbCap<'a> {
pub fn as_object(&self) -> &TcbObject { pub fn as_object(&self) -> &TcbObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
&*(virt.as_const_ptr()) &*(virt.as_const_ptr())
} }
} }
pub fn as_object_mut(&mut self) -> &mut TcbObject { pub fn as_object_mut(&mut self) -> &mut TcbObject {
unsafe { unsafe {
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr); let virt = mmap_phys_to_virt(self.cte.cap.ptr);
&mut *(virt.as_mut_ptr()) &mut *(virt.as_mut_ptr())
} }
} }

View File

@ -42,22 +42,23 @@ impl UntypedCap<'_> {
} }
fn free_offset(&self) -> usize { fn free_offset(&self) -> usize {
self.cte.cap.get().args[0] self.cte.cap.args[0]
} }
fn set_free_offset(&mut self, free_offset: usize) { fn set_free_offset(&mut self, free_offset: usize) {
self.cte.cap.update(|mut c| { unsafe {
c.args[0] = free_offset; self.cte.cap.update(|c| {
c c.args[0] = free_offset;
}); })
};
} }
pub fn is_device(&self) -> bool { pub fn is_device(&self) -> bool {
(self.cte.cap.get().args[1] >> 6) & 1 == 1 (self.cte.cap.args[1] >> 6) & 1 == 1
} }
fn block_bits(&self) -> usize { fn block_bits(&self) -> usize {
self.cte.cap.get().args[1] & MASK!(6) self.cte.cap.args[1] & MASK!(6)
} }
fn block_size(&self) -> usize { fn block_size(&self) -> usize {
@ -110,7 +111,7 @@ impl UntypedCap<'_> {
// Create new capabilities in slot // Create new capabilities in slot
for (i, slot) in slots.iter_mut().enumerate() { for (i, slot) in slots.iter_mut().enumerate() {
let addr = self.cte.cap.get().ptr + start_offset + i * obj_size; let addr = self.cte.cap.ptr + start_offset + i * obj_size;
let new_cap = match obj_type { let new_cap = match obj_type {
ObjectType::Untyped => UntypedCap::mint(0, obj_type.bits(user_obj_bits), self.is_device(), addr), 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), ObjectType::CNode => CNodeCap::mint(user_obj_bits, 0, 0, addr),
@ -121,7 +122,7 @@ impl UntypedCap<'_> {
_ => return Err(SysError::InvalidArgument), _ => return Err(SysError::InvalidArgument),
}; };
slot.cap.set(new_cap); slot.cap = new_cap;
self.append(slot); self.append(slot);
} }
@ -138,7 +139,7 @@ impl Debug for UntypedCap<'_> {
.field("free_offset", &self.free_offset()) .field("free_offset", &self.free_offset())
.field("block_bits", &self.block_bits()) .field("block_bits", &self.block_bits())
.field("is_device", &self.is_device()) .field("is_device", &self.is_device())
.field("ptr", &self.cte.cap.get().ptr) .field("ptr", &self.cte.cap.ptr)
.finish() .finish()
} }
} }