os/arch/riscv/mm/
page_table_entry.rs1use crate::mm::address::{Ppn, UsizeConvert};
2use crate::mm::page_table::PageTableEntry as PageTableEntryTrait;
3use crate::mm::page_table::{UniversalConvertableFlag, UniversalPTEFlag};
4
5bitflags::bitflags! {
7 pub struct SV39PTEFlags: usize {
8 const VALID = 1 << 0; const READ = 1 << 1; const WRITE = 1 << 2; const EXECUTE = 1 << 3; const USER = 1 << 4; const GLOBAL = 1 << 5; const ACCESSED = 1 << 6; const DIRTY = 1 << 7; const _RESERVED = 1 << 8; }
18}
19
20const SV39_PTE_FLAG_MASK: usize = 0xff; const SV39_PTE_PPN_OFFSET: usize = 10; const SV39_PTE_PPN_MASK: u64 = 0x0000_ffff_ffff_fc00; impl UniversalConvertableFlag for SV39PTEFlags {
42 fn from_universal(flag: UniversalPTEFlag) -> Self {
44 Self::from_bits(flag.bits() & SV39_PTE_FLAG_MASK).unwrap()
46 }
47
48 fn to_universal(&self) -> UniversalPTEFlag {
50 UniversalPTEFlag::from_bits(self.bits() & SV39_PTE_FLAG_MASK).unwrap()
51 }
52}
53
54#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
56pub struct PageTableEntry(u64);
57
58impl PageTableEntryTrait for PageTableEntry {
60 type Bits = u64; fn from_bits(bits: Self::Bits) -> Self {
64 PageTableEntry(bits)
65 }
66
67 fn to_bits(&self) -> Self::Bits {
69 self.0
70 }
71
72 fn empty() -> Self {
74 PageTableEntry(0)
75 }
76
77 fn new_leaf(ppn: Ppn, flags: UniversalPTEFlag) -> Self {
79 let ppn_bits: u64 = ppn.as_usize() as u64;
80 let sv39_flags = SV39PTEFlags::from_universal(flags);
81 PageTableEntry((ppn_bits << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64))
83 }
84
85 fn new_table(ppn: Ppn) -> Self {
87 let ppn_bits: u64 = ppn.as_usize() as u64;
88 let sv39_flags = SV39PTEFlags::VALID;
90 PageTableEntry((ppn_bits << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64))
91 }
92
93 fn is_valid(&self) -> bool {
95 (self.0 & SV39PTEFlags::VALID.bits() as u64) != 0
96 }
97
98 fn is_huge(&self) -> bool {
100 let sv39_flags =
104 SV39PTEFlags::from_bits((self.0 & SV39_PTE_FLAG_MASK as u64) as usize).unwrap();
105 sv39_flags.intersects(
107 SV39PTEFlags::union(SV39PTEFlags::READ, SV39PTEFlags::EXECUTE)
108 .union(SV39PTEFlags::WRITE),
109 )
110 }
111
112 fn is_empty(&self) -> bool {
114 self.0 == 0
115 }
116
117 fn ppn(&self) -> Ppn {
119 let ppn = (self.0 & SV39_PTE_PPN_MASK) >> SV39_PTE_PPN_OFFSET;
121 Ppn::from_usize(ppn as usize)
122 }
123
124 fn flags(&self) -> UniversalPTEFlag {
126 let sv39_flags =
128 SV39PTEFlags::from_bits((self.0 & SV39_PTE_FLAG_MASK as u64) as usize).unwrap();
129 sv39_flags.to_universal()
130 }
131
132 fn set_ppn(&mut self, ppn: Ppn) {
134 let ppn_bits = ppn.as_usize() as u64;
135 self.0 = (self.0 & !SV39_PTE_PPN_MASK) | (ppn_bits << SV39_PTE_PPN_OFFSET);
137 }
138
139 fn set_flags(&mut self, flags: UniversalPTEFlag) {
141 let sv39_flags = SV39PTEFlags::from_universal(flags);
142 self.0 = (self.0 & !(SV39_PTE_FLAG_MASK as u64)) | (sv39_flags.bits() as u64);
144 }
145
146 fn clear(&mut self) {
148 self.0 = 0;
149 }
150
151 fn remove_flags(&mut self, flags: UniversalPTEFlag) {
153 let current_flags = self.flags();
154 let new_flags = current_flags & !flags;
155 self.set_flags(new_flags);
156 }
157
158 fn add_flags(&mut self, flags: UniversalPTEFlag) {
160 self.set_flags(self.flags() | flags);
161 }
162}