1use bitflags::*;
4
5use core::convert::{From, Into};
6use core::fmt;
7use core::hash::{Hash, Hasher};
8use core::ops;
9
10macro_rules! check_flag {
11 ($doc:meta, $fun:ident, $flag:expr) => {
12 #[$doc]
13 pub fn $fun(self) -> bool {
14 self.flags().contains($flag)
15 }
16 };
17}
18
19#[inline(always)]
24fn align_down(addr: u32, align: u32) -> u32 {
25 addr & !(align - 1)
26}
27
28#[inline(always)]
33fn align_up(addr: u32, align: u32) -> u32 {
34 let align_mask = align - 1;
35 if addr & align_mask == 0 {
36 addr
37 } else {
38 (addr | align_mask) + 1
39 }
40}
41
42#[repr(transparent)]
44#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
45pub struct PAddr(pub u32);
46
47impl PAddr {
48 pub fn as_u32(self) -> u32 {
50 self.0
51 }
52
53 pub fn as_usize(self) -> usize {
55 self.0 as usize
56 }
57
58 pub fn as_mut_ptr<T>(self) -> *mut T {
60 self.0 as *mut T
61 }
62
63 pub fn as_ptr<T>(self) -> *const T {
65 self.0 as *const T
66 }
67
68 pub const fn zero() -> Self {
70 PAddr(0)
71 }
72
73 pub fn is_zero(self) -> bool {
75 self == PAddr::zero()
76 }
77
78 fn align_up<U>(self, align: U) -> Self
79 where
80 U: Into<u32>,
81 {
82 PAddr(align_up(self.0, align.into()))
83 }
84
85 fn align_down<U>(self, align: U) -> Self
86 where
87 U: Into<u32>,
88 {
89 PAddr(align_down(self.0, align.into()))
90 }
91
92 pub fn base_page_offset(self) -> u32 {
94 self.0 & (BASE_PAGE_SIZE as u32 - 1)
95 }
96
97 pub fn large_page_offset(self) -> u32 {
99 self.0 & (LARGE_PAGE_SIZE as u32 - 1)
100 }
101
102 pub fn align_down_to_base_page(self) -> Self {
104 self.align_down(BASE_PAGE_SIZE as u32)
105 }
106
107 pub fn align_down_to_large_page(self) -> Self {
109 self.align_down(LARGE_PAGE_SIZE as u32)
110 }
111
112 pub fn align_up_to_base_page(self) -> Self {
114 self.align_up(BASE_PAGE_SIZE as u32)
115 }
116
117 pub fn align_up_to_large_page(self) -> Self {
119 self.align_up(LARGE_PAGE_SIZE as u32)
120 }
121
122 pub fn is_base_page_aligned(self) -> bool {
124 self.align_down(BASE_PAGE_SIZE as u32) == self
125 }
126
127 pub fn is_large_page_aligned(self) -> bool {
129 self.align_down(LARGE_PAGE_SIZE as u32) == self
130 }
131
132 pub fn is_aligned<U>(self, align: U) -> bool
137 where
138 U: Into<u32> + Copy,
139 {
140 if !align.into().is_power_of_two() {
141 return false;
142 }
143
144 self.align_down(align) == self
145 }
146}
147
148impl From<u32> for PAddr {
149 fn from(num: u32) -> Self {
150 PAddr(num)
151 }
152}
153
154impl From<usize> for PAddr {
155 fn from(num: usize) -> Self {
156 PAddr(num as u32)
157 }
158}
159
160impl From<i32> for PAddr {
161 fn from(num: i32) -> Self {
162 PAddr(num as u32)
163 }
164}
165
166#[allow(clippy::clippy::from_over_into)]
167impl Into<u32> for PAddr {
168 fn into(self) -> u32 {
169 self.0
170 }
171}
172
173#[allow(clippy::clippy::from_over_into)]
174impl Into<usize> for PAddr {
175 fn into(self) -> usize {
176 self.0 as usize
177 }
178}
179
180impl ops::Add for PAddr {
181 type Output = PAddr;
182
183 fn add(self, rhs: PAddr) -> Self::Output {
184 PAddr(self.0 + rhs.0)
185 }
186}
187
188impl ops::Add<u32> for PAddr {
189 type Output = PAddr;
190
191 fn add(self, rhs: u32) -> Self::Output {
192 PAddr::from(self.0 + rhs)
193 }
194}
195
196impl ops::Add<usize> for PAddr {
197 type Output = PAddr;
198
199 fn add(self, rhs: usize) -> Self::Output {
200 PAddr::from(self.0 + rhs as u32)
201 }
202}
203
204impl ops::AddAssign for PAddr {
205 fn add_assign(&mut self, other: PAddr) {
206 *self = PAddr::from(self.0 + other.0);
207 }
208}
209
210impl ops::AddAssign<u32> for PAddr {
211 fn add_assign(&mut self, offset: u32) {
212 *self = PAddr::from(self.0 + offset);
213 }
214}
215
216impl ops::Sub for PAddr {
217 type Output = PAddr;
218
219 fn sub(self, rhs: PAddr) -> Self::Output {
220 PAddr::from(self.0 - rhs.0)
221 }
222}
223
224impl ops::Sub<u32> for PAddr {
225 type Output = PAddr;
226
227 fn sub(self, rhs: u32) -> Self::Output {
228 PAddr::from(self.0 - rhs)
229 }
230}
231
232impl ops::Sub<usize> for PAddr {
233 type Output = PAddr;
234
235 fn sub(self, rhs: usize) -> Self::Output {
236 PAddr::from(self.0 - rhs as u32)
237 }
238}
239
240impl ops::Rem for PAddr {
241 type Output = PAddr;
242
243 fn rem(self, rhs: PAddr) -> Self::Output {
244 PAddr(self.0 % rhs.0)
245 }
246}
247
248impl ops::Rem<u32> for PAddr {
249 type Output = u32;
250
251 fn rem(self, rhs: u32) -> Self::Output {
252 self.0 % rhs
253 }
254}
255
256impl ops::Rem<usize> for PAddr {
257 type Output = u32;
258
259 fn rem(self, rhs: usize) -> Self::Output {
260 self.0 % (rhs as u32)
261 }
262}
263
264impl ops::BitAnd for PAddr {
265 type Output = Self;
266
267 fn bitand(self, rhs: Self) -> Self {
268 PAddr(self.0 & rhs.0)
269 }
270}
271
272impl ops::BitAnd<u32> for PAddr {
273 type Output = u32;
274
275 fn bitand(self, rhs: u32) -> Self::Output {
276 Into::<u32>::into(self) & rhs
277 }
278}
279
280impl ops::BitOr for PAddr {
281 type Output = PAddr;
282
283 fn bitor(self, rhs: PAddr) -> Self::Output {
284 PAddr(self.0 | rhs.0)
285 }
286}
287
288impl ops::BitOr<u32> for PAddr {
289 type Output = u32;
290
291 fn bitor(self, rhs: u32) -> Self::Output {
292 self.0 | rhs
293 }
294}
295
296impl ops::Shr<u32> for PAddr {
297 type Output = u32;
298
299 fn shr(self, rhs: u32) -> Self::Output {
300 self.0 >> rhs
301 }
302}
303
304impl fmt::Binary for PAddr {
305 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
306 self.0.fmt(f)
307 }
308}
309
310impl fmt::Display for PAddr {
311 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312 self.0.fmt(f)
313 }
314}
315
316impl fmt::Debug for PAddr {
317 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318 write!(f, "{:#x}", self.0)
319 }
320}
321
322impl fmt::LowerHex for PAddr {
323 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
324 self.0.fmt(f)
325 }
326}
327
328impl fmt::Octal for PAddr {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 self.0.fmt(f)
331 }
332}
333
334impl fmt::UpperHex for PAddr {
335 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336 self.0.fmt(f)
337 }
338}
339
340impl fmt::Pointer for PAddr {
341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342 use core::fmt::LowerHex;
343 self.0.fmt(f)
344 }
345}
346
347#[allow(clippy::clippy::derive_hash_xor_eq)]
348impl Hash for PAddr {
349 fn hash<H: Hasher>(&self, state: &mut H) {
350 self.0.hash(state);
351 }
352}
353
354#[repr(transparent)]
356#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
357pub struct IOAddr(pub u32);
358
359impl IOAddr {
360 pub fn as_u32(self) -> u32 {
362 self.0
363 }
364
365 pub fn as_usize(self) -> usize {
367 self.0 as usize
368 }
369
370 pub const fn zero() -> Self {
372 IOAddr(0)
373 }
374
375 pub fn is_zero(self) -> bool {
377 self == IOAddr::zero()
378 }
379
380 fn align_up<U>(self, align: U) -> Self
381 where
382 U: Into<u32>,
383 {
384 IOAddr(align_up(self.0, align.into()))
385 }
386
387 fn align_down<U>(self, align: U) -> Self
388 where
389 U: Into<u32>,
390 {
391 IOAddr(align_down(self.0, align.into()))
392 }
393
394 pub fn base_page_offset(self) -> u32 {
396 self.0 & (BASE_PAGE_SIZE as u32 - 1)
397 }
398
399 pub fn large_page_offset(self) -> u32 {
401 self.0 & (LARGE_PAGE_SIZE as u32 - 1)
402 }
403
404 pub fn align_down_to_base_page(self) -> Self {
406 self.align_down(BASE_PAGE_SIZE as u32)
407 }
408
409 pub fn align_down_to_large_page(self) -> Self {
411 self.align_down(LARGE_PAGE_SIZE as u32)
412 }
413
414 pub fn align_up_to_base_page(self) -> Self {
416 self.align_up(BASE_PAGE_SIZE as u32)
417 }
418
419 pub fn align_up_to_large_page(self) -> Self {
421 self.align_up(LARGE_PAGE_SIZE as u32)
422 }
423
424 pub fn is_base_page_aligned(self) -> bool {
426 self.align_down(BASE_PAGE_SIZE as u32) == self
427 }
428
429 pub fn is_large_page_aligned(self) -> bool {
431 self.align_down(LARGE_PAGE_SIZE as u32) == self
432 }
433
434 pub fn is_aligned<U>(self, align: U) -> bool
439 where
440 U: Into<u32> + Copy,
441 {
442 if !align.into().is_power_of_two() {
443 return false;
444 }
445
446 self.align_down(align) == self
447 }
448}
449
450impl From<u32> for IOAddr {
451 fn from(num: u32) -> Self {
452 IOAddr(num)
453 }
454}
455
456impl From<usize> for IOAddr {
457 fn from(num: usize) -> Self {
458 IOAddr(num as u32)
459 }
460}
461
462impl From<i32> for IOAddr {
463 fn from(num: i32) -> Self {
464 IOAddr(num as u32)
465 }
466}
467
468#[allow(clippy::clippy::from_over_into)]
469impl Into<u32> for IOAddr {
470 fn into(self) -> u32 {
471 self.0
472 }
473}
474
475#[allow(clippy::clippy::from_over_into)]
476impl Into<usize> for IOAddr {
477 fn into(self) -> usize {
478 self.0 as usize
479 }
480}
481
482impl ops::Add for IOAddr {
483 type Output = IOAddr;
484
485 fn add(self, rhs: IOAddr) -> Self::Output {
486 IOAddr(self.0 + rhs.0)
487 }
488}
489
490impl ops::Add<u32> for IOAddr {
491 type Output = IOAddr;
492
493 fn add(self, rhs: u32) -> Self::Output {
494 IOAddr::from(self.0 + rhs)
495 }
496}
497
498impl ops::Add<usize> for IOAddr {
499 type Output = IOAddr;
500
501 fn add(self, rhs: usize) -> Self::Output {
502 IOAddr::from(self.0 + rhs as u32)
503 }
504}
505
506impl ops::AddAssign for IOAddr {
507 fn add_assign(&mut self, other: IOAddr) {
508 *self = IOAddr::from(self.0 + other.0);
509 }
510}
511
512impl ops::AddAssign<u32> for IOAddr {
513 fn add_assign(&mut self, offset: u32) {
514 *self = IOAddr::from(self.0 + offset);
515 }
516}
517
518impl ops::Sub for IOAddr {
519 type Output = IOAddr;
520
521 fn sub(self, rhs: IOAddr) -> Self::Output {
522 IOAddr::from(self.0 - rhs.0)
523 }
524}
525
526impl ops::Sub<u32> for IOAddr {
527 type Output = IOAddr;
528
529 fn sub(self, rhs: u32) -> Self::Output {
530 IOAddr::from(self.0 - rhs)
531 }
532}
533
534impl ops::Sub<usize> for IOAddr {
535 type Output = IOAddr;
536
537 fn sub(self, rhs: usize) -> Self::Output {
538 IOAddr::from(self.0 - rhs as u32)
539 }
540}
541
542impl ops::Rem for IOAddr {
543 type Output = IOAddr;
544
545 fn rem(self, rhs: IOAddr) -> Self::Output {
546 IOAddr(self.0 % rhs.0)
547 }
548}
549
550impl ops::Rem<u32> for IOAddr {
551 type Output = u32;
552
553 fn rem(self, rhs: u32) -> Self::Output {
554 self.0 % rhs
555 }
556}
557
558impl ops::Rem<usize> for IOAddr {
559 type Output = u32;
560
561 fn rem(self, rhs: usize) -> Self::Output {
562 self.0 % (rhs as u32)
563 }
564}
565
566impl ops::BitAnd for IOAddr {
567 type Output = Self;
568
569 fn bitand(self, rhs: Self) -> Self {
570 IOAddr(self.0 & rhs.0)
571 }
572}
573
574impl ops::BitAnd<u32> for IOAddr {
575 type Output = u32;
576
577 fn bitand(self, rhs: u32) -> Self::Output {
578 Into::<u32>::into(self) & rhs
579 }
580}
581
582impl ops::BitOr for IOAddr {
583 type Output = IOAddr;
584
585 fn bitor(self, rhs: IOAddr) -> Self::Output {
586 IOAddr(self.0 | rhs.0)
587 }
588}
589
590impl ops::BitOr<u32> for IOAddr {
591 type Output = u32;
592
593 fn bitor(self, rhs: u32) -> Self::Output {
594 self.0 | rhs
595 }
596}
597
598impl ops::Shr<u32> for IOAddr {
599 type Output = u32;
600
601 fn shr(self, rhs: u32) -> Self::Output {
602 self.0 >> rhs
603 }
604}
605
606impl fmt::Binary for IOAddr {
607 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
608 self.0.fmt(f)
609 }
610}
611
612impl fmt::Display for IOAddr {
613 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
614 self.0.fmt(f)
615 }
616}
617
618impl fmt::Debug for IOAddr {
619 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
620 write!(f, "{:#x}", self.0)
621 }
622}
623
624impl fmt::LowerHex for IOAddr {
625 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626 self.0.fmt(f)
627 }
628}
629
630impl fmt::Octal for IOAddr {
631 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
632 self.0.fmt(f)
633 }
634}
635
636impl fmt::UpperHex for IOAddr {
637 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
638 self.0.fmt(f)
639 }
640}
641
642impl fmt::Pointer for IOAddr {
643 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644 use core::fmt::LowerHex;
645 self.0.fmt(f)
646 }
647}
648
649#[allow(clippy::clippy::derive_hash_xor_eq)]
650impl Hash for IOAddr {
651 fn hash<H: Hasher>(&self, state: &mut H) {
652 self.0.hash(state);
653 }
654}
655
656#[repr(transparent)]
658#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
659pub struct VAddr(pub u32);
660
661impl VAddr {
662 pub const fn from_u32(v: u32) -> Self {
664 VAddr(v)
665 }
666
667 pub const fn from_usize(v: usize) -> Self {
669 VAddr(v as u32)
670 }
671
672 pub const fn as_u32(self) -> u32 {
674 self.0
675 }
676
677 pub const fn as_usize(self) -> usize {
679 self.0 as usize
680 }
681
682 pub fn as_mut_ptr<T>(self) -> *mut T {
684 self.0 as *mut T
685 }
686
687 pub fn as_ptr<T>(self) -> *const T {
689 self.0 as *const T
690 }
691
692 pub const fn zero() -> Self {
694 VAddr(0)
695 }
696
697 pub fn is_zero(self) -> bool {
699 self == VAddr::zero()
700 }
701
702 fn align_up<U>(self, align: U) -> Self
703 where
704 U: Into<u32>,
705 {
706 VAddr(align_up(self.0, align.into()))
707 }
708
709 fn align_down<U>(self, align: U) -> Self
710 where
711 U: Into<u32>,
712 {
713 VAddr(align_down(self.0, align.into()))
714 }
715
716 pub fn base_page_offset(self) -> u32 {
718 self.0 & (BASE_PAGE_SIZE as u32 - 1)
719 }
720
721 pub fn large_page_offset(self) -> u32 {
723 self.0 & (LARGE_PAGE_SIZE as u32 - 1)
724 }
725
726 pub fn align_down_to_base_page(self) -> Self {
728 self.align_down(BASE_PAGE_SIZE as u32)
729 }
730
731 pub fn align_down_to_large_page(self) -> Self {
733 self.align_down(LARGE_PAGE_SIZE as u32)
734 }
735
736 pub fn align_up_to_base_page(self) -> Self {
738 self.align_up(BASE_PAGE_SIZE as u32)
739 }
740
741 pub fn align_up_to_large_page(self) -> Self {
743 self.align_up(LARGE_PAGE_SIZE as u32)
744 }
745
746 pub fn is_base_page_aligned(self) -> bool {
748 self.align_down(BASE_PAGE_SIZE as u32) == self
749 }
750
751 pub fn is_large_page_aligned(self) -> bool {
753 self.align_down(LARGE_PAGE_SIZE as u32) == self
754 }
755
756 pub fn is_aligned<U>(self, align: U) -> bool
761 where
762 U: Into<u32> + Copy,
763 {
764 if !align.into().is_power_of_two() {
765 return false;
766 }
767
768 self.align_down(align) == self
769 }
770}
771
772impl From<u32> for VAddr {
773 fn from(num: u32) -> Self {
774 VAddr(num)
775 }
776}
777
778impl From<i32> for VAddr {
779 fn from(num: i32) -> Self {
780 VAddr(num as u32)
781 }
782}
783
784#[allow(clippy::clippy::from_over_into)]
785impl Into<u32> for VAddr {
786 fn into(self) -> u32 {
787 self.0
788 }
789}
790
791impl From<usize> for VAddr {
792 fn from(num: usize) -> Self {
793 VAddr(num as u32)
794 }
795}
796
797#[allow(clippy::clippy::from_over_into)]
798impl Into<usize> for VAddr {
799 fn into(self) -> usize {
800 self.0 as usize
801 }
802}
803
804impl ops::Add for VAddr {
805 type Output = VAddr;
806
807 fn add(self, rhs: VAddr) -> Self::Output {
808 VAddr(self.0 + rhs.0)
809 }
810}
811
812impl ops::Add<u32> for VAddr {
813 type Output = VAddr;
814
815 fn add(self, rhs: u32) -> Self::Output {
816 VAddr(self.0 + rhs)
817 }
818}
819
820impl ops::Add<usize> for VAddr {
821 type Output = VAddr;
822
823 fn add(self, rhs: usize) -> Self::Output {
824 VAddr::from(self.0 + rhs as u32)
825 }
826}
827
828impl ops::AddAssign for VAddr {
829 fn add_assign(&mut self, other: VAddr) {
830 *self = VAddr::from(self.0 + other.0);
831 }
832}
833
834impl ops::AddAssign<u32> for VAddr {
835 fn add_assign(&mut self, offset: u32) {
836 *self = VAddr::from(self.0 + offset);
837 }
838}
839
840impl ops::AddAssign<usize> for VAddr {
841 fn add_assign(&mut self, offset: usize) {
842 *self = VAddr::from(self.0 + offset as u32);
843 }
844}
845
846impl ops::Sub for VAddr {
847 type Output = VAddr;
848
849 fn sub(self, rhs: VAddr) -> Self::Output {
850 VAddr::from(self.0 - rhs.0)
851 }
852}
853
854impl ops::Sub<u32> for VAddr {
855 type Output = VAddr;
856
857 fn sub(self, rhs: u32) -> Self::Output {
858 VAddr::from(self.0 - rhs)
859 }
860}
861
862impl ops::Sub<usize> for VAddr {
863 type Output = VAddr;
864
865 fn sub(self, rhs: usize) -> Self::Output {
866 VAddr::from(self.0 - rhs as u32)
867 }
868}
869
870impl ops::Rem for VAddr {
871 type Output = VAddr;
872
873 fn rem(self, rhs: VAddr) -> Self::Output {
874 VAddr(self.0 % rhs.0)
875 }
876}
877
878impl ops::Rem<u32> for VAddr {
879 type Output = u32;
880
881 fn rem(self, rhs: Self::Output) -> Self::Output {
882 self.0 % rhs
883 }
884}
885
886impl ops::Rem<usize> for VAddr {
887 type Output = usize;
888
889 fn rem(self, rhs: Self::Output) -> Self::Output {
890 self.as_usize() % rhs
891 }
892}
893
894impl ops::BitAnd for VAddr {
895 type Output = Self;
896
897 fn bitand(self, rhs: Self) -> Self::Output {
898 VAddr(self.0 & rhs.0)
899 }
900}
901
902impl ops::BitAnd<u32> for VAddr {
903 type Output = VAddr;
904
905 fn bitand(self, rhs: u32) -> Self::Output {
906 VAddr(self.0 & rhs)
907 }
908}
909
910impl ops::BitAnd<usize> for VAddr {
911 type Output = VAddr;
912
913 fn bitand(self, rhs: usize) -> Self::Output {
914 VAddr(self.0 & rhs as u32)
915 }
916}
917
918impl ops::BitAnd<i32> for VAddr {
919 type Output = VAddr;
920
921 fn bitand(self, rhs: i32) -> Self::Output {
922 VAddr(self.0 & rhs as u32)
923 }
924}
925
926impl ops::BitOr for VAddr {
927 type Output = VAddr;
928
929 fn bitor(self, rhs: VAddr) -> VAddr {
930 VAddr(self.0 | rhs.0)
931 }
932}
933
934impl ops::BitOr<u32> for VAddr {
935 type Output = VAddr;
936
937 fn bitor(self, rhs: u32) -> Self::Output {
938 VAddr(self.0 | rhs)
939 }
940}
941
942impl ops::BitOr<usize> for VAddr {
943 type Output = VAddr;
944
945 fn bitor(self, rhs: usize) -> Self::Output {
946 VAddr(self.0 | rhs as u32)
947 }
948}
949
950impl ops::Shr<u32> for VAddr {
951 type Output = u32;
952
953 fn shr(self, rhs: u32) -> Self::Output {
954 self.0 >> rhs as u32
955 }
956}
957
958impl ops::Shr<usize> for VAddr {
959 type Output = u32;
960
961 fn shr(self, rhs: usize) -> Self::Output {
962 self.0 >> rhs as u32
963 }
964}
965
966impl ops::Shr<i32> for VAddr {
967 type Output = u32;
968
969 fn shr(self, rhs: i32) -> Self::Output {
970 self.0 >> rhs as u32
971 }
972}
973
974impl fmt::Binary for VAddr {
975 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
976 self.0.fmt(f)
977 }
978}
979
980impl fmt::Display for VAddr {
981 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
982 write!(f, "{:#x}", self.0)
983 }
984}
985
986impl fmt::Debug for VAddr {
987 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
988 write!(f, "{:#x}", self.0)
989 }
990}
991
992impl fmt::LowerHex for VAddr {
993 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
994 self.0.fmt(f)
995 }
996}
997
998impl fmt::Octal for VAddr {
999 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1000 self.0.fmt(f)
1001 }
1002}
1003
1004impl fmt::UpperHex for VAddr {
1005 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1006 self.0.fmt(f)
1007 }
1008}
1009
1010impl fmt::Pointer for VAddr {
1011 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1012 use core::fmt::LowerHex;
1013 self.0.fmt(f)
1014 }
1015}
1016
1017#[allow(clippy::clippy::derive_hash_xor_eq)]
1018impl Hash for VAddr {
1019 fn hash<H: Hasher>(&self, state: &mut H) {
1020 self.0.hash(state);
1021 }
1022}
1023
1024pub const BASE_PAGE_SHIFT: usize = 12;
1026
1027pub const BASE_PAGE_SIZE: usize = 4096;
1029
1030pub const LARGE_PAGE_SIZE: usize = 1024 * 1024 * 4;
1032
1033pub const CACHE_LINE_SIZE: usize = 64;
1035
1036pub struct Page([u8; BASE_PAGE_SIZE]);
1038
1039pub struct LargePage([u8; LARGE_PAGE_SIZE]);
1041
1042const ADDRESS_MASK: u32 = !0xfff;
1044const ADDRESS_MASK_PSE: u32 = !0x3fffff;
1045
1046pub const PAGE_SIZE_ENTRIES: usize = 1024;
1048
1049pub type PD = [PDEntry; PAGE_SIZE_ENTRIES];
1051
1052pub type PT = [PTEntry; PAGE_SIZE_ENTRIES];
1054
1055#[inline]
1057pub fn pd_index(addr: VAddr) -> usize {
1058 ((addr >> 22usize) & 0b1111111111) as usize
1059}
1060
1061#[inline]
1063pub fn pt_index(addr: VAddr) -> usize {
1064 ((addr >> 12usize) & 0b1111111111) as usize
1065}
1066
1067bitflags! {
1068 #[repr(transparent)]
1070 pub struct PDFlags: u32 {
1071 const P = bit!(0);
1073 const RW = bit!(1);
1075 const US = bit!(2);
1077 const PWT = bit!(3);
1079 const PCD = bit!(4);
1081 const A = bit!(5);
1083 const D = bit!(6);
1085 const PS = bit!(7);
1087 const G = bit!(8);
1089 const PAT = bit!(12);
1092 }
1093}
1094
1095#[repr(transparent)]
1097#[derive(Clone, Copy)]
1098pub struct PDEntry(pub u32);
1099
1100impl fmt::Debug for PDEntry {
1101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1102 write!(f, "PDEntry {{ {:#x}, {:?} }}", self.address(), self.flags())
1103 }
1104}
1105
1106impl PDEntry {
1107 pub fn new(pt: PAddr, flags: PDFlags) -> PDEntry {
1118 let mask = if flags.contains(PDFlags::PS) {
1119 ADDRESS_MASK_PSE
1120 } else {
1121 ADDRESS_MASK
1122 };
1123 let pt_val = pt & mask;
1124 assert!(pt_val == pt.into());
1125 assert!(pt % BASE_PAGE_SIZE == 0);
1126 PDEntry(pt_val | flags.bits)
1127 }
1128
1129 pub fn address(self) -> PAddr {
1131 if self.flags().contains(PDFlags::PS) {
1132 PAddr::from(self.0 & ADDRESS_MASK_PSE)
1133 } else {
1134 PAddr::from(self.0 & ADDRESS_MASK)
1135 }
1136 }
1137
1138 pub fn flags(self) -> PDFlags {
1140 PDFlags::from_bits_truncate(self.0)
1141 }
1142
1143 check_flag!(
1144 doc = "Present; must be 1 to map a 4-MByte page.",
1145 is_present,
1146 PDFlags::P
1147 );
1148 check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 4-MByte page referenced by this entry.",
1149 is_writeable, PDFlags::RW);
1150 check_flag!(doc = "User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte page referenced by this entry.",
1151 is_user_mode_allowed, PDFlags::US);
1152 check_flag!(
1153 doc = "Page-level write-through.",
1154 is_page_write_through,
1155 PDFlags::PWT
1156 );
1157 check_flag!(
1158 doc = "Page-level cache disable.",
1159 is_page_level_cache_disabled,
1160 PDFlags::PCD
1161 );
1162 check_flag!(doc = "Accessed; indicates whether software has accessed the 4-MByte page referenced by this entry.",
1163 is_accessed, PDFlags::A);
1164 check_flag!(doc = "Dirty; indicates whether software has written to the 4-MByte page referenced by this entry.",
1165 is_dirty, PDFlags::D);
1166 check_flag!(doc = "Page size; if set this entry maps a 4-MByte page; otherwise, this entry references a page directory.",
1167 is_page, PDFlags::PS);
1168 check_flag!(doc = "Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise.",
1169 is_global, PDFlags::G);
1170 check_flag!(doc = "If the PAT is supported, indirectly determines the memory type used to access the 4-MByte page referenced by this entry; otherwise, reserved (must be 0)",
1171 is_pat, PDFlags::PAT);
1172}
1173
1174bitflags! {
1175 #[repr(transparent)]
1177 pub struct PTFlags: u32 {
1178 const P = bit!(0);
1180 const RW = bit!(1);
1182 const US = bit!(2);
1184 const PWT = bit!(3);
1186 const PCD = bit!(4);
1188 const A = bit!(5);
1190 const D = bit!(6);
1192 const PAT = bit!(7);
1195 const G = bit!(8);
1197 }
1198}
1199
1200#[repr(transparent)]
1202#[derive(Clone, Copy)]
1203pub struct PTEntry(pub u32);
1204
1205impl fmt::Debug for PTEntry {
1206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1207 write!(f, "PTEntry {{ {:#x}, {:?} }}", self.address(), self.flags())
1208 }
1209}
1210
1211impl PTEntry {
1212 pub fn new(page: PAddr, flags: PTFlags) -> PTEntry {
1219 let page_val = page & ADDRESS_MASK;
1220 assert!(page_val == page.into());
1221 assert!(page % BASE_PAGE_SIZE == 0);
1222 PTEntry(page_val | flags.bits)
1223 }
1224
1225 pub fn address(self) -> PAddr {
1227 PAddr::from(self.0 & ADDRESS_MASK)
1228 }
1229
1230 pub fn flags(self) -> PTFlags {
1232 PTFlags::from_bits_truncate(self.0)
1233 }
1234
1235 check_flag!(
1236 doc = "Present; must be 1 to map a 4-KByte page.",
1237 is_present,
1238 PTFlags::P
1239 );
1240 check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry.",
1241 is_writeable, PTFlags::RW);
1242 check_flag!(doc = "User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry.",
1243 is_user_mode_allowed, PTFlags::US);
1244 check_flag!(
1245 doc = "Page-level write-through.",
1246 is_page_write_through,
1247 PTFlags::PWT
1248 );
1249 check_flag!(
1250 doc = "Page-level cache disable.",
1251 is_page_level_cache_disabled,
1252 PTFlags::PCD
1253 );
1254 check_flag!(doc = "Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry.",
1255 is_accessed, PTFlags::A);
1256 check_flag!(doc = "Dirty; indicates whether software has written to the 4-KByte page referenced by this entry.",
1257 is_dirty, PTFlags::D);
1258 check_flag!(doc = "If the PAT is supported, indirectly determines the memory type used to access the 4-KByte page referenced by this entry; otherwise, reserved (must be 0)",
1259 is_pat, PTFlags::PAT);
1260 check_flag!(doc = "Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise.",
1261 is_global, PTFlags::G);
1262}
1263
1264#[cfg(all(test, feature = "utest"))]
1265mod test {
1266 use super::*;
1267
1268 #[test]
1269 fn paddr_align() {
1270 let base = PAddr::from(0x1000);
1271 assert_eq!(base.base_page_offset(), 0x0);
1272 assert_eq!(base.large_page_offset(), 0x1000);
1273 assert_eq!(base.align_down_to_base_page(), PAddr::from(0x1000));
1274 assert_eq!(base.align_down_to_large_page(), PAddr::from(0x0));
1275 assert_eq!(base.align_up_to_base_page(), PAddr::from(0x1000));
1276 assert_eq!(base.align_up_to_large_page(), PAddr::from(0x400000));
1277 assert!(base.is_base_page_aligned());
1278 assert!(!base.is_large_page_aligned());
1279 assert!(base.is_aligned(0x1u32));
1280 assert!(base.is_aligned(0x2u32));
1281 assert!(!base.is_aligned(0x3u32));
1282 assert!(base.is_aligned(0x4u32));
1283
1284 let base = PAddr::from(0x1001);
1285 assert_eq!(base.base_page_offset(), 0x1);
1286 assert_eq!(base.large_page_offset(), 0x1001);
1287 assert_eq!(base.align_down_to_base_page(), PAddr::from(0x1000));
1288 assert_eq!(base.align_down_to_large_page(), PAddr::from(0x0));
1289 assert_eq!(base.align_up_to_base_page(), PAddr::from(0x2000));
1290 assert_eq!(base.align_up_to_large_page(), PAddr::from(0x400000));
1291 assert!(!base.is_base_page_aligned());
1292 assert!(!base.is_large_page_aligned());
1293 assert!(base.is_aligned(0x1u32));
1294 assert!(!base.is_aligned(0x2u32));
1295 assert!(!base.is_aligned(0x3u32));
1296 assert!(!base.is_aligned(0x4u32));
1297
1298 let base = PAddr::from(0x400000);
1299 assert_eq!(base.base_page_offset(), 0x0);
1300 assert_eq!(base.large_page_offset(), 0x0);
1301 assert_eq!(base.align_down_to_base_page(), PAddr::from(0x400000));
1302 assert_eq!(base.align_down_to_large_page(), PAddr::from(0x400000));
1303 assert_eq!(base.align_up_to_base_page(), PAddr::from(0x400000));
1304 assert_eq!(base.align_up_to_large_page(), PAddr::from(0x400000));
1305 assert!(base.is_base_page_aligned());
1306 assert!(base.is_large_page_aligned());
1307 assert!(base.is_aligned(0x1u32));
1308 assert!(base.is_aligned(0x2u32));
1309 assert!(!base.is_aligned(0x3u32));
1310 assert!(base.is_aligned(0x4u32));
1311
1312 let base = PAddr::from(0x400002);
1313 assert_eq!(base.base_page_offset(), 0x2);
1314 assert_eq!(base.large_page_offset(), 0x2);
1315 assert_eq!(base.align_down_to_base_page(), PAddr::from(0x400000));
1316 assert_eq!(base.align_down_to_large_page(), PAddr::from(0x400000));
1317 assert_eq!(base.align_up_to_base_page(), PAddr::from(0x401000));
1318 assert_eq!(base.align_up_to_large_page(), PAddr::from(0x800000));
1319 assert!(!base.is_base_page_aligned());
1320 assert!(!base.is_large_page_aligned());
1321 assert!(base.is_aligned(0x1u32));
1322 assert!(base.is_aligned(0x2u32));
1323 assert!(!base.is_aligned(0x3u32));
1324 assert!(!base.is_aligned(0x4u32));
1325 }
1326
1327 #[test]
1328 fn ioaddr_align() {
1329 let base = IOAddr::from(0x1000);
1330 assert_eq!(base.base_page_offset(), 0x0);
1331 assert_eq!(base.large_page_offset(), 0x1000);
1332 assert_eq!(base.align_down_to_base_page(), IOAddr::from(0x1000));
1333 assert_eq!(base.align_down_to_large_page(), IOAddr::from(0x0));
1334 assert_eq!(base.align_up_to_base_page(), IOAddr::from(0x1000));
1335 assert_eq!(base.align_up_to_large_page(), IOAddr::from(0x400000));
1336 assert!(base.is_base_page_aligned());
1337 assert!(!base.is_large_page_aligned());
1338 assert!(base.is_aligned(0x1u32));
1339 assert!(base.is_aligned(0x2u32));
1340 assert!(!base.is_aligned(0x3u32));
1341 assert!(base.is_aligned(0x4u32));
1342
1343 let base = IOAddr::from(0x1001);
1344 assert_eq!(base.base_page_offset(), 0x1);
1345 assert_eq!(base.large_page_offset(), 0x1001);
1346 assert_eq!(base.align_down_to_base_page(), IOAddr::from(0x1000));
1347 assert_eq!(base.align_down_to_large_page(), IOAddr::from(0x0));
1348 assert_eq!(base.align_up_to_base_page(), IOAddr::from(0x2000));
1349 assert_eq!(base.align_up_to_large_page(), IOAddr::from(0x400000));
1350 assert!(!base.is_base_page_aligned());
1351 assert!(!base.is_large_page_aligned());
1352 assert!(base.is_aligned(0x1u32));
1353 assert!(!base.is_aligned(0x2u32));
1354 assert!(!base.is_aligned(0x3u32));
1355 assert!(!base.is_aligned(0x4u32));
1356
1357 let base = IOAddr::from(0x400000);
1358 assert_eq!(base.base_page_offset(), 0x0);
1359 assert_eq!(base.large_page_offset(), 0x0);
1360 assert_eq!(base.align_down_to_base_page(), IOAddr::from(0x400000));
1361 assert_eq!(base.align_down_to_large_page(), IOAddr::from(0x400000));
1362 assert_eq!(base.align_up_to_base_page(), IOAddr::from(0x400000));
1363 assert_eq!(base.align_up_to_large_page(), IOAddr::from(0x400000));
1364 assert!(base.is_base_page_aligned());
1365 assert!(base.is_large_page_aligned());
1366 assert!(base.is_aligned(0x1u32));
1367 assert!(base.is_aligned(0x2u32));
1368 assert!(!base.is_aligned(0x3u32));
1369 assert!(base.is_aligned(0x4u32));
1370
1371 let base = IOAddr::from(0x400002);
1372 assert_eq!(base.base_page_offset(), 0x2);
1373 assert_eq!(base.large_page_offset(), 0x2);
1374 assert_eq!(base.align_down_to_base_page(), IOAddr::from(0x400000));
1375 assert_eq!(base.align_down_to_large_page(), IOAddr::from(0x400000));
1376 assert_eq!(base.align_up_to_base_page(), IOAddr::from(0x401000));
1377 assert_eq!(base.align_up_to_large_page(), IOAddr::from(0x800000));
1378 assert!(!base.is_base_page_aligned());
1379 assert!(!base.is_large_page_aligned());
1380 assert!(base.is_aligned(0x1u32));
1381 assert!(base.is_aligned(0x2u32));
1382 assert!(!base.is_aligned(0x3u32));
1383 assert!(!base.is_aligned(0x4u32));
1384 }
1385
1386 #[test]
1387 fn vaddr_align() {
1388 let base = VAddr::from(0x1000);
1389 assert_eq!(base.base_page_offset(), 0x0);
1390 assert_eq!(base.large_page_offset(), 0x1000);
1391 assert_eq!(base.align_down_to_base_page(), VAddr::from(0x1000));
1392 assert_eq!(base.align_down_to_large_page(), VAddr::from(0x0));
1393 assert_eq!(base.align_up_to_base_page(), VAddr::from(0x1000));
1394 assert_eq!(base.align_up_to_large_page(), VAddr::from(0x400000));
1395 assert!(base.is_base_page_aligned());
1396 assert!(!base.is_large_page_aligned());
1397 assert!(base.is_aligned(0x1u32));
1398 assert!(base.is_aligned(0x2u32));
1399 assert!(!base.is_aligned(0x3u32));
1400 assert!(base.is_aligned(0x4u32));
1401
1402 let base = VAddr::from(0x1001);
1403 assert_eq!(base.base_page_offset(), 0x1);
1404 assert_eq!(base.large_page_offset(), 0x1001);
1405 assert_eq!(base.align_down_to_base_page(), VAddr::from(0x1000));
1406 assert_eq!(base.align_down_to_large_page(), VAddr::from(0x0));
1407 assert_eq!(base.align_up_to_base_page(), VAddr::from(0x2000));
1408 assert_eq!(base.align_up_to_large_page(), VAddr::from(0x400000));
1409 assert!(!base.is_base_page_aligned());
1410 assert!(!base.is_large_page_aligned());
1411 assert!(base.is_aligned(0x1u32));
1412 assert!(!base.is_aligned(0x2u32));
1413 assert!(!base.is_aligned(0x3u32));
1414 assert!(!base.is_aligned(0x4u32));
1415
1416 let base = VAddr::from(0x400000);
1417 assert_eq!(base.base_page_offset(), 0x0);
1418 assert_eq!(base.large_page_offset(), 0x0);
1419 assert_eq!(base.align_down_to_base_page(), VAddr::from(0x400000));
1420 assert_eq!(base.align_down_to_large_page(), VAddr::from(0x400000));
1421 assert_eq!(base.align_up_to_base_page(), VAddr::from(0x400000));
1422 assert_eq!(base.align_up_to_large_page(), VAddr::from(0x400000));
1423 assert!(base.is_base_page_aligned());
1424 assert!(base.is_large_page_aligned());
1425 assert!(base.is_aligned(0x1u32));
1426 assert!(base.is_aligned(0x2u32));
1427 assert!(!base.is_aligned(0x3u32));
1428 assert!(base.is_aligned(0x4u32));
1429
1430 let base = VAddr::from(0x400002);
1431 assert_eq!(base.base_page_offset(), 0x2);
1432 assert_eq!(base.large_page_offset(), 0x2);
1433 assert_eq!(base.align_down_to_base_page(), VAddr::from(0x400000));
1434 assert_eq!(base.align_down_to_large_page(), VAddr::from(0x400000));
1435 assert_eq!(base.align_up_to_base_page(), VAddr::from(0x401000));
1436 assert_eq!(base.align_up_to_large_page(), VAddr::from(0x800000));
1437 assert!(!base.is_base_page_aligned());
1438 assert!(!base.is_large_page_aligned());
1439 assert!(base.is_aligned(0x1u32));
1440 assert!(base.is_aligned(0x2u32));
1441 assert!(!base.is_aligned(0x3u32));
1442 assert!(!base.is_aligned(0x4u32));
1443 }
1444}