Skip to main content

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

1// SPDX-License-Identifier: GPL-3.0-only
2//! VMM Paging (x86_64): `translate` and `translate_with_size`
3//!
4//! Authors: MarioS271
5
6use super::super::page_type::{HUGE_PAGE_SIZE_1GIB, HUGE_PAGE_SIZE_2MIB};
7use super::helpers::{advance_current_pagetable, is_huge_page, is_present};
8use crate::lib::addr::{PhysAddr, VirtAddr};
9use crate::mm::pmm::FRAME_SIZE;
10use x86_64::structures::paging::PageTable;
11
12pub unsafe fn translate(
13    page_ptr: VirtAddr,
14    virt: VirtAddr
15) -> Option<PhysAddr> {
16    let res = unsafe { translate_with_size(page_ptr, virt)? };
17    Some(res.0)
18}
19
20pub unsafe fn translate_with_size(
21    page_ptr: VirtAddr,
22    virt: VirtAddr
23) -> Option<(PhysAddr, u64)> {
24    let mut current = page_ptr.as_mut_ptr::<PageTable>();
25
26    // PML4
27    // Safety:
28    // - current_pagetable is a valid, non-zero, page-aligned pointer allocated by the PMM and
29    //   initialized by setup_kernel_paging
30    // - the VMM is wrapped in an IrqMutex which guarantees serialized VMM method execution
31    let entry = unsafe { &(&*current)[virt.p4_index()] };
32    if !is_present(entry) { return None; }
33    current = advance_current_pagetable(entry);
34
35    // PDPT
36    // Safety:
37    // - current_pagetable is a valid, non-zero, page-aligned pointer computed from the previous
38    //   current_pagetable which was also valid
39    // - the VMM is wrapped in an IrqMutex which guarantees serialized VMM method execution
40    let entry = unsafe { &(&*current)[virt.p3_index()] };
41    if !is_present(entry) { return None; }
42    if is_huge_page(entry) {
43        return Some((
44            PhysAddr::new(entry.addr().as_u64() + (virt.as_u64() & (HUGE_PAGE_SIZE_1GIB - 1))),
45            HUGE_PAGE_SIZE_1GIB
46        ));
47    }
48    current = advance_current_pagetable(entry);
49
50    // PD
51    // Safety:
52    // - current_pagetable is a valid, non-zero, page-aligned pointer computed from the previous
53    //   current_pagetable which was also valid
54    // - the VMM is wrapped in an IrqMutex which guarantees serialized VMM method execution
55    let entry = unsafe { &(&*current)[virt.p2_index()] };
56    if !is_present(entry) { return None; }
57    if is_huge_page(entry) {
58        return Some((
59            PhysAddr::new(entry.addr().as_u64() + (virt.as_u64() & (HUGE_PAGE_SIZE_2MIB - 1))),
60            HUGE_PAGE_SIZE_2MIB
61        ));
62    }
63    current = advance_current_pagetable(entry);
64
65    // PT
66    // Safety:
67    // - current_pagetable is a valid, non-zero, page-aligned pointer computed from the previous
68    //   current_pagetable which was also valid
69    // - the VMM is wrapped in an IrqMutex which guarantees serialized VMM method execution
70    let entry = unsafe { &(&*current)[virt.p1_index()] };
71    if !is_present(entry) { return None; }
72    Some((
73        PhysAddr::new(entry.addr().as_u64() + (virt.as_u64() & (FRAME_SIZE - 1))),
74        FRAME_SIZE
75    ))
76}