Skip to main content

kernel/arch/x86_64/mm/vmm/paging/
mod.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! VMM Paging (x86_64): mapping, unmapping, remapping pages and more
3//!
4//! Authors: MarioS271
5
6mod helpers;
7mod setup_kernel_paging;
8mod map_page;
9mod unmap;
10mod remap;
11mod translate;
12mod map_range;
13
14use super::page_type::PageType;
15use crate::lib::addr::{PhysAddr, VirtAddr};
16use crate::lib::types::boot_info::KernelSectionInfo;
17use crate::mm::pmm::Pmm;
18use crate::mm::vmm::boot_mapping::BootMappings;
19use crate::mm::vmm::traits::VmmPaging;
20use crate::mm::vmm::vma::VmaFlags;
21use crate::mm::vmm::{Vmm, VmmResult};
22use crate::state::kstate::KSTATE;
23use x86_64::structures::paging::page_table::PageTableEntry;
24use x86_64::structures::paging::PageTableFlags;
25
26impl VmmPaging for Vmm {
27    type PageType = PageType;
28    type PageTableFlags = PageTableFlags;
29
30    #[inline(always)]
31    fn setup_kernel_paging(sections: &KernelSectionInfo) -> (VirtAddr, BootMappings) {
32        setup_kernel_paging::setup_kernel_paging(sections)
33    }
34
35    #[inline(always)]
36    unsafe fn map_page(
37        pmm: &mut Pmm,
38        page_ptr: VirtAddr,
39        virt: VirtAddr,
40        phys: PhysAddr,
41        page_type: Self::PageType,
42        flags: Self::PageTableFlags
43    ) -> VmmResult {
44        unsafe { map_page::map_page(pmm, page_ptr, virt, phys, page_type, flags) }
45    }
46
47    #[inline(always)]
48    unsafe fn map_range(
49        pmm: &mut Pmm,
50        page_ptr: VirtAddr,
51        virt: VirtAddr,
52        phys: PhysAddr,
53        size: u64,
54        flags: Self::PageTableFlags,
55        can_overmap: bool
56    ) -> VmmResult {
57        unsafe { map_range::map_range(pmm, page_ptr, virt, phys, size, flags, can_overmap) }
58    }
59
60    #[inline(always)]
61    unsafe fn unmap_page(
62        page_ptr: VirtAddr,
63        virt: VirtAddr
64    ) -> VmmResult {
65        unsafe { unmap::unmap_page(page_ptr, virt) }
66    }
67
68    #[inline(always)]
69    unsafe fn remap_page(
70        page_ptr: VirtAddr,
71        virt: VirtAddr,
72        new_flags: Self::PageTableFlags
73    ) -> VmmResult {
74        unsafe { remap::remap_page(page_ptr, virt, new_flags) }
75    }
76
77    #[inline(always)]
78    fn translate(
79        page_ptr: VirtAddr,
80        virt: VirtAddr
81    ) -> Option<PhysAddr> {
82        unsafe { translate::translate(page_ptr, virt) }
83    }
84
85    #[inline(always)]
86    fn translate_with_size(
87        page_ptr: VirtAddr,
88        virt: VirtAddr
89    ) -> Option<(PhysAddr, u64)> {
90        unsafe { translate::translate_with_size(page_ptr, virt) }
91    }
92
93    fn vma_flags_to_page_flags(vma_flags: VmaFlags) -> Self::PageTableFlags {
94        let mut flags = PageTableFlags::PRESENT;
95
96        if vma_flags.contains(VmaFlags::WRITE) {
97            flags |= PageTableFlags::WRITABLE;
98        }
99        if !vma_flags.contains(VmaFlags::EXEC) {
100            flags |= PageTableFlags::NO_EXECUTE;
101        }
102        if vma_flags.contains(VmaFlags::USER) {
103            flags |= PageTableFlags::USER_ACCESSIBLE;
104        } else {
105            flags |= PageTableFlags::GLOBAL;
106        }
107
108        flags
109    }
110
111    unsafe fn clone_kernel_mappings(dst: VirtAddr) {
112        unsafe {
113            core::ptr::copy_nonoverlapping(
114                KSTATE.mm.kernel_addr_space().lock().page_ptr().as_ptr::<PageTableEntry>().add(256),
115                dst.as_mut_ptr::<PageTableEntry>().add(256),
116                256
117            );
118        }
119    }
120}