Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand All @@ -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"
Expand All @@ -40,4 +40,3 @@ lazy_static = "1.5"
spin = "0.10"
assert_matches = "1.5.0"
axin = "0.1.0"

3 changes: 1 addition & 2 deletions src/address_space/backend/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ impl<H: PagingHandler> Backend<H> {
size,
MappingFlags::empty(),
false,
false,
)
.is_ok()
}
Expand All @@ -76,7 +75,7 @@ impl<H: PagingHandler> Backend<H> {
) -> 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() {
Expand Down
3 changes: 1 addition & 2 deletions src/address_space/backend/linear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ impl<H: PagingHandler> Backend<H> {
size,
flags,
true,
true,
)
.is_ok()
}
Expand All @@ -60,6 +59,6 @@ impl<H: PagingHandler> Backend<H> {
_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()
}
}
2 changes: 1 addition & 1 deletion src/address_space/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl<H: PagingHandler> MappingBackend for Backend<H> {
new_flags: MappingFlags,
page_table: &mut PageTable<H>,
) -> bool {
page_table.protect_region(start, size, new_flags, true)
page_table.protect_region(start, size, new_flags)
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/address_space/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/npt/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<GuestPhysAddr>) {
#[cfg(not(test))]
if let Some(vaddr) = vaddr {
Expand Down
115 changes: 44 additions & 71 deletions src/npt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<H> = arch::ExtendedPageTable<H>;

} else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
/// RISC-V Level 3 nested page table (Sv39, x4 not supported)
pub type NestedPageTableL3<H> = page_table_multiarch::PageTable64<arch::Sv39MetaData<GuestPhysAddr>, arch::Rv64PTE, H>;
pub type NestedPageTableL4<H> = page_table_multiarch::PageTable64<arch::Sv48MetaData<GuestPhysAddr>, arch::Rv64PTE, H>;

/// RISC-V Level 4 nested page table (Sv48, x4 not supported)
pub type NestedPageTableL4<H> = page_table_multiarch::PageTable64<arch::Sv48MetaData<GuestPhysAddr>, 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<H> = page_table_multiarch::PageTable64<arch::A64HVPagingMetaDataL3, arch::A64PTEHV, H>;

/// AArch64 Level 4 nested page table type alias.
Expand All @@ -51,8 +52,6 @@ impl<H: PagingHandler> NestedPageTable<H> {
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))
}
Expand All @@ -69,7 +68,7 @@ impl<H: PagingHandler> NestedPageTable<H> {
}
}

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(),
Expand All @@ -81,22 +80,20 @@ impl<H: PagingHandler> NestedPageTable<H> {
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(())
}
Expand All @@ -105,19 +102,11 @@ impl<H: PagingHandler> NestedPageTable<H> {
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),
}
}

Expand All @@ -129,52 +118,42 @@ impl<H: PagingHandler> NestedPageTable<H> {
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(())
}

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(),
}
}

Expand All @@ -184,19 +163,16 @@ impl<H: PagingHandler> NestedPageTable<H> {
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(),
}
}
Expand All @@ -205,11 +181,8 @@ impl<H: PagingHandler> NestedPageTable<H> {
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),
Expand Down
21 changes: 21 additions & 0 deletions src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,31 @@ impl PagingHandler for MockHal {
Self::mock_alloc_frame()
}

fn alloc_frames(count: usize, _align: usize) -> Option<PhysAddr> {
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)
}
Expand Down