page_table_entry/arch/
riscv.rs1use core::fmt;
4
5use memory_addr::PhysAddr;
6
7use crate::{GenericPTE, MappingFlags};
8
9bitflags::bitflags! {
10 #[derive(Debug)]
12 pub struct PTEFlags: usize {
13 const V = 1 << 0;
15 const R = 1 << 1;
17 const W = 1 << 2;
19 const X = 1 << 3;
21 const U = 1 << 4;
23 const G = 1 << 5;
25 const A = 1 << 6;
28 const D = 1 << 7;
31 #[cfg(feature = "xuantie-c9xx")]
36 const SO = (1 << 63);
37 #[cfg(feature = "xuantie-c9xx")]
39 const C = (1 << 62);
40 #[cfg(feature = "xuantie-c9xx")]
42 const B = (1 << 61);
43 #[cfg(feature = "xuantie-c9xx")]
45 const SH = (1 << 60);
46
47 #[cfg(feature = "xuantie-c9xx")]
49 const XUANTIE_C9XX_DEVICE = Self::SO.bits() | Self::B.bits();
50 #[cfg(feature = "xuantie-c9xx")]
52 const XUANTIE_C9XX_NORMAL = Self::C.bits() | Self::B.bits() | Self::SH.bits();
53 }
54}
55
56impl From<PTEFlags> for MappingFlags {
57 fn from(f: PTEFlags) -> Self {
58 let mut ret = Self::empty();
59 if !f.contains(PTEFlags::V) {
60 return ret;
61 }
62 if f.contains(PTEFlags::R) {
63 ret |= Self::READ;
64 }
65 if f.contains(PTEFlags::W) {
66 ret |= Self::WRITE;
67 }
68 if f.contains(PTEFlags::X) {
69 ret |= Self::EXECUTE;
70 }
71 if f.contains(PTEFlags::U) {
72 ret |= Self::USER;
73 }
74 ret
75 }
76}
77
78impl From<MappingFlags> for PTEFlags {
79 fn from(f: MappingFlags) -> Self {
80 if f.is_empty() {
81 return Self::empty();
82 }
83 let mut ret = Self::V | Self::A | Self::D;
84 if f.contains(MappingFlags::READ) {
85 ret |= Self::R;
86 }
87 if f.contains(MappingFlags::WRITE) {
88 ret |= Self::W;
89 }
90 if f.contains(MappingFlags::EXECUTE) {
91 ret |= Self::X;
92 }
93 if f.contains(MappingFlags::USER) {
94 ret |= Self::U;
95 }
96
97 #[cfg(feature = "xuantie-c9xx")]
98 if f.contains(MappingFlags::DEVICE) {
99 ret |= Self::XUANTIE_C9XX_DEVICE;
100 } else {
101 ret |= Self::XUANTIE_C9XX_NORMAL;
102 }
103
104 ret
105 }
106}
107
108#[derive(Clone, Copy)]
110#[repr(transparent)]
111pub struct Rv64PTE(u64);
112
113impl Rv64PTE {
114 const PHYS_ADDR_MASK: u64 = (1 << 54) - (1 << 10);
116
117 pub const fn empty() -> Self {
119 Self(0)
120 }
121}
122
123impl GenericPTE for Rv64PTE {
124 fn new_page(paddr: PhysAddr, mflags: MappingFlags, _is_huge: bool) -> Self {
125 let flags = PTEFlags::from(mflags);
126 debug_assert!(flags.intersects(PTEFlags::R | PTEFlags::X));
127 Self(flags.bits() as u64 | ((paddr.as_usize() >> 2) as u64 & Self::PHYS_ADDR_MASK))
128 }
129
130 fn new_table(paddr: PhysAddr) -> Self {
131 Self(PTEFlags::V.bits() as u64 | ((paddr.as_usize() >> 2) as u64 & Self::PHYS_ADDR_MASK))
132 }
133
134 fn paddr(&self) -> PhysAddr {
135 PhysAddr::from(((self.0 & Self::PHYS_ADDR_MASK) << 2) as usize)
136 }
137
138 fn flags(&self) -> MappingFlags {
139 PTEFlags::from_bits_truncate(self.0 as usize).into()
140 }
141
142 fn set_paddr(&mut self, paddr: PhysAddr) {
143 self.0 = (self.0 & !Self::PHYS_ADDR_MASK)
144 | ((paddr.as_usize() as u64 >> 2) & Self::PHYS_ADDR_MASK);
145 }
146
147 fn set_flags(&mut self, flags: MappingFlags, _is_huge: bool) {
148 let flags = PTEFlags::from(flags);
149 debug_assert!(flags.intersects(PTEFlags::R | PTEFlags::X));
150 self.0 = (self.0 & Self::PHYS_ADDR_MASK) | flags.bits() as u64;
151 }
152
153 fn bits(self) -> usize {
154 self.0 as usize
155 }
156
157 fn is_unused(&self) -> bool {
158 self.0 == 0
159 }
160
161 fn is_present(&self) -> bool {
162 PTEFlags::from_bits_truncate(self.0 as usize).contains(PTEFlags::V)
163 }
164
165 fn is_huge(&self) -> bool {
166 PTEFlags::from_bits_truncate(self.0 as usize).intersects(PTEFlags::R | PTEFlags::X)
167 }
168
169 fn clear(&mut self) {
170 self.0 = 0
171 }
172}
173
174impl fmt::Debug for Rv64PTE {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 let mut f = f.debug_struct("Rv64PTE");
177 f.field("raw", &self.0)
178 .field("paddr", &self.paddr())
179 .field("flags", &self.flags())
180 .finish()
181 }
182}