diff --git a/framework/aster-frame/src/vm/mod.rs b/framework/aster-frame/src/vm/mod.rs index 9066adf4d..2c14639cc 100644 --- a/framework/aster-frame/src/vm/mod.rs +++ b/framework/aster-frame/src/vm/mod.rs @@ -20,6 +20,7 @@ pub(crate) mod page_table; mod space; use alloc::{borrow::ToOwned, vec::Vec}; +use core::ops::Range; use spin::Once; @@ -48,22 +49,41 @@ pub const PAGE_SIZE: usize = 0x1000; /// for the rationale. pub const MAX_USERSPACE_VADDR: Vaddr = 0x0000_8000_0000_0000 - PAGE_SIZE; -/// Start of the kernel address space. -/// -/// This is the _lowest_ address of the x86-64's _high_ canonical addresses. -/// -/// This is also the base address of the direct mapping of all physical -/// memory in the kernel address space. +/// The base address of the direct mapping of physical memory. pub(crate) const PHYS_MEM_BASE_VADDR: Vaddr = 0xffff_8000_0000_0000; +/// The maximum size of the direct mapping of physical memory. +/// +/// This size acts as a cap. If the actual memory size exceeds this value, +/// the remaining memory cannot be included in the direct mapping because +/// the maximum size of the direct mapping is limited by this value. On +/// the other hand, if the actual memory size is smaller, the direct +/// mapping can shrink to save memory consumption due to the page table. +/// +/// We do not currently have APIs to manually map MMIO pages, so we have +/// to rely on the direct mapping to perform MMIO operations. Therefore, +/// we set the maximum size to 127 TiB, which makes some surprisingly +/// high MMIO addresses usable (e.g., `0x7000_0000_7004` for VirtIO +/// devices in the TDX environment) and leaves the last 1 TiB for other +/// uses (e.g., the kernel code starting at [`kernel_loaded_offset()`]). +pub(crate) const PHYS_MEM_MAPPING_MAX_SIZE: usize = 127 << 40; + +/// The address range of the direct mapping of physical memory. +/// +/// This range is constructed based on [`PHYS_MEM_BASE_VADDR`] and +/// [`PHYS_MEM_MAPPING_MAX_SIZE`]. +pub(crate) const PHYS_MEM_VADDR_RANGE: Range = + PHYS_MEM_BASE_VADDR..(PHYS_MEM_BASE_VADDR + PHYS_MEM_MAPPING_MAX_SIZE); + /// The kernel code is linear mapped to this address. /// /// FIXME: This offset should be randomly chosen by the loader or the /// boot compatibility layer. But we disabled it because the framework /// doesn't support relocatable kernel yet. -pub fn kernel_loaded_offset() -> usize { +pub const fn kernel_loaded_offset() -> usize { 0xffff_ffff_8000_0000 } +const_assert!(PHYS_MEM_VADDR_RANGE.end < kernel_loaded_offset()); /// Get physical address trait pub trait HasPaddr { @@ -71,7 +91,7 @@ pub trait HasPaddr { } pub fn vaddr_to_paddr(va: Vaddr) -> Option { - if (PHYS_MEM_BASE_VADDR..=kernel_loaded_offset()).contains(&va) { + if PHYS_MEM_VADDR_RANGE.contains(&va) { // can use offset to get the physical address Some(va - PHYS_MEM_BASE_VADDR) } else {