kernel_alloc/phys_mapper.rs
1//! # HHDM-based [`PhysMapper`] for Kernel Virtual Memory
2//!
3//! This module provides a [`PhysMapper`] implementation for kernels that use a
4//! higher-half direct map (HHDM). It allows safe and portable access to physical
5//! memory by converting a physical address to a usable pointer in the current
6//! virtual address space.
7//!
8//! ## Why is this needed?
9//! - Rust and C code can only dereference virtual addresses, not physical ones.
10//! - When manipulating page tables or other physical memory, you need a way to
11//!   "see" or "touch" a physical address from your code.
12//! - The mapping strategy (HHDM, identity, temporary) may differ between bootloader,
13//!   kernel, and tests, so this trait abstracts over those details.
14//!
15//! ## How does it work?
16//! - With HHDM, every physical address is mapped at `HHDM_BASE + pa`.
17//! - This implementation simply adds the HHDM base to the physical address and
18//!   returns a pointer.
19//!
20//! ## Example
21//! ```rust,no_run
22//! use kernel_vmem::{addresses::PhysicalAddress, page_table::pt::PageTable, PhysMapper};
23//! use kernel_alloc::phys_mapper::HhdmPhysMapper;
24//! let phys = PhysicalAddress::new(0x1234_0000);
25//! let mapper = HhdmPhysMapper;
26//! unsafe {
27//!     let table: &mut PageTable = mapper.phys_to_mut(phys);
28//! }
29//! ```
30//!
31//! ## See also
32//! - [`PhysMapper`] trait in `kernel-vmem`
33//! - Your kernel's memory layout and HHDM configuration
34
35use kernel_info::memory::HHDM_BASE;
36use kernel_vmem::PhysMapper;
37use kernel_vmem::addresses::PhysicalAddress;
38
39/// [`PhysMapper`] implementation for kernels with a higher-half direct map (HHDM).
40///
41/// This type allows you to convert a physical address to a usable pointer in the
42/// kernel's virtual address space by adding `HHDM_BASE` to the physical address.
43///
44/// # Safety
45/// - The HHDM mapping must be present and cover the referenced physical range.
46/// - The returned pointer must only be used for valid, mapped, and writable memory.
47///
48/// # Example
49/// ```rust,no_run
50/// use kernel_vmem::{addresses::PhysicalAddress, page_table::pt::PageTable, PhysMapper};
51/// use kernel_alloc::phys_mapper::HhdmPhysMapper;
52/// let phys = PhysicalAddress::new(0x1234_0000);
53/// let mapper = HhdmPhysMapper;
54/// unsafe {
55///     let table: &mut PageTable = mapper.phys_to_mut(phys);
56/// }
57/// ```
58pub struct HhdmPhysMapper;
59
60impl PhysMapper for HhdmPhysMapper {
61    unsafe fn phys_to_mut<T>(&self, pa: PhysicalAddress) -> &mut T {
62        let va = (HHDM_BASE + pa.as_u64()) as *mut T;
63        // SAFETY: Caller must ensure the physical address is valid and mapped via HHDM.
64        unsafe { &mut *va }
65    }
66}