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 }
32}
33
34impl From<PTEFlags> for MappingFlags {
35 fn from(f: PTEFlags) -> Self {
36 let mut ret = Self::empty();
37 if !f.contains(PTEFlags::V) {
38 return ret;
39 }
40 if f.contains(PTEFlags::R) {
41 ret |= Self::READ;
42 }
43 if f.contains(PTEFlags::W) {
44 ret |= Self::WRITE;
45 }
46 if f.contains(PTEFlags::X) {
47 ret |= Self::EXECUTE;
48 }
49 if f.contains(PTEFlags::U) {
50 ret |= Self::USER;
51 }
52 ret
53 }
54}
55
56impl From<MappingFlags> for PTEFlags {
57 fn from(f: MappingFlags) -> Self {
58 if f.is_empty() {
59 return Self::empty();
60 }
61 let mut ret = Self::V;
62 if f.contains(MappingFlags::READ) {
63 ret |= Self::R;
64 }
65 if f.contains(MappingFlags::WRITE) {
66 ret |= Self::W;
67 }
68 if f.contains(MappingFlags::EXECUTE) {
69 ret |= Self::X;
70 }
71 if f.contains(MappingFlags::USER) {
72 ret |= Self::U;
73 }
74 ret
75 }
76}
77
78#[derive(Clone, Copy)]
80#[repr(transparent)]
81pub struct Rv64PTE(u64);
82
83impl Rv64PTE {
84 const PHYS_ADDR_MASK: u64 = (1 << 54) - (1 << 10);
86
87 pub const fn empty() -> Self {
89 Self(0)
90 }
91}
92
93impl GenericPTE for Rv64PTE {
94 fn new_page(paddr: PhysAddr, flags: MappingFlags, _is_huge: bool) -> Self {
95 let flags = PTEFlags::from(flags) | PTEFlags::A | PTEFlags::D;
96 debug_assert!(flags.intersects(PTEFlags::R | PTEFlags::X));
97 Self(flags.bits() as u64 | ((paddr.as_usize() >> 2) as u64 & Self::PHYS_ADDR_MASK))
98 }
99
100 fn new_table(paddr: PhysAddr) -> Self {
101 Self(PTEFlags::V.bits() as u64 | ((paddr.as_usize() >> 2) as u64 & Self::PHYS_ADDR_MASK))
102 }
103
104 fn paddr(&self) -> PhysAddr {
105 PhysAddr::from(((self.0 & Self::PHYS_ADDR_MASK) << 2) as usize)
106 }
107
108 fn flags(&self) -> MappingFlags {
109 PTEFlags::from_bits_truncate(self.0 as usize).into()
110 }
111
112 fn set_paddr(&mut self, paddr: PhysAddr) {
113 self.0 = (self.0 & !Self::PHYS_ADDR_MASK)
114 | ((paddr.as_usize() as u64 >> 2) & Self::PHYS_ADDR_MASK);
115 }
116
117 fn set_flags(&mut self, flags: MappingFlags, _is_huge: bool) {
118 let flags = PTEFlags::from(flags) | PTEFlags::A | PTEFlags::D;
119 debug_assert!(flags.intersects(PTEFlags::R | PTEFlags::X));
120 self.0 = (self.0 & Self::PHYS_ADDR_MASK) | flags.bits() as u64;
121 }
122
123 fn bits(self) -> usize {
124 self.0 as usize
125 }
126
127 fn is_unused(&self) -> bool {
128 self.0 == 0
129 }
130
131 fn is_present(&self) -> bool {
132 PTEFlags::from_bits_truncate(self.0 as usize).contains(PTEFlags::V)
133 }
134
135 fn is_huge(&self) -> bool {
136 PTEFlags::from_bits_truncate(self.0 as usize).intersects(PTEFlags::R | PTEFlags::X)
137 }
138
139 fn clear(&mut self) {
140 self.0 = 0
141 }
142}
143
144impl fmt::Debug for Rv64PTE {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 let mut f = f.debug_struct("Rv64PTE");
147 f.field("raw", &self.0)
148 .field("paddr", &self.paddr())
149 .field("flags", &self.flags())
150 .finish()
151 }
152}