page_table_entry/arch/
loongarch64.rs1use core::fmt;
8
9use memory_addr::PhysAddr;
10
11use crate::{GenericPTE, MappingFlags};
12
13bitflags::bitflags! {
14 #[derive(Debug)]
18 pub struct PTEFlags: u64 {
19 const V = 1 << 0;
21 const D = 1 << 1;
24 const PLVL = 1 << 2;
26 const PLVH = 1 << 3;
28 const MATL = 1 << 4;
43 const MATH = 1 << 5;
45 const GH = 1 << 6;
47 const P = 1 << 7;
49 const W = 1 << 8;
51 const G = 1 << 12;
53 const NR = 1 << 61;
55 const NX = 1 << 62;
57 const RPLV = 1 << 63;
60 }
61}
62
63impl From<PTEFlags> for MappingFlags {
64 fn from(f: PTEFlags) -> Self {
65 if !f.contains(PTEFlags::V) {
66 return Self::empty();
67 }
68 let mut ret = Self::empty();
69 if !f.contains(PTEFlags::NR) {
70 ret |= Self::READ;
71 }
72 if f.contains(PTEFlags::W) {
73 ret |= Self::WRITE;
74 }
75 if !f.contains(PTEFlags::NX) {
76 ret |= Self::EXECUTE;
77 }
78 if f.contains(PTEFlags::PLVL | PTEFlags::PLVH) {
79 ret |= Self::USER;
80 }
81 if !f.contains(PTEFlags::MATL) {
82 if f.contains(PTEFlags::MATH) {
83 ret |= Self::UNCACHED;
84 } else {
85 ret |= Self::DEVICE;
86 }
87 }
88 ret
89 }
90}
91
92impl From<MappingFlags> for PTEFlags {
93 fn from(f: MappingFlags) -> Self {
94 if f.is_empty() {
95 return Self::empty();
96 }
97 let mut ret = Self::V | Self::P;
98 if !f.contains(MappingFlags::READ) {
99 ret |= Self::NR;
100 }
101 if f.contains(MappingFlags::WRITE) {
102 ret |= Self::W | Self::D;
103 }
104 if !f.contains(MappingFlags::EXECUTE) {
105 ret |= Self::NX;
106 }
107 if f.contains(MappingFlags::USER) {
108 ret |= Self::PLVH | Self::PLVL;
109 }
110 if !f.contains(MappingFlags::DEVICE) {
111 if f.contains(MappingFlags::UNCACHED) {
112 ret |= Self::MATH;
114 } else {
115 ret |= Self::MATL;
117 }
118 }
119 ret
120 }
121}
122
123#[derive(Clone, Copy)]
125#[repr(transparent)]
126pub struct LA64PTE(u64);
127
128impl LA64PTE {
129 const PHYS_ADDR_MASK: u64 = 0x0000_ffff_ffff_f000;
131
132 pub const fn empty() -> Self {
134 Self(0)
135 }
136}
137
138impl GenericPTE for LA64PTE {
139 fn new_page(paddr: PhysAddr, flags: MappingFlags, is_huge: bool) -> Self {
140 let mut flags = PTEFlags::from(flags);
141 if is_huge {
142 flags |= PTEFlags::GH;
143 }
144 Self(flags.bits() | ((paddr.as_usize()) as u64 & Self::PHYS_ADDR_MASK))
145 }
146
147 fn new_table(paddr: PhysAddr) -> Self {
148 Self((paddr.as_usize() as u64) & Self::PHYS_ADDR_MASK)
149 }
150
151 fn paddr(&self) -> PhysAddr {
152 PhysAddr::from((self.0 & Self::PHYS_ADDR_MASK) as usize)
153 }
154
155 fn flags(&self) -> MappingFlags {
156 PTEFlags::from_bits_truncate(self.0).into()
157 }
158
159 fn set_paddr(&mut self, paddr: PhysAddr) {
160 self.0 = (self.0 & !Self::PHYS_ADDR_MASK) | (paddr.as_usize() as u64 & Self::PHYS_ADDR_MASK)
161 }
162
163 fn set_flags(&mut self, flags: MappingFlags, is_huge: bool) {
164 let mut flags = PTEFlags::from(flags);
165 if is_huge {
166 flags |= PTEFlags::GH;
167 }
168 self.0 = (self.0 & Self::PHYS_ADDR_MASK) | flags.bits();
169 }
170
171 fn bits(self) -> usize {
172 self.0 as usize
173 }
174
175 fn is_unused(&self) -> bool {
176 self.0 == 0
177 }
178
179 fn is_present(&self) -> bool {
180 PTEFlags::from_bits_truncate(self.0).contains(PTEFlags::P)
181 }
182
183 fn is_huge(&self) -> bool {
184 PTEFlags::from_bits_truncate(self.0).contains(PTEFlags::GH)
185 }
186
187 fn clear(&mut self) {
188 self.0 = 0
189 }
190}
191
192impl fmt::Debug for LA64PTE {
193 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 let mut f = f.debug_struct("LA64PTE");
195 f.field("raw", &self.0)
196 .field("paddr", &self.paddr())
197 .field("flags", &self.flags())
198 .finish()
199 }
200}