Skip to main content

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

1// SPDX-License-Identifier: GPL-3.0-only
2//! VMM Paging (x86_64): `map_range`
3//!
4//! Authors: MarioS271
5
6use crate::arch::x86_64::mm::vmm::page_type::{PageType, HUGE_PAGE_SIZE_1GIB, HUGE_PAGE_SIZE_2MIB};
7use crate::lib::addr::{PhysAddr, VirtAddr};
8use crate::mm::pmm::Pmm;
9use crate::mm::vmm::VmmResult;
10use x86_64::structures::paging::PageTableFlags;
11
12pub unsafe fn map_range(
13    pmm: &mut Pmm,
14    page_ptr: VirtAddr,
15    virt: VirtAddr,
16    phys: PhysAddr,
17    size: u64,
18    flags: PageTableFlags,
19    can_overmap: bool
20) -> VmmResult {
21    #[cfg(feature = "debug-checks")]
22    {
23        use super::helpers::misaligned_address_panic;
24        use crate::mm::pmm::FRAME_SIZE;
25        if !virt.is_aligned(FRAME_SIZE) || !phys.is_aligned(FRAME_SIZE) || size % FRAME_SIZE != 0 {
26            misaligned_address_panic(PageType::Normal);
27        }
28    }
29
30    let mut offset = 0u64;
31
32    while offset < size {
33        let virt = virt + offset;
34        let phys = phys + offset;
35        let remaining = size - offset;
36
37        let fits = |page_size: u64| {
38            virt.is_aligned(page_size)
39                && phys.is_aligned(page_size)
40                && (can_overmap || remaining >= page_size)
41        };
42
43        let page_type = if fits(HUGE_PAGE_SIZE_1GIB) {
44            PageType::HugePage1GiB
45        }
46        else if fits(HUGE_PAGE_SIZE_2MIB) {
47            PageType::HugePage2MiB
48        }
49        else {
50            PageType::Normal
51        };
52
53        unsafe {
54            super::map_page::map_page(pmm, page_ptr, virt, phys, page_type, flags)?;
55        }
56
57        offset += page_type as u64;
58    }
59
60    Ok(())
61}