From 64977f2efca58cfdccd8b6e6e7fa03a0459d8682 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Thu, 15 Jan 2026 23:27:59 +0800 Subject: [PATCH 1/7] update axerrno to 0.2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4d124fe..7a9610c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ 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" From 16163ef4a4516fa2d5b51c8b08f5940d1ff31f04 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Thu, 15 Jan 2026 23:29:38 +0800 Subject: [PATCH 2/7] some small format fixes --- src/address_space/mod.rs | 3 +-- src/lib.rs | 1 + src/npt/mod.rs | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/address_space/mod.rs b/src/address_space/mod.rs index 9144996..eb07615 100644 --- a/src/address_space/mod.rs +++ b/src/address_space/mod.rs @@ -1,7 +1,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; @@ -11,7 +11,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 a1a4daf..11ed0f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,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/mod.rs b/src/npt/mod.rs index 967785e..f8151bd 100644 --- a/src/npt/mod.rs +++ b/src/npt/mod.rs @@ -9,13 +9,14 @@ 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. @@ -55,7 +56,7 @@ impl NestedPageTable { } } - pub fn root_paddr(&self) -> memory_addr::PhysAddr { + pub const fn root_paddr(&self) -> memory_addr::PhysAddr { match self { #[cfg(not(target_arch = "x86_64"))] NestedPageTable::L3(pt) => pt.root_paddr(), From 40c5b2e750d182ef91153887c71d35cba802a3bb Mon Sep 17 00:00:00 2001 From: aarkegz Date: Thu, 5 Mar 2026 19:20:46 +0800 Subject: [PATCH 3/7] update page_table_entry and page_table_multiarch dependencies to version 0.6 in Cargo.toml --- Cargo.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7a9610c..e78572f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,8 +29,8 @@ numeric-enum-macro = "0.2" 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" - From 4e96af2f761e39361b6e49dc15263c7452bd6cd8 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Thu, 5 Mar 2026 19:33:39 +0800 Subject: [PATCH 4/7] chore: bump version to 0.3.0 in Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b30743a..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"] From 8afea5ac6a407a1b29e262d81b4684f847c67771 Mon Sep 17 00:00:00 2001 From: YanLien Date: Tue, 24 Feb 2026 11:10:28 +0800 Subject: [PATCH 5/7] test: add multi-frame allocation support and fix warning --- src/npt/arch/x86_64.rs | 1 + src/test_utils/mod.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) 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/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) } From 4b6c1f7aa078a98a4c2c5e672ed0f8997d47a44c Mon Sep 17 00:00:00 2001 From: YanLien Date: Tue, 24 Feb 2026 11:06:31 +0800 Subject: [PATCH 6/7] feat: update page_table_multiarch to 0.6 --- src/address_space/backend/alloc.rs | 24 ++++++++++++------------ src/address_space/backend/linear.rs | 20 ++++++++++---------- src/address_space/backend/mod.rs | 5 ++++- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/address_space/backend/alloc.rs b/src/address_space/backend/alloc.rs index 65aa0f8..f63a0c2 100644 --- a/src/address_space/backend/alloc.rs +++ b/src/address_space/backend/alloc.rs @@ -46,7 +46,7 @@ impl Backend { // allocate all possible physical frames for populated mapping. for addr in PageIter4K::new(start, start + size).unwrap() { if H::alloc_frame() - .and_then(|frame| pt.map(addr, frame, PageSize::Size4K, flags).ok()) + .and_then(|frame| pt.cursor().map(addr, frame, PageSize::Size4K, flags).ok()) .is_none() { return false; @@ -55,15 +55,15 @@ impl Backend { true } else { // Map to a empty entry for on-demand mapping. - pt.map_region( - start, - |_va| PhysAddr::from(0), - size, - MappingFlags::empty(), - false, - false, - ) - .is_ok() + pt.cursor() + .map_region( + start, + |_va| PhysAddr::from(0), + size, + MappingFlags::empty(), + false, + ) + .is_ok() } } @@ -76,7 +76,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.cursor().unmap(addr) { // Deallocate the physical frame if there is a mapping in the // page table. if page_size.is_huge() { @@ -106,7 +106,7 @@ impl Backend { let Some(frame) = H::alloc_frame() else { return false; }; - pt.remap(vaddr, frame, orig_flags) + pt.cursor().remap(vaddr, frame, orig_flags).ok() } } } diff --git a/src/address_space/backend/linear.rs b/src/address_space/backend/linear.rs index 0ef10e6..0aa0740 100644 --- a/src/address_space/backend/linear.rs +++ b/src/address_space/backend/linear.rs @@ -41,15 +41,15 @@ impl Backend { pa_start + size, flags ); - pt.map_region( - start, - |va| PhysAddr::from(va.as_usize() - pa_va_offset), - size, - flags, - true, - true, - ) - .is_ok() + pt.cursor() + .map_region( + start, + |va| PhysAddr::from(va.as_usize() - pa_va_offset), + size, + flags, + true, + ) + .is_ok() } pub(crate) fn unmap_linear( @@ -60,6 +60,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.cursor().unmap_region(start, size).is_ok() } } diff --git a/src/address_space/backend/mod.rs b/src/address_space/backend/mod.rs index 44b6c85..8a05c98 100644 --- a/src/address_space/backend/mod.rs +++ b/src/address_space/backend/mod.rs @@ -98,7 +98,10 @@ impl MappingBackend for Backend { new_flags: MappingFlags, page_table: &mut PageTable, ) -> bool { - page_table.protect_region(start, size, new_flags, true) + page_table + .cursor() + .protect_region(start, size, new_flags) + .is_ok() } } From 745cace2727684840a78d6a8ccd7b181808cdb68 Mon Sep 17 00:00:00 2001 From: aarkegz Date: Thu, 5 Mar 2026 19:52:16 +0800 Subject: [PATCH 7/7] fix: page table operations, to adapt `page_table*` 0.6 --- src/address_space/backend/alloc.rs | 23 +++--- src/address_space/backend/linear.rs | 19 +++-- src/address_space/backend/mod.rs | 5 +- src/npt/mod.rs | 108 +++++++++++----------------- 4 files changed, 61 insertions(+), 94 deletions(-) diff --git a/src/address_space/backend/alloc.rs b/src/address_space/backend/alloc.rs index f63a0c2..9f493d9 100644 --- a/src/address_space/backend/alloc.rs +++ b/src/address_space/backend/alloc.rs @@ -46,7 +46,7 @@ impl Backend { // allocate all possible physical frames for populated mapping. for addr in PageIter4K::new(start, start + size).unwrap() { if H::alloc_frame() - .and_then(|frame| pt.cursor().map(addr, frame, PageSize::Size4K, flags).ok()) + .and_then(|frame| pt.map(addr, frame, PageSize::Size4K, flags).ok()) .is_none() { return false; @@ -55,15 +55,14 @@ impl Backend { true } else { // Map to a empty entry for on-demand mapping. - pt.cursor() - .map_region( - start, - |_va| PhysAddr::from(0), - size, - MappingFlags::empty(), - false, - ) - .is_ok() + pt.map_region( + start, + |_va| PhysAddr::from(0), + size, + MappingFlags::empty(), + 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.cursor().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() { @@ -106,7 +105,7 @@ impl Backend { let Some(frame) = H::alloc_frame() else { return false; }; - pt.cursor().remap(vaddr, frame, orig_flags).ok() + pt.remap(vaddr, frame, orig_flags) } } } diff --git a/src/address_space/backend/linear.rs b/src/address_space/backend/linear.rs index 0aa0740..baf44fe 100644 --- a/src/address_space/backend/linear.rs +++ b/src/address_space/backend/linear.rs @@ -41,15 +41,14 @@ impl Backend { pa_start + size, flags ); - pt.cursor() - .map_region( - start, - |va| PhysAddr::from(va.as_usize() - pa_va_offset), - size, - flags, - true, - ) - .is_ok() + pt.map_region( + start, + |va| PhysAddr::from(va.as_usize() - pa_va_offset), + size, + flags, + true, + ) + .is_ok() } pub(crate) fn unmap_linear( @@ -60,6 +59,6 @@ impl Backend { _pa_va_offset: usize, ) -> bool { debug!("unmap_linear: [{:#x}, {:#x})", start, start + size); - pt.cursor().unmap_region(start, size).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 8a05c98..8a7916b 100644 --- a/src/address_space/backend/mod.rs +++ b/src/address_space/backend/mod.rs @@ -98,10 +98,7 @@ impl MappingBackend for Backend { new_flags: MappingFlags, page_table: &mut PageTable, ) -> bool { - page_table - .cursor() - .protect_region(start, size, new_flags) - .is_ok() + page_table.protect_region(start, size, new_flags) } } diff --git a/src/npt/mod.rs b/src/npt/mod.rs index 05b22b0..5346be0 100644 --- a/src/npt/mod.rs +++ b/src/npt/mod.rs @@ -16,7 +16,7 @@ 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; @@ -52,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)) } @@ -70,7 +68,7 @@ impl NestedPageTable { } } - pub const 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(), @@ -82,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(()) } @@ -106,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), } } @@ -130,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(()) } @@ -174,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(), } } @@ -185,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(), } } @@ -206,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),