axmm/backend/
mod.rs

1//! Memory mapping backends.
2
3use axhal::paging::{MappingFlags, PageTable};
4use memory_addr::VirtAddr;
5use memory_set::MappingBackend;
6
7mod alloc;
8mod linear;
9
10/// A unified enum type for different memory mapping backends.
11///
12/// Currently, two backends are implemented:
13///
14/// - **Linear**: used for linear mappings. The target physical frames are
15///   contiguous and their addresses should be known when creating the mapping.
16/// - **Allocation**: used in general, or for lazy mappings. The target physical
17///   frames are obtained from the global allocator.
18#[derive(Clone)]
19pub enum Backend {
20    /// Linear mapping backend.
21    ///
22    /// The offset between the virtual address and the physical address is
23    /// constant, which is specified by `pa_va_offset`. For example, the virtual
24    /// address `vaddr` is mapped to the physical address `vaddr - pa_va_offset`.
25    Linear {
26        /// `vaddr - paddr`.
27        pa_va_offset: usize,
28    },
29    /// Allocation mapping backend.
30    ///
31    /// If `populate` is `true`, all physical frames are allocated when the
32    /// mapping is created, and no page faults are triggered during the memory
33    /// access. Otherwise, the physical frames are allocated on demand (by
34    /// handling page faults).
35    Alloc {
36        /// Whether to populate the physical frames when creating the mapping.
37        populate: bool,
38    },
39}
40
41impl MappingBackend for Backend {
42    type Addr = VirtAddr;
43    type Flags = MappingFlags;
44    type PageTable = PageTable;
45    fn map(&self, start: VirtAddr, size: usize, flags: MappingFlags, pt: &mut PageTable) -> bool {
46        match *self {
47            Self::Linear { pa_va_offset } => self.map_linear(start, size, flags, pt, pa_va_offset),
48            Self::Alloc { populate } => self.map_alloc(start, size, flags, pt, populate),
49        }
50    }
51
52    fn unmap(&self, start: VirtAddr, size: usize, pt: &mut PageTable) -> bool {
53        match *self {
54            Self::Linear { pa_va_offset } => self.unmap_linear(start, size, pt, pa_va_offset),
55            Self::Alloc { populate } => self.unmap_alloc(start, size, pt, populate),
56        }
57    }
58
59    fn protect(
60        &self,
61        start: Self::Addr,
62        size: usize,
63        new_flags: Self::Flags,
64        page_table: &mut Self::PageTable,
65    ) -> bool {
66        page_table
67            .protect_region(start, size, new_flags, true)
68            .map(|tlb| tlb.ignore())
69            .is_ok()
70    }
71}
72
73impl Backend {
74    pub(crate) fn handle_page_fault(
75        &self,
76        vaddr: VirtAddr,
77        orig_flags: MappingFlags,
78        page_table: &mut PageTable,
79    ) -> bool {
80        match *self {
81            Self::Linear { .. } => false, // Linear mappings should not trigger page faults.
82            Self::Alloc { populate } => {
83                self.handle_page_fault_alloc(vaddr, orig_flags, page_table, populate)
84            }
85        }
86    }
87}