11use std:: {
22 alloc:: { self , Layout } ,
33 cell:: RefCell ,
4- collections:: HashSet ,
4+ collections:: { HashMap , HashSet } ,
55 marker:: PhantomData ,
6+ mem,
67} ;
78
89use memory_addr:: { PhysAddr , VirtAddr } ;
910use page_table_entry:: { GenericPTE , MappingFlags } ;
1011use page_table_multiarch:: { PageSize , PageTable64 , PagingHandler , PagingMetaData , PagingResult } ;
1112use rand:: { Rng , SeedableRng , rngs:: SmallRng } ;
1213
13- const PAGE_LAYOUT : Layout = unsafe { Layout :: from_size_align_unchecked ( 4096 , 4096 ) } ;
14+ /// Creates a layout for allocating `num` pages with alignment of `2^align_pow2`
15+ /// pages.
16+ const fn pages_layout ( num : usize , align_pow2 : usize ) -> Layout {
17+ unsafe { Layout :: from_size_align_unchecked ( 4096 * num, 4096 * ( 1 << align_pow2) ) }
18+ }
19+
20+ const PAGE_LAYOUT : Layout = pages_layout ( 1 , 0 ) ;
1421
1522thread_local ! {
1623 static ALLOCATED : RefCell <HashSet <usize >> = RefCell :: default ( ) ;
24+ static ALIGN_POW2 : RefCell <HashMap <usize , usize >> = RefCell :: default ( ) ;
1725}
1826
1927struct TrackPagingHandler < M : PagingMetaData > ( PhantomData < M > ) ;
@@ -29,6 +37,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
2937 Some ( PhysAddr :: from_usize ( ptr) )
3038 }
3139
40+ fn alloc_frames ( num : usize , align_pow2 : usize ) -> Option < PhysAddr > {
41+ let layout = pages_layout ( num, align_pow2) ;
42+ let ptr = unsafe { alloc:: alloc ( layout) } as usize ;
43+ assert ! (
44+ ptr <= M :: PA_MAX_ADDR ,
45+ "allocated frame address exceeds PA_MAX_ADDR"
46+ ) ;
47+ ALLOCATED . with_borrow_mut ( |it| {
48+ for i in 0 ..num {
49+ it. insert ( ptr + i * 4096 ) ;
50+ }
51+ } ) ;
52+ ALIGN_POW2 . with_borrow_mut ( |it| {
53+ it. insert ( ptr, align_pow2) ;
54+ } ) ;
55+ Some ( PhysAddr :: from_usize ( ptr) )
56+ }
57+
3258 fn dealloc_frame ( paddr : PhysAddr ) {
3359 let ptr = paddr. as_usize ( ) ;
3460 ALLOCATED . with_borrow_mut ( |it| {
@@ -39,6 +65,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
3965 }
4066 }
4167
68+ fn dealloc_frames ( paddr : PhysAddr , num : usize ) {
69+ let ptr = paddr. as_usize ( ) ;
70+ ALLOCATED . with_borrow_mut ( |it| {
71+ for i in 0 ..num {
72+ let addr = ptr + i * 4096 ;
73+ assert ! ( it. remove( & addr) , "dealloc a frame that was not allocated" ) ;
74+ }
75+ } ) ;
76+ let align_pow2 = ALIGN_POW2 . with_borrow_mut ( |it| {
77+ it. remove ( & ptr)
78+ . expect ( "dealloc frames that were not allocated" )
79+ } ) ;
80+ let layout = pages_layout ( num, align_pow2) ;
81+ unsafe {
82+ alloc:: dealloc ( ptr as _ , layout) ;
83+ }
84+ }
85+
4286 fn phys_to_virt ( paddr : PhysAddr ) -> VirtAddr {
4387 assert ! ( paddr. as_usize( ) > 0 ) ;
4488 VirtAddr :: from_usize ( paddr. as_usize ( ) )
0 commit comments