@@ -27,6 +27,7 @@ const fn p1_index(vaddr: usize) -> usize {
2727/// When the [`PageTable64`] itself is dropped.
2828pub struct PageTable64 < M : PagingMetaData , PTE : GenericPTE , H : PagingHandler > {
2929 root_paddr : PhysAddr ,
30+ borrowed_entries : bitmaps:: Bitmap < ENTRY_COUNT > ,
3031 _phantom : PhantomData < ( M , PTE , H ) > ,
3132}
3233
@@ -38,13 +39,15 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
3839 let root_paddr = Self :: alloc_table ( ) ?;
3940 Ok ( Self {
4041 root_paddr,
42+ borrowed_entries : bitmaps:: Bitmap :: new ( ) ,
4143 _phantom : PhantomData ,
4244 } )
4345 }
4446
4547 pub fn from_paddr ( root_paddr : PhysAddr ) -> Self {
4648 Self {
4749 root_paddr,
50+ borrowed_entries : bitmaps:: Bitmap :: new ( ) ,
4851 _phantom : PhantomData ,
4952 }
5053 }
@@ -349,7 +352,14 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
349352 let end_idx = index_fn ( start. into ( ) + size - 1 ) + 1 ;
350353 assert ! ( start_idx < ENTRY_COUNT ) ;
351354 assert ! ( end_idx <= ENTRY_COUNT ) ;
352- dst_table[ start_idx..end_idx] . copy_from_slice ( & src_table[ start_idx..end_idx] ) ;
355+ // dst_table[start_idx..end_idx].copy_from_slice(&src_table[start_idx..end_idx]);
356+ for i in start_idx..end_idx {
357+ let entry = & mut dst_table[ i] ;
358+ if !self . borrowed_entries . set ( i, true ) && self . next_table ( entry) . is_ok ( ) {
359+ self . dealloc_tree ( entry. paddr ( ) , 1 ) ;
360+ }
361+ * entry = src_table[ i] ;
362+ }
353363 }
354364}
355365
@@ -527,22 +537,44 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
527537 }
528538 Ok ( ( ) )
529539 }
540+
541+ fn dealloc_tree ( & self , table_paddr : PhysAddr , level : usize ) {
542+ // don't free the entries in last level, they are not array.
543+ if level < M :: LEVELS - 1 {
544+ for entry in self . table_of ( table_paddr) {
545+ if self . next_table ( entry) . is_ok ( ) {
546+ self . dealloc_tree ( entry. paddr ( ) , level + 1 ) ;
547+ }
548+ }
549+ }
550+ H :: dealloc_frame ( table_paddr) ;
551+ }
530552}
531553
532554impl < M : PagingMetaData , PTE : GenericPTE , H : PagingHandler > Drop for PageTable64 < M , PTE , H > {
533555 fn drop ( & mut self ) {
534556 warn ! ( "Dropping page table @ {:#x}" , self . root_paddr( ) ) ;
535557
536- // don't free the entries in last level, they are not array.
537- let _ = self . walk (
538- usize:: MAX ,
539- None ,
540- Some ( & |level, _index, _vaddr, entry : & PTE | {
541- if level < M :: LEVELS - 1 && entry. is_present ( ) && !entry. is_huge ( ) {
542- H :: dealloc_frame ( entry. paddr ( ) ) ;
543- }
544- } ) ,
545- ) ;
558+ // // don't free the entries in last level, they are not array.
559+ // let _ = self.walk(
560+ // usize::MAX,
561+ // None,
562+ // Some(&|level, _index, _vaddr, entry: &PTE| {
563+ // if level < M::LEVELS - 1 && entry.is_present() && !entry.is_huge() {
564+ // H::dealloc_frame(entry.paddr());
565+ // }
566+ // }),
567+ // );
568+ let root = self . table_of ( self . root_paddr ) ;
569+ #[ allow( unused_variables) ]
570+ for ( i, entry) in root. iter ( ) . enumerate ( ) {
571+ if self . borrowed_entries . get ( i) {
572+ continue ;
573+ }
574+ if self . next_table ( entry) . is_ok ( ) {
575+ self . dealloc_tree ( entry. paddr ( ) , 1 ) ;
576+ }
577+ }
546578 H :: dealloc_frame ( self . root_paddr ( ) ) ;
547579 }
548580}
0 commit comments