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