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