Skip to main content

strat9_kernel/arch/
xshim.rs

1//! Architecture-neutral shim mirroring the subset of the `x86_64` crate API
2//! used by shared kernel code (address types, page sizes, paging flags).
3//!
4//! Purpose: the ~42 `use x86_64::...` call-sites outside `arch/` are being
5//! rewritten to `use crate::arch::xshim::...` so the riscv64 backend can
6//! provide its own implementations. On x86_64 the shim re-exports the real
7//! crate types so behaviour is bit-identical.
8
9#[cfg(target_arch = "x86_64")]
10pub use x86_64::{
11    structures::paging::{
12        mapper::TranslateResult, PageTableFlags, PhysFrame, Size2MiB, Size4KiB, Translate,
13    },
14    PhysAddr, VirtAddr,
15};
16
17// riscv64 uses the neutral types defined below.
18
19#[cfg(not(target_arch = "x86_64"))]
20mod neutral {
21    pub use crate::ostd::mm::{PhysAddr, VirtAddr};
22
23    /// Page granularity markers (4 KiB / 2 MiB).
24    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
25    pub struct Size4KiB;
26
27    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
28    pub struct Size2MiB;
29
30    pub const SIZE_4KIB: u64 = 4096;
31    pub const SIZE_2MIB: u64 = 2 * 1024 * 1024;
32
33    bitflags::bitflags! {
34        /// Page-table flags, arch-neutral encoding (subset of both ISAs).
35        #[derive(Clone, Copy, PartialEq, Eq, Debug)]
36        pub struct PageTableFlags: u64 {
37            const PRESENT = 1 << 0;
38            const WRITABLE = 1 << 1;
39            const USER_ACCESSIBLE = 1 << 2;
40            const NO_EXECUTE = 1 << 3;
41            const NO_CACHE = 1 << 4;
42            const HUGE_PAGE = 1 << 5;
43            const BIT_9 = 1 << 9; // used as COW marker on x86_64
44        }
45    }
46
47    /// Result of a translation walk.
48    #[derive(Clone, Copy, Debug)]
49    pub enum TranslateResult {
50        Mapped {
51            frame: PhysFrame<Size4KiB>,
52            offset: u64,
53            flags: PageTableFlags,
54        },
55        NotMapped,
56        InvalidFrameAddress(PhysAddr),
57    }
58
59    /// A physical memory frame of a given size.
60    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
61    pub struct PhysFrame<S> {
62        start: PhysAddr,
63        _size: core::marker::PhantomData<S>,
64    }
65
66    impl<S> PhysFrame<S> {
67        pub fn start_address(&self) -> PhysAddr {
68            self.start
69        }
70    }
71
72    impl PhysFrame<Size4KiB> {
73        pub fn containing_address(addr: PhysAddr) -> Self {
74            Self {
75                start: PhysAddr::new(addr.as_u64() & !0xFFF),
76                _size: core::marker::PhantomData,
77            }
78        }
79    }
80
81    impl PhysFrame<Size2MiB> {
82        pub fn containing_address(addr: PhysAddr) -> Self {
83            Self {
84                start: PhysAddr::new(addr.as_u64() & !(SIZE_2MIB - 1)),
85                _size: core::marker::PhantomData,
86            }
87        }
88    }
89}
90
91#[cfg(not(target_arch = "x86_64"))]
92pub use neutral::*;
93
94/// Address bits within a page-table entry (Sv48: PPN[2..0] + flags).
95pub const PTR_MASK: u64 = 0x0000_FFFF_FFFF_F000;
96
97/// Translation trait mirroring `x86_64::structures::paging::Translate`
98/// (neutral version; on riscv64 implemented by the Sv48 mapper).
99#[cfg(not(target_arch = "x86_64"))]
100pub trait Translate {
101    fn translate(&self, virt: VirtAddr) -> Option<(PhysFrame<Size4KiB>, PageTableFlags)>;
102}