1
1
//! Access the page tables through a recursively mapped level 4 table.
2
2
3
+ use core:: fmt;
4
+
3
5
use super :: * ;
4
6
use crate :: registers:: control:: Cr3 ;
5
7
use crate :: structures:: paging:: PageTableIndex ;
6
8
use crate :: structures:: paging:: {
7
9
frame_alloc:: FrameAllocator ,
8
- page:: NotGiantPageSize ,
10
+ page:: { AddressNotAligned , NotGiantPageSize } ,
9
11
page_table:: { FrameError , PageTable , PageTableEntry , PageTableFlags } ,
10
12
Page , PageSize , PhysFrame , Size1GiB , Size2MiB , Size4KiB ,
11
13
} ;
@@ -46,18 +48,18 @@ impl<'a> RecursivePageTable<'a> {
46
48
///
47
49
/// Otherwise `Err(())` is returned.
48
50
#[ inline]
49
- pub fn new ( table : & ' a mut PageTable ) -> Result < Self , ( ) > {
51
+ pub fn new ( table : & ' a mut PageTable ) -> Result < Self , InvalidPageTable > {
50
52
let page = Page :: containing_address ( VirtAddr :: new ( table as * const _ as u64 ) ) ;
51
53
let recursive_index = page. p4_index ( ) ;
52
54
53
55
if page. p3_index ( ) != recursive_index
54
56
|| page. p2_index ( ) != recursive_index
55
57
|| page. p1_index ( ) != recursive_index
56
58
{
57
- return Err ( ( ) ) ;
59
+ return Err ( InvalidPageTable :: NotRecursive ) ;
58
60
}
59
61
if Ok ( Cr3 :: read ( ) . 0 ) != table[ recursive_index] . frame ( ) {
60
- return Err ( ( ) ) ;
62
+ return Err ( InvalidPageTable :: NotActive ) ;
61
63
}
62
64
63
65
Ok ( RecursivePageTable {
@@ -326,7 +328,7 @@ impl<'a> Mapper<Size1GiB> for RecursivePageTable<'a> {
326
328
}
327
329
328
330
let frame = PhysFrame :: from_start_address ( p3_entry. addr ( ) )
329
- . map_err ( |( ) | UnmapError :: InvalidFrameAddress ( p3_entry. addr ( ) ) ) ?;
331
+ . map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p3_entry. addr ( ) ) ) ?;
330
332
331
333
p3_entry. set_unused ( ) ;
332
334
Ok ( ( frame, MapperFlush :: new ( page) ) )
@@ -404,7 +406,7 @@ impl<'a> Mapper<Size1GiB> for RecursivePageTable<'a> {
404
406
}
405
407
406
408
PhysFrame :: from_start_address ( p3_entry. addr ( ) )
407
- . map_err ( |( ) | TranslateError :: InvalidFrameAddress ( p3_entry. addr ( ) ) )
409
+ . map_err ( |AddressNotAligned | TranslateError :: InvalidFrameAddress ( p3_entry. addr ( ) ) )
408
410
}
409
411
}
410
412
@@ -454,7 +456,7 @@ impl<'a> Mapper<Size2MiB> for RecursivePageTable<'a> {
454
456
}
455
457
456
458
let frame = PhysFrame :: from_start_address ( p2_entry. addr ( ) )
457
- . map_err ( |( ) | UnmapError :: InvalidFrameAddress ( p2_entry. addr ( ) ) ) ?;
459
+ . map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p2_entry. addr ( ) ) ) ?;
458
460
459
461
p2_entry. set_unused ( ) ;
460
462
Ok ( ( frame, MapperFlush :: new ( page) ) )
@@ -561,7 +563,7 @@ impl<'a> Mapper<Size2MiB> for RecursivePageTable<'a> {
561
563
}
562
564
563
565
PhysFrame :: from_start_address ( p2_entry. addr ( ) )
564
- . map_err ( |( ) | TranslateError :: InvalidFrameAddress ( p2_entry. addr ( ) ) )
566
+ . map_err ( |AddressNotAligned | TranslateError :: InvalidFrameAddress ( p2_entry. addr ( ) ) )
565
567
}
566
568
}
567
569
@@ -752,7 +754,7 @@ impl<'a> Mapper<Size4KiB> for RecursivePageTable<'a> {
752
754
}
753
755
754
756
PhysFrame :: from_start_address ( p1_entry. addr ( ) )
755
- . map_err ( |( ) | TranslateError :: InvalidFrameAddress ( p1_entry. addr ( ) ) )
757
+ . map_err ( |AddressNotAligned | TranslateError :: InvalidFrameAddress ( p1_entry. addr ( ) ) )
756
758
}
757
759
}
758
760
@@ -815,7 +817,7 @@ impl<'a> MapperAllSizes for RecursivePageTable<'a> {
815
817
816
818
let frame = match PhysFrame :: from_start_address ( p1_entry. addr ( ) ) {
817
819
Ok ( frame) => frame,
818
- Err ( ( ) ) => return TranslateResult :: InvalidFrameAddress ( p1_entry. addr ( ) ) ,
820
+ Err ( AddressNotAligned ) => return TranslateResult :: InvalidFrameAddress ( p1_entry. addr ( ) ) ,
819
821
} ;
820
822
let offset = u64:: from ( addr. page_offset ( ) ) ;
821
823
let flags = p1_entry. flags ( ) ;
@@ -827,6 +829,33 @@ impl<'a> MapperAllSizes for RecursivePageTable<'a> {
827
829
}
828
830
}
829
831
832
+ /// The given page table was not suitable to create a `RecursivePageTable`.
833
+ #[ derive( Debug ) ]
834
+ pub enum InvalidPageTable {
835
+ /// The given page table was not at an recursive address.
836
+ ///
837
+ /// The page table address must be of the form `0o_xxx_xxx_xxx_xxx_0000` where `xxx`
838
+ /// is the recursive entry.
839
+ NotRecursive ,
840
+ /// The given page table was not active on the CPU.
841
+ ///
842
+ /// The recursive page table design requires that the given level 4 table is active
843
+ /// on the CPU because otherwise it's not possible to access the other page tables
844
+ /// through recursive memory addresses.
845
+ NotActive ,
846
+ }
847
+
848
+ impl fmt:: Display for InvalidPageTable {
849
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
850
+ match self {
851
+ InvalidPageTable :: NotRecursive => {
852
+ write ! ( f, "given page table address is not recursive" )
853
+ }
854
+ InvalidPageTable :: NotActive => write ! ( f, "given page table is not active on the CPU" ) ,
855
+ }
856
+ }
857
+ }
858
+
830
859
#[ inline]
831
860
fn p3_ptr < S : PageSize > ( page : Page < S > , recursive_index : PageTableIndex ) -> * mut PageTable {
832
861
p3_page ( page, recursive_index) . start_address ( ) . as_mut_ptr ( )
0 commit comments