axmm/
lib.rs

1//! [ArceOS](https://github.com/arceos-org/arceos) memory management module.
2
3#![no_std]
4
5#[macro_use]
6extern crate log;
7extern crate alloc;
8
9mod aspace;
10mod backend;
11#[cfg(feature = "cow")]
12mod frameinfo;
13
14pub mod page_iter_wrapper;
15pub use self::aspace::AddrSpace;
16pub use self::backend::Backend;
17
18use axerrno::{AxError, AxResult};
19use axhal::mem::phys_to_virt;
20use axhal::paging::PageSize;
21use kspin::SpinNoIrq;
22use lazyinit::LazyInit;
23use memory_addr::{PhysAddr, va};
24use memory_set::MappingError;
25
26static KERNEL_ASPACE: LazyInit<SpinNoIrq<AddrSpace>> = LazyInit::new();
27
28fn mapping_err_to_ax_err(err: MappingError) -> AxError {
29    warn!("Mapping error: {:?}", err);
30    match err {
31        MappingError::InvalidParam => AxError::InvalidInput,
32        MappingError::AlreadyExists => AxError::AlreadyExists,
33        MappingError::BadState => AxError::BadState,
34    }
35}
36
37/// Creates a new address space for kernel itself.
38pub fn new_kernel_aspace() -> AxResult<AddrSpace> {
39    let mut aspace = AddrSpace::new_empty(
40        va!(axconfig::plat::KERNEL_ASPACE_BASE),
41        axconfig::plat::KERNEL_ASPACE_SIZE,
42    )?;
43    for r in axhal::mem::memory_regions() {
44        aspace.map_linear(
45            phys_to_virt(r.paddr),
46            r.paddr,
47            r.size,
48            r.flags.into(),
49            PageSize::Size4K,
50        )?;
51    }
52    Ok(aspace)
53}
54
55/// Returns the globally unique kernel address space.
56pub fn kernel_aspace() -> &'static SpinNoIrq<AddrSpace> {
57    &KERNEL_ASPACE
58}
59
60/// Returns the root physical address of the kernel page table.
61pub fn kernel_page_table_root() -> PhysAddr {
62    KERNEL_ASPACE.lock().page_table_root()
63}
64
65/// Initializes virtual memory management.
66///
67/// It mainly sets up the kernel virtual memory address space and recreate a
68/// fine-grained kernel page table.
69pub fn init_memory_management() {
70    info!("Initialize virtual memory management...");
71
72    let kernel_aspace = new_kernel_aspace().expect("failed to initialize kernel address space");
73    debug!("kernel address space init OK: {:#x?}", kernel_aspace);
74    KERNEL_ASPACE.init_once(SpinNoIrq::new(kernel_aspace));
75    axhal::paging::set_kernel_page_table_root(kernel_page_table_root());
76}
77
78/// Initializes kernel paging for secondary CPUs.
79pub fn init_memory_management_secondary() {
80    axhal::paging::set_kernel_page_table_root(kernel_page_table_root());
81}