diff --git a/Cargo.toml b/Cargo.toml index adafa2a7dc..d5755aae45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "rmm" version = "0.1.0" authors = ["Jeremy Soller "] -edition = "2018" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/allocator/frame/buddy.rs b/src/allocator/frame/buddy.rs index b4c224f957..def1c87a84 100644 --- a/src/allocator/frame/buddy.rs +++ b/src/allocator/frame/buddy.rs @@ -54,22 +54,28 @@ impl BuddyEntry { } unsafe fn usage_addr(&self, page: usize) -> Option { - if page < self.pages() { - let phys = self.base.add(page * mem::size_of::()); - Some(A::phys_to_virt(phys)) - } else { - None + unsafe { + if page < self.pages() { + let phys = self.base.add(page * mem::size_of::()); + Some(A::phys_to_virt(phys)) + } else { + None + } } } unsafe fn usage(&self, page: usize) -> Option { - let addr = self.usage_addr(page)?; - Some(A::read(addr)) + unsafe { + let addr = self.usage_addr(page)?; + Some(A::read(addr)) + } } unsafe fn set_usage(&self, page: usize, usage: BuddyUsage) -> Option<()> { - let addr = self.usage_addr(page)?; - Some(A::write(addr, usage)) + unsafe { + let addr = self.usage_addr(page)?; + Some(A::write(addr, usage)) + } } } @@ -82,208 +88,216 @@ impl BuddyAllocator { const BUDDY_ENTRIES: usize = A::PAGE_SIZE / mem::size_of::>(); pub unsafe fn new(mut bump_allocator: BumpAllocator) -> Option { - // Allocate buddy table - let table_phys = bump_allocator.allocate_one()?; - let table_virt = A::phys_to_virt(table_phys); - for i in 0..(A::PAGE_SIZE / mem::size_of::>()) { - let virt = table_virt.add(i * mem::size_of::>()); - A::write(virt, BuddyEntry::::empty()); - } - - let allocator = Self { - table_virt, - phantom: PhantomData, - }; - - // Add areas to buddy table, combining areas when possible, and skipping frames used - // by the bump allocator - let mut offset = bump_allocator.offset(); - for old_area in bump_allocator.areas().iter() { - let mut area = old_area.clone(); - if offset >= area.size { - offset -= area.size; - continue; - } else if offset > 0 { - area.base = area.base.add(offset); - area.size -= offset; - offset = 0; - } + unsafe { + // Allocate buddy table + let table_phys = bump_allocator.allocate_one()?; + let table_virt = A::phys_to_virt(table_phys); for i in 0..(A::PAGE_SIZE / mem::size_of::>()) { + let virt = table_virt.add(i * mem::size_of::>()); + A::write(virt, BuddyEntry::::empty()); + } + + let allocator = Self { + table_virt, + phantom: PhantomData, + }; + + // Add areas to buddy table, combining areas when possible, and skipping frames used + // by the bump allocator + let mut offset = bump_allocator.offset(); + for old_area in bump_allocator.areas().iter() { + let mut area = old_area.clone(); + if offset >= area.size { + offset -= area.size; + continue; + } else if offset > 0 { + area.base = area.base.add(offset); + area.size -= offset; + offset = 0; + } + for i in 0..(A::PAGE_SIZE / mem::size_of::>()) { + let virt = table_virt.add(i * mem::size_of::>()); + let mut entry = A::read::>(virt); + let inserted = if area.base.add(area.size) == { entry.base } { + // Combine entry at start + entry.base = area.base; + entry.size += area.size; + true + } else if area.base == entry.base.add(entry.size) { + // Combine entry at end + entry.size += area.size; + true + } else if entry.size == 0 { + // Create new entry + entry.base = area.base; + entry.size = area.size; + true + } else { + false + }; + if inserted { + A::write(virt, entry); + break; + } + } + } + + //TODO: sort areas? + + // Allocate buddy maps + for i in 0..Self::BUDDY_ENTRIES { let virt = table_virt.add(i * mem::size_of::>()); let mut entry = A::read::>(virt); - let inserted = if area.base.add(area.size) == { entry.base } { - // Combine entry at start - entry.base = area.base; - entry.size += area.size; - true - } else if area.base == entry.base.add(entry.size) { - // Combine entry at end - entry.size += area.size; - true - } else if entry.size == 0 { - // Create new entry - entry.base = area.base; - entry.size = area.size; - true - } else { - false - }; - if inserted { - A::write(virt, entry); - break; - } - } - } - //TODO: sort areas? + // Only set up entries that have enough space for their own usage map + let usage_pages = entry.usage_pages(); + if entry.pages() > usage_pages { + // Mark all usage bytes as unused + let usage_start = entry.usage_addr(0)?; + for page in 0..usage_pages { + A::write_bytes(usage_start.add(page << A::PAGE_SHIFT), 0, A::PAGE_SIZE); + } - // Allocate buddy maps - for i in 0..Self::BUDDY_ENTRIES { - let virt = table_virt.add(i * mem::size_of::>()); - let mut entry = A::read::>(virt); - - // Only set up entries that have enough space for their own usage map - let usage_pages = entry.usage_pages(); - if entry.pages() > usage_pages { - // Mark all usage bytes as unused - let usage_start = entry.usage_addr(0)?; - for page in 0..usage_pages { - A::write_bytes(usage_start.add(page << A::PAGE_SHIFT), 0, A::PAGE_SIZE); + // Mark bytes used for usage as used + for page in 0..usage_pages { + entry.set_usage(page, BuddyUsage(1))?; + } } - // Mark bytes used for usage as used - for page in 0..usage_pages { - entry.set_usage(page, BuddyUsage(1))?; - } + // Skip the pages used for usage + entry.skip = usage_pages; + + // Set used pages to pages used for usage + entry.used = usage_pages; + + // Write updated entry + A::write(virt, entry); } - // Skip the pages used for usage - entry.skip = usage_pages; - - // Set used pages to pages used for usage - entry.used = usage_pages; - - // Write updated entry - A::write(virt, entry); + Some(allocator) } - - Some(allocator) } } impl FrameAllocator for BuddyAllocator { unsafe fn allocate(&mut self, count: FrameCount) -> Option { - if self.table_virt.data() == 0 { - return None; - } + unsafe { + if self.table_virt.data() == 0 { + return None; + } - for entry_i in 0..Self::BUDDY_ENTRIES { - let virt = self - .table_virt - .add(entry_i * mem::size_of::>()); - let mut entry = A::read::>(virt); + for entry_i in 0..Self::BUDDY_ENTRIES { + let virt = self + .table_virt + .add(entry_i * mem::size_of::>()); + let mut entry = A::read::>(virt); - let mut free_page = entry.skip; - let mut free_count = 0; - for page in entry.skip..entry.pages() { - let usage = entry.usage(page)?; - if usage.0 == 0 { - free_count += 1; + let mut free_page = entry.skip; + let mut free_count = 0; + for page in entry.skip..entry.pages() { + let usage = entry.usage(page)?; + if usage.0 == 0 { + free_count += 1; - if free_count == count.data() { - break; + if free_count == count.data() { + break; + } + } else { + free_page = page + 1; + free_count = 0; } - } else { - free_page = page + 1; - free_count = 0; + } + + if free_count == count.data() { + for page in free_page..free_page + free_count { + // Update usage + let mut usage = entry.usage(page)?; + usage.0 += 1; + entry.set_usage(page, usage); + + // Zero page + let page_phys = entry.base.add(page << A::PAGE_SHIFT); + let page_virt = A::phys_to_virt(page_phys); + A::write_bytes(page_virt, 0, A::PAGE_SIZE); + } + + // Update skip if necessary + if entry.skip == free_page { + entry.skip = free_page + free_count; + } + + // Update used page count + entry.used += free_count; + + // Write updated entry + A::write(virt, entry); + + return Some(entry.base.add(free_page << A::PAGE_SHIFT)); } } - if free_count == count.data() { - for page in free_page..free_page + free_count { - // Update usage - let mut usage = entry.usage(page)?; - usage.0 += 1; - entry.set_usage(page, usage); - - // Zero page - let page_phys = entry.base.add(page << A::PAGE_SHIFT); - let page_virt = A::phys_to_virt(page_phys); - A::write_bytes(page_virt, 0, A::PAGE_SIZE); - } - - // Update skip if necessary - if entry.skip == free_page { - entry.skip = free_page + free_count; - } - - // Update used page count - entry.used += free_count; - - // Write updated entry - A::write(virt, entry); - - return Some(entry.base.add(free_page << A::PAGE_SHIFT)); - } + None } - - None } unsafe fn free(&mut self, base: PhysicalAddress, count: FrameCount) { - if self.table_virt.data() == 0 { - return; - } + unsafe { + if self.table_virt.data() == 0 { + return; + } - let size = count.data() * A::PAGE_SIZE; - for i in 0..Self::BUDDY_ENTRIES { - let virt = self.table_virt.add(i * mem::size_of::>()); - let mut entry = A::read::>(virt); + let size = count.data() * A::PAGE_SIZE; + for i in 0..Self::BUDDY_ENTRIES { + let virt = self.table_virt.add(i * mem::size_of::>()); + let mut entry = A::read::>(virt); - if base >= { entry.base } && base.add(size) <= entry.base.add(entry.size) { - let start_page = (base.data() - { entry.base }.data()) >> A::PAGE_SHIFT; - for page in start_page..start_page + count.data() { - let mut usage = entry.usage(page).expect("failed to get usage during free"); + if base >= { entry.base } && base.add(size) <= entry.base.add(entry.size) { + let start_page = (base.data() - { entry.base }.data()) >> A::PAGE_SHIFT; + for page in start_page..start_page + count.data() { + let mut usage = entry.usage(page).expect("failed to get usage during free"); - if usage.0 > 0 { - usage.0 -= 1; - } else { - panic!("tried to free already free frame"); - } - - // If page was freed - if usage.0 == 0 { - // Update skip if necessary - if page < entry.skip { - entry.skip = page; + if usage.0 > 0 { + usage.0 -= 1; + } else { + panic!("tried to free already free frame"); } - // Update used page count - entry.used -= 1; + // If page was freed + if usage.0 == 0 { + // Update skip if necessary + if page < entry.skip { + entry.skip = page; + } + + // Update used page count + entry.used -= 1; + } + + entry + .set_usage(page, usage) + .expect("failed to set usage during free"); } - entry - .set_usage(page, usage) - .expect("failed to set usage during free"); + // Write updated entry + A::write(virt, entry); + + return; } - - // Write updated entry - A::write(virt, entry); - - return; } } } unsafe fn usage(&self) -> FrameUsage { - let mut total = 0; - let mut used = 0; - for i in 0..Self::BUDDY_ENTRIES { - let virt = self.table_virt.add(i * mem::size_of::>()); - let entry = A::read::>(virt); - total += entry.size >> A::PAGE_SHIFT; - used += entry.used; + unsafe { + let mut total = 0; + let mut used = 0; + for i in 0..Self::BUDDY_ENTRIES { + let virt = self.table_virt.add(i * mem::size_of::>()); + let entry = A::read::>(virt); + total += entry.size >> A::PAGE_SHIFT; + used += entry.used; + } + FrameUsage::new(FrameCount::new(used), FrameCount::new(total)) } - FrameUsage::new(FrameCount::new(used), FrameCount::new(total)) } } diff --git a/src/allocator/frame/bump.rs b/src/allocator/frame/bump.rs index ee897feb80..9985feff3a 100644 --- a/src/allocator/frame/bump.rs +++ b/src/allocator/frame/bump.rs @@ -11,7 +11,9 @@ pub struct BumpAllocator { impl BumpAllocator { pub fn new(mut areas: &'static [MemoryArea], mut offset: usize) -> Self { - while let Some(first) = areas.first() && first.size <= offset { + while let Some(first) = areas.first() + && first.size <= offset + { offset -= first.size; areas = &areas[1..]; } @@ -32,7 +34,9 @@ impl BumpAllocator { } pub fn abs_offset(&self) -> PhysicalAddress { let (areas, off) = self.cur_areas; - areas.first().map_or(PhysicalAddress::new(0), |a| a.base.add(off)) + areas + .first() + .map_or(PhysicalAddress::new(0), |a| a.base.add(off)) } pub fn offset(&self) -> usize { (unsafe { self.usage().total().data() - self.usage().free().data() }) * A::PAGE_SIZE @@ -41,21 +45,23 @@ impl BumpAllocator { impl FrameAllocator for BumpAllocator { unsafe fn allocate(&mut self, count: FrameCount) -> Option { - let req_size = count.data() * A::PAGE_SIZE; + unsafe { + let req_size = count.data() * A::PAGE_SIZE; - let block = loop { - let area = self.cur_areas.0.first()?; - let off = self.cur_areas.1; - if area.size - off < req_size { - self.cur_areas = (&self.cur_areas.0[1..], 0); - continue; - } - self.cur_areas.1 += req_size; + let block = loop { + let area = self.cur_areas.0.first()?; + let off = self.cur_areas.1; + if area.size - off < req_size { + self.cur_areas = (&self.cur_areas.0[1..], 0); + continue; + } + self.cur_areas.1 += req_size; - break area.base.add(off); - }; - A::write_bytes(A::phys_to_virt(block), 0, req_size); - Some(block) + break area.base.add(off); + }; + A::write_bytes(A::phys_to_virt(block), 0, req_size); + Some(block) + } } unsafe fn free(&mut self, _address: PhysicalAddress, _count: FrameCount) { @@ -65,6 +71,9 @@ impl FrameAllocator for BumpAllocator { unsafe fn usage(&self) -> FrameUsage { let total = self.orig_areas.0.iter().map(|a| a.size).sum::() - self.orig_areas.1; let free = self.cur_areas.0.iter().map(|a| a.size).sum::() - self.cur_areas.1; - FrameUsage::new(FrameCount::new((total - free) / A::PAGE_SIZE), FrameCount::new(total / A::PAGE_SIZE)) + FrameUsage::new( + FrameCount::new((total - free) / A::PAGE_SIZE), + FrameCount::new(total / A::PAGE_SIZE), + ) } } diff --git a/src/allocator/frame/mod.rs b/src/allocator/frame/mod.rs index 626ff41714..1260def01b 100644 --- a/src/allocator/frame/mod.rs +++ b/src/allocator/frame/mod.rs @@ -49,11 +49,13 @@ pub trait FrameAllocator { unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount); unsafe fn allocate_one(&mut self) -> Option { - self.allocate(FrameCount::new(1)) + unsafe { self.allocate(FrameCount::new(1)) } } unsafe fn free_one(&mut self, address: PhysicalAddress) { - self.free(address, FrameCount::new(1)); + unsafe { + self.free(address, FrameCount::new(1)); + } } unsafe fn usage(&self) -> FrameUsage; @@ -64,18 +66,18 @@ where T: FrameAllocator, { unsafe fn allocate(&mut self, count: FrameCount) -> Option { - T::allocate(self, count) + unsafe { T::allocate(self, count) } } unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount) { - T::free(self, address, count) + unsafe { T::free(self, address, count) } } unsafe fn allocate_one(&mut self) -> Option { - T::allocate_one(self) + unsafe { T::allocate_one(self) } } unsafe fn free_one(&mut self, address: PhysicalAddress) { - T::free_one(self, address) + unsafe { T::free_one(self, address) } } unsafe fn usage(&self) -> FrameUsage { - T::usage(self) + unsafe { T::usage(self) } } } diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs index 687294d3b5..118ac956ea 100644 --- a/src/arch/aarch64.rs +++ b/src/arch/aarch64.rs @@ -42,51 +42,59 @@ impl Arch for AArch64Arch { #[inline(always)] unsafe fn invalidate(address: VirtualAddress) { - asm!(" + unsafe { + asm!(" dsb ishst tlbi vaae1is, {} dsb ish isb ", in(reg) (address.data() >> Self::PAGE_SHIFT)); + } } #[inline(always)] unsafe fn invalidate_all() { - asm!( - " + unsafe { + asm!( + " dsb ishst tlbi vmalle1is dsb ish isb " - ); + ); + } } #[inline(always)] unsafe fn table(table_kind: TableKind) -> PhysicalAddress { - let address: usize; - match table_kind { - TableKind::User => { - asm!("mrs {0}, ttbr0_el1", out(reg) address); - } - TableKind::Kernel => { - asm!("mrs {0}, ttbr1_el1", out(reg) address); + unsafe { + let address: usize; + match table_kind { + TableKind::User => { + asm!("mrs {0}, ttbr0_el1", out(reg) address); + } + TableKind::Kernel => { + asm!("mrs {0}, ttbr1_el1", out(reg) address); + } } + PhysicalAddress::new(address) } - PhysicalAddress::new(address) } #[inline(always)] unsafe fn set_table(table_kind: TableKind, address: PhysicalAddress) { - match table_kind { - TableKind::User => { - asm!("msr ttbr0_el1, {0}", in(reg) address.data()); - } - TableKind::Kernel => { - asm!("msr ttbr1_el1, {0}", in(reg) address.data()); + unsafe { + match table_kind { + TableKind::User => { + asm!("msr ttbr0_el1, {0}", in(reg) address.data()); + } + TableKind::Kernel => { + asm!("msr ttbr1_el1, {0}", in(reg) address.data()); + } } + Self::invalidate_all(); } - Self::invalidate_all(); } fn virt_is_valid(_address: VirtualAddress) -> bool { diff --git a/src/arch/emulate.rs b/src/arch/emulate.rs index 3e381db676..f6f33cd171 100644 --- a/src/arch/emulate.rs +++ b/src/arch/emulate.rs @@ -34,76 +34,84 @@ impl Arch for EmulateArch { const ENTRY_FLAG_WRITE_COMBINING: usize = X8664Arch::ENTRY_FLAG_WRITE_COMBINING; unsafe fn init() -> &'static [MemoryArea] { - // Create machine with PAGE_ENTRIES pages offset mapped (2 MiB on x86_64) - let mut machine = Machine::new(MEMORY_SIZE); + unsafe { + // Create machine with PAGE_ENTRIES pages offset mapped (2 MiB on x86_64) + let mut machine = Machine::new(MEMORY_SIZE); - // PML4 index 256 (PHYS_OFFSET) link to PDP - let pml4 = 0; - let pdp = pml4 + Self::PAGE_SIZE; - let flags = Self::ENTRY_FLAG_READWRITE | Self::ENTRY_FLAG_PRESENT; - machine.write_phys::( - PhysicalAddress::new(pml4 + 256 * Self::PAGE_ENTRY_SIZE), - pdp | flags, - ); - - // PDP link to PD - let pd = pdp + Self::PAGE_SIZE; - machine.write_phys::(PhysicalAddress::new(pdp), pd | flags); - - // PD link to PT - let pt = pd + Self::PAGE_SIZE; - machine.write_phys::(PhysicalAddress::new(pd), pt | flags); - - // PT links to frames - for i in 0..Self::PAGE_ENTRIES { - let page = i * Self::PAGE_SIZE; + // PML4 index 256 (PHYS_OFFSET) link to PDP + let pml4 = 0; + let pdp = pml4 + Self::PAGE_SIZE; + let flags = Self::ENTRY_FLAG_READWRITE | Self::ENTRY_FLAG_PRESENT; machine.write_phys::( - PhysicalAddress::new(pt + i * Self::PAGE_ENTRY_SIZE), - page | flags, + PhysicalAddress::new(pml4 + 256 * Self::PAGE_ENTRY_SIZE), + pdp | flags, ); + + // PDP link to PD + let pd = pdp + Self::PAGE_SIZE; + machine.write_phys::(PhysicalAddress::new(pdp), pd | flags); + + // PD link to PT + let pt = pd + Self::PAGE_SIZE; + machine.write_phys::(PhysicalAddress::new(pd), pt | flags); + + // PT links to frames + for i in 0..Self::PAGE_ENTRIES { + let page = i * Self::PAGE_SIZE; + machine.write_phys::( + PhysicalAddress::new(pt + i * Self::PAGE_ENTRY_SIZE), + page | flags, + ); + } + + MACHINE = Some(machine); + + // Set table to pml4 + EmulateArch::set_table(TableKind::Kernel, PhysicalAddress::new(pml4)); + + &MEMORY_AREAS } - - MACHINE = Some(machine); - - // Set table to pml4 - EmulateArch::set_table(TableKind::Kernel, PhysicalAddress::new(pml4)); - - &MEMORY_AREAS } #[inline(always)] unsafe fn read(address: VirtualAddress) -> T { - MACHINE.as_ref().unwrap().read(address) + unsafe { MACHINE.as_ref().unwrap().read(address) } } #[inline(always)] unsafe fn write(address: VirtualAddress, value: T) { - MACHINE.as_mut().unwrap().write(address, value) + unsafe { MACHINE.as_mut().unwrap().write(address, value) } } #[inline(always)] unsafe fn write_bytes(address: VirtualAddress, value: u8, count: usize) { - MACHINE.as_mut().unwrap().write_bytes(address, value, count) + unsafe { MACHINE.as_mut().unwrap().write_bytes(address, value, count) } } #[inline(always)] unsafe fn invalidate(address: VirtualAddress) { - MACHINE.as_mut().unwrap().invalidate(address); + unsafe { + MACHINE.as_mut().unwrap().invalidate(address); + } } #[inline(always)] unsafe fn invalidate_all() { - MACHINE.as_mut().unwrap().invalidate_all(); + unsafe { + MACHINE.as_mut().unwrap().invalidate_all(); + } } #[inline(always)] unsafe fn table(_table_kind: TableKind) -> PhysicalAddress { - MACHINE.as_mut().unwrap().get_table() + unsafe { MACHINE.as_mut().unwrap().get_table() } } #[inline(always)] unsafe fn set_table(_table_kind: TableKind, address: PhysicalAddress) { - MACHINE.as_mut().unwrap().set_table(address); + unsafe { + MACHINE.as_mut().unwrap().set_table(address); + } } fn virt_is_valid(_address: VirtualAddress) -> bool { // TODO: Don't see why an emulated arch would have any problems with canonicalness... diff --git a/src/arch/mod.rs b/src/arch/mod.rs index cd68f09f2c..a5f92a80bc 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -65,25 +65,27 @@ pub trait Arch: Clone + Copy { #[inline(always)] unsafe fn read(address: VirtualAddress) -> T { - ptr::read(address.data() as *const T) + unsafe { ptr::read(address.data() as *const T) } } #[inline(always)] unsafe fn write(address: VirtualAddress, value: T) { - ptr::write(address.data() as *mut T, value) + unsafe { ptr::write(address.data() as *mut T, value) } } #[inline(always)] unsafe fn write_bytes(address: VirtualAddress, value: u8, count: usize) { - ptr::write_bytes(address.data() as *mut u8, value, count) + unsafe { ptr::write_bytes(address.data() as *mut u8, value, count) } } unsafe fn invalidate(address: VirtualAddress); #[inline(always)] unsafe fn invalidate_all() { - //TODO: this stub only works on x86_64, maybe make the arch implement this? - Self::set_table(TableKind::User, Self::table(TableKind::User)); + unsafe { + //TODO: this stub only works on x86_64, maybe make the arch implement this? + Self::set_table(TableKind::User, Self::table(TableKind::User)); + } } unsafe fn table(table_kind: TableKind) -> PhysicalAddress; diff --git a/src/arch/riscv64/sv39.rs b/src/arch/riscv64/sv39.rs index 31ade20c1e..5948d88da6 100644 --- a/src/arch/riscv64/sv39.rs +++ b/src/arch/riscv64/sv39.rs @@ -34,29 +34,37 @@ impl Arch for RiscV64Sv39Arch { #[inline(always)] unsafe fn invalidate(address: VirtualAddress) { - asm!("sfence.vma {}", in(reg) address.data()); + unsafe { + asm!("sfence.vma {}", in(reg) address.data()); + } } #[inline(always)] unsafe fn invalidate_all() { - asm!("sfence.vma"); + unsafe { + asm!("sfence.vma"); + } } #[inline(always)] unsafe fn table(_table_kind: TableKind) -> PhysicalAddress { - let satp: usize; - asm!("csrr {0}, satp", out(reg) satp); - PhysicalAddress::new( - (satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN - ) + unsafe { + let satp: usize; + asm!("csrr {0}, satp", out(reg) satp); + PhysicalAddress::new( + (satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN + ) + } } #[inline(always)] unsafe fn set_table(_table_kind: TableKind, address: PhysicalAddress) { - let satp = (8 << 60) | // Sv39 MODE + unsafe { + let satp = (8 << 60) | // Sv39 MODE (address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment) - asm!("csrw satp, {0}", in(reg) satp); - Self::invalidate_all(); + asm!("csrw satp, {0}", in(reg) satp); + Self::invalidate_all(); + } } fn virt_is_valid(address: VirtualAddress) -> bool { diff --git a/src/arch/riscv64/sv48.rs b/src/arch/riscv64/sv48.rs index 7e80ad0c3a..8d6e2faf0c 100644 --- a/src/arch/riscv64/sv48.rs +++ b/src/arch/riscv64/sv48.rs @@ -34,29 +34,37 @@ impl Arch for RiscV64Sv48Arch { #[inline(always)] unsafe fn invalidate(address: VirtualAddress) { - asm!("sfence.vma {}", in(reg) address.data()); + unsafe { + asm!("sfence.vma {}", in(reg) address.data()); + } } #[inline(always)] unsafe fn invalidate_all() { - asm!("sfence.vma"); + unsafe { + asm!("sfence.vma"); + } } #[inline(always)] unsafe fn table(_table_kind: TableKind) -> PhysicalAddress { - let satp: usize; - asm!("csrr {0}, satp", out(reg) satp); - PhysicalAddress::new( - (satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN - ) + unsafe { + let satp: usize; + asm!("csrr {0}, satp", out(reg) satp); + PhysicalAddress::new( + (satp & Self::ENTRY_ADDRESS_MASK) << Self::PAGE_SHIFT, // Convert from PPN + ) + } } #[inline(always)] unsafe fn set_table(_table_kind: TableKind, address: PhysicalAddress) { - let satp = (9 << 60) | // Sv48 MODE + unsafe { + let satp = (9 << 60) | // Sv48 MODE (address.data() >> Self::PAGE_SHIFT); // Convert to PPN (TODO: ensure alignment) - asm!("csrw satp, {0}", in(reg) satp); - Self::invalidate_all(); + asm!("csrw satp, {0}", in(reg) satp); + Self::invalidate_all(); + } } fn virt_is_valid(address: VirtualAddress) -> bool { diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index 3b0bacff0d..6bc5022388 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -32,19 +32,25 @@ impl Arch for X8664Arch { #[inline(always)] unsafe fn invalidate(address: VirtualAddress) { - asm!("invlpg [{0}]", in(reg) address.data()); + unsafe { + asm!("invlpg [{0}]", in(reg) address.data()); + } } #[inline(always)] unsafe fn table(_table_kind: TableKind) -> PhysicalAddress { - let address: usize; - asm!("mov {0}, cr3", out(reg) address); - PhysicalAddress::new(address) + unsafe { + let address: usize; + asm!("mov {0}, cr3", out(reg) address); + PhysicalAddress::new(address) + } } #[inline(always)] unsafe fn set_table(_table_kind: TableKind, address: PhysicalAddress) { - asm!("mov cr3, {0}", in(reg) address.data()); + unsafe { + asm!("mov cr3, {0}", in(reg) address.data()); + } } fn virt_is_valid(address: VirtualAddress) -> bool { diff --git a/src/main.rs b/src/main.rs index 86f5c67b60..a63c24f305 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,22 +23,24 @@ pub fn format_size(size: usize) -> String { #[allow(dead_code)] unsafe fn dump_tables(table: PageTable) { - let level = table.level(); - for i in 0..A::PAGE_ENTRIES { - if level == 0 { - if let Some(entry) = table.entry(i) { - if entry.present() { - let base = table.entry_base(i).unwrap(); - println!( - "0x{:X}: 0x{:X}", - base.data(), - entry.address().unwrap().data() - ); + unsafe { + let level = table.level(); + for i in 0..A::PAGE_ENTRIES { + if level == 0 { + if let Some(entry) = table.entry(i) { + if entry.present() { + let base = table.entry_base(i).unwrap(); + println!( + "0x{:X}: 0x{:X}", + base.data(), + entry.address().unwrap().data() + ); + } + } + } else { + if let Some(next) = table.next(i) { + dump_tables(next); } - } - } else { - if let Some(next) = table.next(i) { - dump_tables(next); } } } @@ -64,21 +66,25 @@ impl SlabNode { } pub unsafe fn insert(&mut self, phys: PhysicalAddress) { - let virt = A::phys_to_virt(phys); - A::write(virt, self.next); - self.next = phys; - self.count += 1; + unsafe { + let virt = A::phys_to_virt(phys); + A::write(virt, self.next); + self.next = phys; + self.count += 1; + } } pub unsafe fn remove(&mut self) -> Option { - if self.count > 0 { - let phys = self.next; - let virt = A::phys_to_virt(phys); - self.next = A::read(virt); - self.count -= 1; - Some(phys) - } else { - None + unsafe { + if self.count > 0 { + let phys = self.next; + let virt = A::phys_to_virt(phys); + self.next = A::read(virt); + self.count -= 1; + Some(phys) + } else { + None + } } } } @@ -91,57 +97,63 @@ pub struct SlabAllocator { impl SlabAllocator { pub unsafe fn new(areas: &'static [MemoryArea], offset: usize) -> Self { - let mut allocator = Self { - nodes: [ - SlabNode::empty(), - SlabNode::empty(), - SlabNode::empty(), - SlabNode::empty(), - ], - phantom: PhantomData, - }; + unsafe { + let mut allocator = Self { + nodes: [ + SlabNode::empty(), + SlabNode::empty(), + SlabNode::empty(), + SlabNode::empty(), + ], + phantom: PhantomData, + }; - // Add unused areas to free lists - let mut area_offset = offset; - for area in areas.iter() { - if area_offset < area.size { - let area_base = area.base.add(area_offset); - let area_size = area.size - area_offset; - allocator.free(area_base, area_size); - area_offset = 0; - } else { - area_offset -= area.size; + // Add unused areas to free lists + let mut area_offset = offset; + for area in areas.iter() { + if area_offset < area.size { + let area_base = area.base.add(area_offset); + let area_size = area.size - area_offset; + allocator.free(area_base, area_size); + area_offset = 0; + } else { + area_offset -= area.size; + } } - } - allocator + allocator + } } pub unsafe fn allocate(&mut self, size: usize) -> Option { - for level in 0..A::PAGE_LEVELS - 1 { - let level_shift = level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT; - let level_size = 1 << level_shift; - if size <= level_size { - if let Some(base) = self.nodes[level].remove() { - self.free(base.add(size), level_size - size); - return Some(base); + unsafe { + for level in 0..A::PAGE_LEVELS - 1 { + let level_shift = level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT; + let level_size = 1 << level_shift; + if size <= level_size { + if let Some(base) = self.nodes[level].remove() { + self.free(base.add(size), level_size - size); + return Some(base); + } } } + None } - None } //TODO: This causes fragmentation, since neighbors are not identified //TODO: remainders less than PAGE_SIZE will be lost pub unsafe fn free(&mut self, mut base: PhysicalAddress, mut size: usize) { - for level in (0..A::PAGE_LEVELS - 1).rev() { - let level_shift = level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT; - let level_size = 1 << level_shift; - while size >= level_size { - println!("Add {:X} {}", base.data(), format_size(level_size)); - self.nodes[level].insert(base); - base = base.add(level_size); - size -= level_size; + unsafe { + for level in (0..A::PAGE_LEVELS - 1).rev() { + let level_shift = level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT; + let level_size = 1 << level_shift; + while size >= level_size { + println!("Add {:X} {}", base.data(), format_size(level_size)); + self.nodes[level].insert(base); + base = base.add(level_size); + size -= level_size; + } } } } @@ -158,133 +170,137 @@ impl SlabAllocator { } unsafe fn new_tables(areas: &'static [MemoryArea]) { - // First, calculate how much memory we have - let mut size = 0; - for area in areas.iter() { - size += area.size; - } - - println!("Memory: {}", format_size(size)); - - // Create a basic allocator for the first pages - let mut bump_allocator = BumpAllocator::::new(areas, 0); - - { - // Map all physical areas at PHYS_OFFSET - let mut mapper = PageMapper::::create(TableKind::Kernel, &mut bump_allocator) - .expect("failed to create Mapper"); + unsafe { + // First, calculate how much memory we have + let mut size = 0; for area in areas.iter() { - for i in 0..area.size / A::PAGE_SIZE { - let phys = area.base.add(i * A::PAGE_SIZE); - let virt = A::phys_to_virt(phys); - let flush = mapper - .map_phys(virt, phys, PageFlags::::new().write(true)) - .expect("failed to map page to frame"); - flush.ignore(); // Not the active table - } + size += area.size; } - // Use the new table - mapper.make_current(); - } + println!("Memory: {}", format_size(size)); - // Create the physical memory map - let offset = bump_allocator.offset(); - println!("Permanently used: {}", format_size(offset)); + // Create a basic allocator for the first pages + let mut bump_allocator = BumpAllocator::::new(areas, 0); - let mut allocator = BuddyAllocator::::new(bump_allocator).unwrap(); - - for i in 0..16 { { - let phys_opt = allocator.allocate_one(); - println!("page {}: {:X?}", i, phys_opt); - if i % 3 == 0 { - if let Some(phys) = phys_opt { - println!("free {}: {:X?}", i, phys_opt); - allocator.free_one(phys); + // Map all physical areas at PHYS_OFFSET + let mut mapper = PageMapper::::create(TableKind::Kernel, &mut bump_allocator) + .expect("failed to create Mapper"); + for area in areas.iter() { + for i in 0..area.size / A::PAGE_SIZE { + let phys = area.base.add(i * A::PAGE_SIZE); + let virt = A::phys_to_virt(phys); + let flush = mapper + .map_phys(virt, phys, PageFlags::::new().write(true)) + .expect("failed to map page to frame"); + flush.ignore(); // Not the active table + } + } + + // Use the new table + mapper.make_current(); + } + + // Create the physical memory map + let offset = bump_allocator.offset(); + println!("Permanently used: {}", format_size(offset)); + + let mut allocator = BuddyAllocator::::new(bump_allocator).unwrap(); + + for i in 0..16 { + { + let phys_opt = allocator.allocate_one(); + println!("page {}: {:X?}", i, phys_opt); + if i % 3 == 0 { + if let Some(phys) = phys_opt { + println!("free {}: {:X?}", i, phys_opt); + allocator.free_one(phys); + } + } + } + + { + let phys_opt = allocator.allocate(FrameCount::new(16)); + println!("page*16 {}: {:X?}", i, phys_opt); + if i % 2 == 0 { + if let Some(phys) = phys_opt { + println!("free*16 {}: {:X?}", i, phys_opt); + allocator.free(phys, FrameCount::new(16)); + } } } } - { - let phys_opt = allocator.allocate(FrameCount::new(16)); - println!("page*16 {}: {:X?}", i, phys_opt); - if i % 2 == 0 { - if let Some(phys) = phys_opt { - println!("free*16 {}: {:X?}", i, phys_opt); - allocator.free(phys, FrameCount::new(16)); - } - } + let mut mapper = PageMapper::::current(TableKind::Kernel, &mut allocator); + let mut flush_all = PageFlushAll::new(); + for i in 0..16 { + let virt = VirtualAddress::new(MEGABYTE + i * A::PAGE_SIZE); + let flush = mapper + .map(virt, PageFlags::::new().user(true).write(true)) + .expect("failed to map page"); + flush_all.consume(flush); } - } + flush_all.flush(); - let mut mapper = PageMapper::::current(TableKind::Kernel, &mut allocator); - let mut flush_all = PageFlushAll::new(); - for i in 0..16 { - let virt = VirtualAddress::new(MEGABYTE + i * A::PAGE_SIZE); - let flush = mapper - .map(virt, PageFlags::::new().user(true).write(true)) - .expect("failed to map page"); - flush_all.consume(flush); - } - flush_all.flush(); + let mut flush_all = PageFlushAll::new(); + for i in 0..16 { + let virt = VirtualAddress::new(MEGABYTE + i * A::PAGE_SIZE); + let flush = mapper.unmap(virt, false).expect("failed to unmap page"); + flush_all.consume(flush); + } + flush_all.flush(); - let mut flush_all = PageFlushAll::new(); - for i in 0..16 { - let virt = VirtualAddress::new(MEGABYTE + i * A::PAGE_SIZE); - let flush = mapper.unmap(virt, false).expect("failed to unmap page"); - flush_all.consume(flush); + let usage = allocator.usage(); + println!("Allocator usage:"); + println!( + " Used: {}", + format_size(usage.used().data() * A::PAGE_SIZE) + ); + println!( + " Free: {}", + format_size(usage.free().data() * A::PAGE_SIZE) + ); + println!( + " Total: {}", + format_size(usage.total().data() * A::PAGE_SIZE) + ); } - flush_all.flush(); - - let usage = allocator.usage(); - println!("Allocator usage:"); - println!( - " Used: {}", - format_size(usage.used().data() * A::PAGE_SIZE) - ); - println!( - " Free: {}", - format_size(usage.free().data() * A::PAGE_SIZE) - ); - println!( - " Total: {}", - format_size(usage.total().data() * A::PAGE_SIZE) - ); } unsafe fn inner() { - let areas = A::init(); + unsafe { + let areas = A::init(); - // Debug table - //dump_tables(PageTable::::top()); + // Debug table + //dump_tables(PageTable::::top()); - new_tables::(areas); + new_tables::(areas); - //dump_tables(PageTable::::top()); + //dump_tables(PageTable::::top()); - for i in &[1, 2, 4, 8, 16, 32] { - let phys = PhysicalAddress::new(i * MEGABYTE); - let virt = A::phys_to_virt(phys); + for i in &[1, 2, 4, 8, 16, 32] { + let phys = PhysicalAddress::new(i * MEGABYTE); + let virt = A::phys_to_virt(phys); - // Test read - println!( - "0x{:X} (0x{:X}) = 0x{:X}", - virt.data(), - phys.data(), - A::read::(virt) - ); + // Test read + println!( + "0x{:X} (0x{:X}) = 0x{:X}", + virt.data(), + phys.data(), + A::read::(virt) + ); - // Test write - A::write::(virt, 0x5A); + // Test write + A::write::(virt, 0x5A); - // Test read - println!( - "0x{:X} (0x{:X}) = 0x{:X}", - virt.data(), - phys.data(), - A::read::(virt) - ); + // Test read + println!( + "0x{:X} (0x{:X}) = 0x{:X}", + virt.data(), + phys.data(), + A::read::(virt) + ); + } } } diff --git a/src/page/mapper.rs b/src/page/mapper.rs index a6aa726be8..27e2b936e7 100644 --- a/src/page/mapper.rs +++ b/src/page/mapper.rs @@ -23,13 +23,17 @@ impl PageMapper { } pub unsafe fn create(table_kind: TableKind, mut allocator: F) -> Option { - let table_addr = allocator.allocate_one()?; - Some(Self::new(table_kind, table_addr, allocator)) + unsafe { + let table_addr = allocator.allocate_one()?; + Some(Self::new(table_kind, table_addr, allocator)) + } } pub unsafe fn current(table_kind: TableKind, allocator: F) -> Self { - let table_addr = A::table(table_kind); - Self::new(table_kind, table_addr, allocator) + unsafe { + let table_addr = A::table(table_kind); + Self::new(table_kind, table_addr, allocator) + } } pub fn is_current(&self) -> bool { @@ -37,7 +41,9 @@ impl PageMapper { } pub unsafe fn make_current(&self) { - A::set_table(self.table_kind, self.table_addr); + unsafe { + A::set_table(self.table_kind, self.table_addr); + } } pub fn table(&self) -> PageTable { @@ -59,33 +65,37 @@ impl PageMapper { virt: VirtualAddress, f: impl FnOnce(PhysicalAddress, PageFlags) -> (PhysicalAddress, PageFlags), ) -> Option<(PageFlags, PhysicalAddress, PageFlush)> { - self.visit(virt, |p1, i| { - let old_entry = p1.entry(i)?; - let old_phys = old_entry.address().ok()?; - let old_flags = old_entry.flags(); - let (new_phys, new_flags) = f(old_phys, old_flags); - // TODO: Higher-level PageEntry::new interface? - let new_entry = PageEntry::new(new_phys.data(), new_flags.data()); - p1.set_entry(i, new_entry); - Some((old_flags, old_phys, PageFlush::new(virt))) - }) - .flatten() + unsafe { + self.visit(virt, |p1, i| { + let old_entry = p1.entry(i)?; + let old_phys = old_entry.address().ok()?; + let old_flags = old_entry.flags(); + let (new_phys, new_flags) = f(old_phys, old_flags); + // TODO: Higher-level PageEntry::new interface? + let new_entry = PageEntry::new(new_phys.data(), new_flags.data()); + p1.set_entry(i, new_entry); + Some((old_flags, old_phys, PageFlush::new(virt))) + }) + .flatten() + } } pub unsafe fn remap_with( &mut self, virt: VirtualAddress, map_flags: impl FnOnce(PageFlags) -> PageFlags, ) -> Option<(PageFlags, PhysicalAddress, PageFlush)> { - self.remap_with_full(virt, |same_phys, old_flags| { - (same_phys, map_flags(old_flags)) - }) + unsafe { + self.remap_with_full(virt, |same_phys, old_flags| { + (same_phys, map_flags(old_flags)) + }) + } } pub unsafe fn remap( &mut self, virt: VirtualAddress, flags: PageFlags, ) -> Option> { - self.remap_with(virt, |_| flags).map(|(_, _, flush)| flush) + unsafe { self.remap_with(virt, |_| flags).map(|(_, _, flush)| flush) } } pub unsafe fn map( @@ -93,8 +103,10 @@ impl PageMapper { virt: VirtualAddress, flags: PageFlags, ) -> Option> { - let phys = self.allocator.allocate_one()?; - self.map_phys(virt, phys, flags) + unsafe { + let phys = self.allocator.allocate_one()?; + self.map_phys(virt, phys, flags) + } } pub unsafe fn map_phys( @@ -103,34 +115,36 @@ impl PageMapper { phys: PhysicalAddress, flags: PageFlags, ) -> Option> { - //TODO: verify virt and phys are aligned - //TODO: verify flags have correct bits - let entry = PageEntry::new(phys.data(), flags.data()); - let mut table = self.table(); - loop { - let i = table.index_of(virt)?; - if table.level() == 0 { - //TODO: check for overwriting entry - table.set_entry(i, entry); - return Some(PageFlush::new(virt)); - } else { - let next_opt = table.next(i); - let next = match next_opt { - Some(some) => some, - None => { - let next_phys = self.allocator.allocate_one()?; - //TODO: correct flags? - let flags = A::ENTRY_FLAG_DEFAULT_TABLE - | if virt.kind() == TableKind::User { - A::ENTRY_FLAG_TABLE_USER - } else { - 0 - }; - table.set_entry(i, PageEntry::new(next_phys.data(), flags)); - table.next(i)? - } - }; - table = next; + unsafe { + //TODO: verify virt and phys are aligned + //TODO: verify flags have correct bits + let entry = PageEntry::new(phys.data(), flags.data()); + let mut table = self.table(); + loop { + let i = table.index_of(virt)?; + if table.level() == 0 { + //TODO: check for overwriting entry + table.set_entry(i, entry); + return Some(PageFlush::new(virt)); + } else { + let next_opt = table.next(i); + let next = match next_opt { + Some(some) => some, + None => { + let next_phys = self.allocator.allocate_one()?; + //TODO: correct flags? + let flags = A::ENTRY_FLAG_DEFAULT_TABLE + | if virt.kind() == TableKind::User { + A::ENTRY_FLAG_TABLE_USER + } else { + 0 + }; + table.set_entry(i, PageEntry::new(next_phys.data(), flags)); + table.next(i)? + } + }; + table = next; + } } } } @@ -139,8 +153,10 @@ impl PageMapper { phys: PhysicalAddress, flags: PageFlags, ) -> Option<(VirtualAddress, PageFlush)> { - let virt = A::phys_to_virt(phys); - self.map_phys(virt, phys, flags).map(|flush| (virt, flush)) + unsafe { + let virt = A::phys_to_virt(phys); + self.map_phys(virt, phys, flags).map(|flush| (virt, flush)) + } } fn visit( &self, @@ -169,9 +185,11 @@ impl PageMapper { virt: VirtualAddress, unmap_parents: bool, ) -> Option> { - let (old, _, flush) = self.unmap_phys(virt, unmap_parents)?; - self.allocator.free_one(old); - Some(flush) + unsafe { + let (old, _, flush) = self.unmap_phys(virt, unmap_parents)?; + self.allocator.free_one(old); + Some(flush) + } } pub unsafe fn unmap_phys( @@ -179,11 +197,13 @@ impl PageMapper { virt: VirtualAddress, unmap_parents: bool, ) -> Option<(PhysicalAddress, PageFlags, PageFlush)> { - //TODO: verify virt is aligned - let mut table = self.table(); - let level = table.level(); - unmap_phys_inner(virt, &mut table, level, unmap_parents, &mut self.allocator) - .map(|(pa, pf)| (pa, pf, PageFlush::new(virt))) + unsafe { + //TODO: verify virt is aligned + let mut table = self.table(); + let level = table.level(); + unmap_phys_inner(virt, &mut table, level, unmap_parents, &mut self.allocator) + .map(|(pa, pf)| (pa, pf, PageFlush::new(virt))) + } } } unsafe fn unmap_phys_inner( @@ -193,35 +213,38 @@ unsafe fn unmap_phys_inner( unmap_parents: bool, allocator: &mut impl FrameAllocator, ) -> Option<(PhysicalAddress, PageFlags)> { - let i = table.index_of(virt)?; + unsafe { + let i = table.index_of(virt)?; - if table.level() == 0 { - let entry_opt = table.entry(i); - table.set_entry(i, PageEntry::new(0, 0)); - let entry = entry_opt?; + if table.level() == 0 { + let entry_opt = table.entry(i); + table.set_entry(i, PageEntry::new(0, 0)); + let entry = entry_opt?; - Some((entry.address().ok()?, entry.flags())) - } else { - let mut subtable = table.next(i)?; + Some((entry.address().ok()?, entry.flags())) + } else { + let mut subtable = table.next(i)?; - let res = unmap_phys_inner(virt, &mut subtable, initial_level, unmap_parents, allocator)?; + let res = + unmap_phys_inner(virt, &mut subtable, initial_level, unmap_parents, allocator)?; - //TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, - // as these mappings may become out of sync - if unmap_parents { - // TODO: Use a counter? This would reduce the remaining number of available bits, but could be - // faster (benchmark is needed). - let is_still_populated = (0..A::PAGE_ENTRIES) - .map(|j| subtable.entry(j).expect("must be within bounds")) - .any(|e| e.present()); + //TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, + // as these mappings may become out of sync + if unmap_parents { + // TODO: Use a counter? This would reduce the remaining number of available bits, but could be + // faster (benchmark is needed). + let is_still_populated = (0..A::PAGE_ENTRIES) + .map(|j| subtable.entry(j).expect("must be within bounds")) + .any(|e| e.present()); - if !is_still_populated { - allocator.free_one(subtable.phys()); - table.set_entry(i, PageEntry::new(0, 0)); + if !is_still_populated { + allocator.free_one(subtable.phys()); + table.set_entry(i, PageEntry::new(0, 0)); + } } - } - Some(res) + Some(res) + } } } impl core::fmt::Debug for PageMapper { diff --git a/src/page/table.rs b/src/page/table.rs index 70d281543d..c6d377a28e 100644 --- a/src/page/table.rs +++ b/src/page/table.rs @@ -21,11 +21,13 @@ impl PageTable { } pub unsafe fn top(table_kind: TableKind) -> Self { - Self::new( - VirtualAddress::new(0), - A::table(table_kind), - A::PAGE_LEVELS - 1, - ) + unsafe { + Self::new( + VirtualAddress::new(0), + A::table(table_kind), + A::PAGE_LEVELS - 1, + ) + } } pub fn base(&self) -> VirtualAddress { @@ -41,16 +43,18 @@ impl PageTable { } pub unsafe fn virt(&self) -> VirtualAddress { - A::phys_to_virt(self.phys) + unsafe { + A::phys_to_virt(self.phys) - // Recursive mapping - // let mut addr = 0xFFFF_FFFF_FFFF_F000; - // for level in (self.level + 1 .. A::PAGE_LEVELS).rev() { - // let index = (self.base.0 >> (level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT)) & A::PAGE_ENTRY_MASK; - // addr <<= A::PAGE_ENTRY_SHIFT; - // addr |= index << A::PAGE_SHIFT; - // } - // VirtualAddress::new(addr) + // Recursive mapping + // let mut addr = 0xFFFF_FFFF_FFFF_F000; + // for level in (self.level + 1 .. A::PAGE_LEVELS).rev() { + // let index = (self.base.0 >> (level * A::PAGE_ENTRY_SHIFT + A::PAGE_SHIFT)) & A::PAGE_ENTRY_MASK; + // addr <<= A::PAGE_ENTRY_SHIFT; + // addr |= index << A::PAGE_SHIFT; + // } + // VirtualAddress::new(addr) + } } pub fn entry_base(&self, i: usize) -> Option { @@ -63,22 +67,28 @@ impl PageTable { } pub unsafe fn entry_virt(&self, i: usize) -> Option { - if i < A::PAGE_ENTRIES { - Some(self.virt().add(i * A::PAGE_ENTRY_SIZE)) - } else { - None + unsafe { + if i < A::PAGE_ENTRIES { + Some(self.virt().add(i * A::PAGE_ENTRY_SIZE)) + } else { + None + } } } pub unsafe fn entry(&self, i: usize) -> Option> { - let addr = self.entry_virt(i)?; - Some(PageEntry::from_data(A::read::(addr))) + unsafe { + let addr = self.entry_virt(i)?; + Some(PageEntry::from_data(A::read::(addr))) + } } pub unsafe fn set_entry(&mut self, i: usize, entry: PageEntry) -> Option<()> { - let addr = self.entry_virt(i)?; - A::write::(addr, entry.data()); - Some(()) + unsafe { + let addr = self.entry_virt(i)?; + A::write::(addr, entry.data()); + Some(()) + } } pub unsafe fn index_of(&self, address: VirtualAddress) -> Option { @@ -98,14 +108,16 @@ impl PageTable { } pub unsafe fn next(&self, i: usize) -> Option { - if self.level == 0 { - return None; - } + unsafe { + if self.level == 0 { + return None; + } - Some(PageTable::new( - self.entry_base(i)?, - self.entry(i)?.address().ok()?, - self.level - 1, - )) + Some(PageTable::new( + self.entry_base(i)?, + self.entry(i)?.address().ok()?, + self.level - 1, + )) + } } }