diff --git a/Cargo.toml b/Cargo.toml index f470aac..e2186ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["hypervisor", "address-space"] license = "Apache-2.0" name = "axaddrspace" repository = "https://github.com/arceos-hypervisor/axaddrspace" -version = "0.2.0" +version = "0.3.0" [features] arm-el2 = ["page_table_entry/arm-el2"] @@ -26,11 +26,11 @@ log = "0.4" numeric-enum-macro = "0.2" # Operating system independent modules provided by ArceOS. -axerrno = "0.1.0" +axerrno = "0.2.0" memory_addr = "0.4" memory_set = "0.4" -page_table_entry = "0.5" -page_table_multiarch = "0.5" +page_table_entry = "0.6" +page_table_multiarch = "0.6" [target.'cfg(any(target_arch = "x86_64", doc))'.dependencies] x86 = "0.52" @@ -40,4 +40,3 @@ lazy_static = "1.5" spin = "0.10" assert_matches = "1.5.0" axin = "0.1.0" - diff --git a/src/address_space/backend/alloc.rs b/src/address_space/backend/alloc.rs index 65aa0f8..9f493d9 100644 --- a/src/address_space/backend/alloc.rs +++ b/src/address_space/backend/alloc.rs @@ -61,7 +61,6 @@ impl Backend { size, MappingFlags::empty(), false, - false, ) .is_ok() } @@ -76,7 +75,7 @@ impl Backend { ) -> bool { debug!("unmap_alloc: [{:#x}, {:#x})", start, start + size); for addr in PageIter4K::new(start, start + size).unwrap() { - if let Ok((frame, page_size)) = pt.unmap(addr) { + if let Ok((frame, _, page_size)) = pt.unmap(addr) { // Deallocate the physical frame if there is a mapping in the // page table. if page_size.is_huge() { diff --git a/src/address_space/backend/linear.rs b/src/address_space/backend/linear.rs index 0ef10e6..baf44fe 100644 --- a/src/address_space/backend/linear.rs +++ b/src/address_space/backend/linear.rs @@ -47,7 +47,6 @@ impl Backend { size, flags, true, - true, ) .is_ok() } @@ -60,6 +59,6 @@ impl Backend { _pa_va_offset: usize, ) -> bool { debug!("unmap_linear: [{:#x}, {:#x})", start, start + size); - pt.unmap_region(start, size, true).is_ok() + pt.unmap_region(start, size).is_ok() } } diff --git a/src/address_space/backend/mod.rs b/src/address_space/backend/mod.rs index 44b6c85..8a7916b 100644 --- a/src/address_space/backend/mod.rs +++ b/src/address_space/backend/mod.rs @@ -98,7 +98,7 @@ impl MappingBackend for Backend { new_flags: MappingFlags, page_table: &mut PageTable, ) -> bool { - page_table.protect_region(start, size, new_flags, true) + page_table.protect_region(start, size, new_flags) } } diff --git a/src/address_space/mod.rs b/src/address_space/mod.rs index 067f312..8cf6ebd 100644 --- a/src/address_space/mod.rs +++ b/src/address_space/mod.rs @@ -15,7 +15,7 @@ use alloc::vec::Vec; use core::fmt; -use axerrno::ax_err; +use axerrno::{AxResult, ax_err}; use memory_addr::{MemoryAddr, PhysAddr, is_aligned_4k}; use memory_set::{MemoryArea, MemorySet}; use page_table_multiarch::PagingHandler; @@ -25,7 +25,6 @@ use crate::{GuestPhysAddr, GuestPhysAddrRange, mapping_err_to_ax_err}; mod backend; -pub use axerrno::{AxError, AxResult}; pub use backend::Backend; pub use page_table_entry::MappingFlags; diff --git a/src/lib.rs b/src/lib.rs index f983299..e91f573 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ pub use hal::AxMmHal; pub use memory_accessor::GuestMemoryAccessor; +use axerrno::AxError; use memory_set::MappingError; /// Information about nested page faults. diff --git a/src/npt/arch/x86_64.rs b/src/npt/arch/x86_64.rs index e06a2a1..65b6261 100644 --- a/src/npt/arch/x86_64.rs +++ b/src/npt/arch/x86_64.rs @@ -190,6 +190,7 @@ impl PagingMetaData for ExtendedPageTableMetadata { // Under the x86 architecture, the flush_tlb operation will invoke the ring0 instruction, // causing the test to trigger a SIGSEGV exception. + #[allow(unused_variables)] fn flush_tlb(vaddr: Option) { #[cfg(not(test))] if let Some(vaddr) = vaddr { diff --git a/src/npt/mod.rs b/src/npt/mod.rs index 614b23f..5346be0 100644 --- a/src/npt/mod.rs +++ b/src/npt/mod.rs @@ -16,20 +16,21 @@ use axerrno::{ax_err, ax_err_type}; use memory_addr::PhysAddr; use memory_set::MappingError; use page_table_entry::MappingFlags; -use page_table_multiarch::PagingHandler; +use page_table_multiarch::{PageSize, PagingHandler}; use crate::GuestPhysAddr; cfg_if::cfg_if! { if #[cfg(target_arch = "x86_64")] { pub type NestedPageTableL4 = arch::ExtendedPageTable; - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + /// RISC-V Level 3 nested page table (Sv39, x4 not supported) pub type NestedPageTableL3 = page_table_multiarch::PageTable64, arch::Rv64PTE, H>; - pub type NestedPageTableL4 = page_table_multiarch::PageTable64, arch::Rv64PTE, H>; + /// RISC-V Level 4 nested page table (Sv48, x4 not supported) + pub type NestedPageTableL4 = page_table_multiarch::PageTable64, arch::Rv64PTE, H>; } else if #[cfg(target_arch = "aarch64")] { - /// AArch64 Level 3 nested page table type alias. + /// AArch64 Level 3 nested page table type alias. pub type NestedPageTableL3 = page_table_multiarch::PageTable64; /// AArch64 Level 4 nested page table type alias. @@ -51,8 +52,6 @@ impl NestedPageTable { 3 => { #[cfg(not(target_arch = "x86_64"))] { - use axerrno::ax_err_type; - let res = NestedPageTableL3::try_new().map_err(|_| ax_err_type!(NoMemory))?; Ok(NestedPageTable::L3(res)) } @@ -69,7 +68,7 @@ impl NestedPageTable { } } - pub fn root_paddr(&self) -> memory_addr::PhysAddr { + pub const fn root_paddr(&self) -> PhysAddr { match self { #[cfg(not(target_arch = "x86_64"))] NestedPageTable::L3(pt) => pt.root_paddr(), @@ -81,22 +80,20 @@ impl NestedPageTable { pub fn map( &mut self, vaddr: crate::GuestPhysAddr, - paddr: memory_addr::PhysAddr, - size: page_table_multiarch::PageSize, + paddr: PhysAddr, + size: PageSize, flags: page_table_entry::MappingFlags, ) -> memory_set::MappingResult { match self { #[cfg(not(target_arch = "x86_64"))] - NestedPageTable::L3(pt) => { - pt.map(vaddr, paddr, size, flags) - .map_err(|_| MappingError::BadState)? - .flush(); - } - NestedPageTable::L4(pt) => { - pt.map(vaddr, paddr, size, flags) - .map_err(|_| MappingError::BadState)? - .flush(); - } + NestedPageTable::L3(pt) => pt + .cursor() + .map(vaddr, paddr, size, flags) + .map_err(|_| MappingError::BadState)?, + NestedPageTable::L4(pt) => pt + .cursor() + .map(vaddr, paddr, size, flags) + .map_err(|_| MappingError::BadState)?, } Ok(()) } @@ -105,19 +102,11 @@ impl NestedPageTable { pub fn unmap( &mut self, vaddr: GuestPhysAddr, - ) -> memory_set::MappingResult<(memory_addr::PhysAddr, page_table_multiarch::PageSize)> { + ) -> memory_set::MappingResult<(PhysAddr, MappingFlags, PageSize)> { match self { #[cfg(not(target_arch = "x86_64"))] - NestedPageTable::L3(pt) => { - let (addr, size, f) = pt.unmap(vaddr).map_err(|_| MappingError::BadState)?; - f.flush(); - Ok((addr, size)) - } - NestedPageTable::L4(pt) => { - let (addr, size, f) = pt.unmap(vaddr).map_err(|_| MappingError::BadState)?; - f.flush(); - Ok((addr, size)) - } + NestedPageTable::L3(pt) => pt.cursor().unmap(vaddr).map_err(|_| MappingError::BadState), + NestedPageTable::L4(pt) => pt.cursor().unmap(vaddr).map_err(|_| MappingError::BadState), } } @@ -129,43 +118,33 @@ impl NestedPageTable { size: usize, flags: MappingFlags, allow_huge: bool, - flush_tlb_by_page: bool, ) -> memory_set::MappingResult { match self { #[cfg(not(target_arch = "x86_64"))] - NestedPageTable::L3(pt) => { - pt.map_region(vaddr, get_paddr, size, flags, allow_huge, flush_tlb_by_page) - .map_err(|_| MappingError::BadState)? - .flush_all(); - } - NestedPageTable::L4(pt) => { - pt.map_region(vaddr, get_paddr, size, flags, allow_huge, flush_tlb_by_page) - .map_err(|_| MappingError::BadState)? - .flush_all(); - } + NestedPageTable::L3(pt) => pt + .cursor() + .map_region(vaddr, get_paddr, size, flags, allow_huge) + .map_err(|_| MappingError::BadState)?, + NestedPageTable::L4(pt) => pt + .cursor() + .map_region(vaddr, get_paddr, size, flags, allow_huge) + .map_err(|_| MappingError::BadState)?, } Ok(()) } /// Unmaps a region. - pub fn unmap_region( - &mut self, - start: GuestPhysAddr, - size: usize, - flush: bool, - ) -> memory_set::MappingResult { + pub fn unmap_region(&mut self, start: GuestPhysAddr, size: usize) -> memory_set::MappingResult { match self { #[cfg(not(target_arch = "x86_64"))] - NestedPageTable::L3(pt) => { - pt.unmap_region(start, size, flush) - .map_err(|_| MappingError::BadState)? - .ignore(); - } - NestedPageTable::L4(pt) => { - pt.unmap_region(start, size, flush) - .map_err(|_| MappingError::BadState)? - .ignore(); - } + NestedPageTable::L3(pt) => pt + .cursor() + .unmap_region(start, size) + .map_err(|_| MappingError::BadState)?, + NestedPageTable::L4(pt) => pt + .cursor() + .unmap_region(start, size) + .map_err(|_| MappingError::BadState)?, } Ok(()) } @@ -173,8 +152,8 @@ impl NestedPageTable { pub fn remap(&mut self, start: GuestPhysAddr, paddr: PhysAddr, flags: MappingFlags) -> bool { match self { #[cfg(not(target_arch = "x86_64"))] - NestedPageTable::L3(pt) => pt.remap(start, paddr, flags).is_ok(), - NestedPageTable::L4(pt) => pt.remap(start, paddr, flags).is_ok(), + NestedPageTable::L3(pt) => pt.cursor().remap(start, paddr, flags).is_ok(), + NestedPageTable::L4(pt) => pt.cursor().remap(start, paddr, flags).is_ok(), } } @@ -184,19 +163,16 @@ impl NestedPageTable { start: GuestPhysAddr, size: usize, new_flags: page_table_entry::MappingFlags, - flush: bool, ) -> bool { match self { #[cfg(not(target_arch = "x86_64"))] NestedPageTable::L3(pt) => pt - .protect_region(start, size, new_flags, flush) // If the TLB is refreshed immediately every time, there might be performance issues. - // The TLB refresh is managed uniformly at a higher level. - .map(|tlb| tlb.ignore()) + .cursor() + .protect_region(start, size, new_flags) // If the TLB is refreshed immediately every time, there might be performance issues. .is_ok(), NestedPageTable::L4(pt) => pt - .protect_region(start, size, new_flags, flush) // If the TLB is refreshed immediately every time, there might be performance issues. - // The TLB refresh is managed uniformly at a higher level. - .map(|tlb| tlb.ignore()) + .cursor() + .protect_region(start, size, new_flags) // If the TLB is refreshed immediately every time, there might be performance issues. .is_ok(), } } @@ -205,11 +181,8 @@ impl NestedPageTable { pub fn query( &self, vaddr: crate::GuestPhysAddr, - ) -> page_table_multiarch::PagingResult<( - memory_addr::PhysAddr, - page_table_entry::MappingFlags, - page_table_multiarch::PageSize, - )> { + ) -> page_table_multiarch::PagingResult<(PhysAddr, page_table_entry::MappingFlags, PageSize)> + { match self { #[cfg(not(target_arch = "x86_64"))] NestedPageTable::L3(pt) => pt.query(vaddr), diff --git a/src/test_utils/mod.rs b/src/test_utils/mod.rs index 7dc543b..e2d6a47 100644 --- a/src/test_utils/mod.rs +++ b/src/test_utils/mod.rs @@ -90,10 +90,31 @@ impl PagingHandler for MockHal { Self::mock_alloc_frame() } + fn alloc_frames(count: usize, _align: usize) -> Option { + if count == 0 { + return Some(PhysAddr::from(0)); + } + // For simplicity, just allocate frames sequentially + let first = Self::mock_alloc_frame()?; + for _ in 1..count { + if Self::mock_alloc_frame().is_none() { + return None; + } + } + Some(first) + } + fn dealloc_frame(_paddr: PhysAddr) { Self::mock_dealloc_frame(_paddr) } + fn dealloc_frames(paddr: PhysAddr, count: usize) { + for i in 0..count { + let offset = i * PAGE_SIZE; + Self::mock_dealloc_frame(PhysAddr::from(paddr.as_usize() + offset)); + } + } + fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { Self::mock_phys_to_virt(paddr) }