11use std:: {
22 alloc:: { self , Layout } ,
33 cell:: RefCell ,
4- collections:: HashSet ,
4+ collections:: { HashMap , HashSet } ,
55 marker:: PhantomData ,
66} ;
77
@@ -10,10 +10,23 @@ use page_table_entry::{GenericPTE, MappingFlags};
1010use page_table_multiarch:: { PageSize , PageTable64 , PagingHandler , PagingMetaData , PagingResult } ;
1111use rand:: { Rng , SeedableRng , rngs:: SmallRng } ;
1212
13- const PAGE_LAYOUT : Layout = unsafe { Layout :: from_size_align_unchecked ( 4096 , 4096 ) } ;
13+ /// Creates a layout for allocating `num` pages with alignment of `2^align_pow2`
14+ /// pages.
15+ const fn pages_layout ( num : usize , align : usize ) -> Layout {
16+ if !align. is_power_of_two ( ) {
17+ panic ! ( "alignment must be a power of two" ) ;
18+ }
19+ if align % 4096 != 0 {
20+ panic ! ( "alignment must be a multiple of 4K" ) ;
21+ }
22+ unsafe { Layout :: from_size_align_unchecked ( 4096 * num, align) }
23+ }
24+
25+ const PAGE_LAYOUT : Layout = pages_layout ( 1 , 4096 ) ;
1426
1527thread_local ! {
1628 static ALLOCATED : RefCell <HashSet <usize >> = RefCell :: default ( ) ;
29+ static ALIGN : RefCell <HashMap <usize , usize >> = RefCell :: default ( ) ;
1730}
1831
1932struct TrackPagingHandler < M : PagingMetaData > ( PhantomData < M > ) ;
@@ -29,6 +42,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
2942 Some ( PhysAddr :: from_usize ( ptr) )
3043 }
3144
45+ fn alloc_frames ( num : usize , align : usize ) -> Option < PhysAddr > {
46+ let layout = pages_layout ( num, align) ;
47+ let ptr = unsafe { alloc:: alloc ( layout) } as usize ;
48+ assert ! (
49+ ptr <= M :: PA_MAX_ADDR ,
50+ "allocated frame address exceeds PA_MAX_ADDR"
51+ ) ;
52+ ALLOCATED . with_borrow_mut ( |it| {
53+ for i in 0 ..num {
54+ it. insert ( ptr + i * 4096 ) ;
55+ }
56+ } ) ;
57+ ALIGN . with_borrow_mut ( |it| {
58+ it. insert ( ptr, align) ;
59+ } ) ;
60+ Some ( PhysAddr :: from_usize ( ptr) )
61+ }
62+
3263 fn dealloc_frame ( paddr : PhysAddr ) {
3364 let ptr = paddr. as_usize ( ) ;
3465 ALLOCATED . with_borrow_mut ( |it| {
@@ -39,6 +70,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
3970 }
4071 }
4172
73+ fn dealloc_frames ( paddr : PhysAddr , num : usize ) {
74+ let ptr = paddr. as_usize ( ) ;
75+ ALLOCATED . with_borrow_mut ( |it| {
76+ for i in 0 ..num {
77+ let addr = ptr + i * 4096 ;
78+ assert ! ( it. remove( & addr) , "dealloc a frame that was not allocated" ) ;
79+ }
80+ } ) ;
81+ let align = ALIGN . with_borrow_mut ( |it| {
82+ it. remove ( & ptr)
83+ . expect ( "dealloc frames that were not allocated" )
84+ } ) ;
85+ let layout = pages_layout ( num, align) ;
86+ unsafe {
87+ alloc:: dealloc ( ptr as _ , layout) ;
88+ }
89+ }
90+
4291 fn phys_to_virt ( paddr : PhysAddr ) -> VirtAddr {
4392 assert ! ( paddr. as_usize( ) > 0 ) ;
4493 VirtAddr :: from_usize ( paddr. as_usize ( ) )
0 commit comments