page_table_entry/arch/
x86_64.rs1use core::fmt;
4
5use memory_addr::PhysAddr;
6pub use x86_64::structures::paging::page_table::PageTableFlags as PTF;
7
8use crate::{GenericPTE, MappingFlags};
9
10impl From<PTF> for MappingFlags {
11 fn from(f: PTF) -> Self {
12 if !f.contains(PTF::PRESENT) {
13 return Self::empty();
14 }
15 let mut ret = Self::READ;
16 if f.contains(PTF::WRITABLE) {
17 ret |= Self::WRITE;
18 }
19 if !f.contains(PTF::NO_EXECUTE) {
20 ret |= Self::EXECUTE;
21 }
22 if f.contains(PTF::USER_ACCESSIBLE) {
23 ret |= Self::USER;
24 }
25 if f.contains(PTF::NO_CACHE) {
26 ret |= Self::UNCACHED;
27 }
28 ret
29 }
30}
31
32impl From<MappingFlags> for PTF {
33 fn from(f: MappingFlags) -> Self {
34 if f.is_empty() {
35 return Self::empty();
36 }
37 let mut ret = Self::PRESENT;
38 if f.contains(MappingFlags::WRITE) {
39 ret |= Self::WRITABLE;
40 }
41 if !f.contains(MappingFlags::EXECUTE) {
42 ret |= Self::NO_EXECUTE;
43 }
44 if f.contains(MappingFlags::USER) {
45 ret |= Self::USER_ACCESSIBLE;
46 }
47 if f.contains(MappingFlags::DEVICE) || f.contains(MappingFlags::UNCACHED) {
48 ret |= Self::NO_CACHE | Self::WRITE_THROUGH;
49 }
50 ret
51 }
52}
53
54#[derive(Clone, Copy)]
56#[repr(transparent)]
57pub struct X64PTE(u64);
58
59impl X64PTE {
60 const PHYS_ADDR_MASK: u64 = 0x000f_ffff_ffff_f000;
62
63 pub const fn empty() -> Self {
65 Self(0)
66 }
67}
68
69impl GenericPTE for X64PTE {
70 fn new_page(paddr: PhysAddr, flags: MappingFlags, is_huge: bool) -> Self {
71 let mut flags = PTF::from(flags);
72 if is_huge {
73 flags |= PTF::HUGE_PAGE;
74 }
75 Self(flags.bits() | (paddr.as_usize() as u64 & Self::PHYS_ADDR_MASK))
76 }
77
78 fn new_table(paddr: PhysAddr) -> Self {
79 let flags = PTF::PRESENT | PTF::WRITABLE | PTF::USER_ACCESSIBLE;
80 Self(flags.bits() | (paddr.as_usize() as u64 & Self::PHYS_ADDR_MASK))
81 }
82
83 fn paddr(&self) -> PhysAddr {
84 PhysAddr::from((self.0 & Self::PHYS_ADDR_MASK) as usize)
85 }
86
87 fn flags(&self) -> MappingFlags {
88 PTF::from_bits_truncate(self.0).into()
89 }
90
91 fn set_paddr(&mut self, paddr: PhysAddr) {
92 self.0 = (self.0 & !Self::PHYS_ADDR_MASK) | (paddr.as_usize() as u64 & Self::PHYS_ADDR_MASK)
93 }
94
95 fn set_flags(&mut self, flags: MappingFlags, is_huge: bool) {
96 let mut flags = PTF::from(flags);
97 if is_huge {
98 flags |= PTF::HUGE_PAGE;
99 }
100 self.0 = (self.0 & Self::PHYS_ADDR_MASK) | flags.bits()
101 }
102
103 fn bits(self) -> usize {
104 self.0 as usize
105 }
106
107 fn is_unused(&self) -> bool {
108 self.0 == 0
109 }
110
111 fn is_present(&self) -> bool {
112 PTF::from_bits_truncate(self.0).contains(PTF::PRESENT)
113 }
114
115 fn is_huge(&self) -> bool {
116 PTF::from_bits_truncate(self.0).contains(PTF::HUGE_PAGE)
117 }
118
119 fn clear(&mut self) {
120 self.0 = 0
121 }
122}
123
124impl fmt::Debug for X64PTE {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 let mut f = f.debug_struct("X64PTE");
127 f.field("raw", &self.0)
128 .field("paddr", &self.paddr())
129 .field("flags", &self.flags())
130 .finish()
131 }
132}