@@ -573,6 +573,7 @@ impl Pagetables {
573573 return ;
574574 }
575575
576+ let mut needs_flush = false ;
576577 let _guard = self . update_lock . read ( ) ;
577578 let pml4 = self . activate ( ) ;
578579 for p4_index in start. p4_index ( ) ..=end. p4_index ( ) {
@@ -652,15 +653,15 @@ impl Pagetables {
652653
653654 for p1_index in start. p1_index ( ) ..=end. p1_index ( ) {
654655 let pte = & pt[ p1_index] ;
655- unsafe {
656- pte. try_unmap ( ) ;
657- }
656+ needs_flush |= unsafe { pte. try_unmap ( ) } ;
658657 }
659658 }
660659 }
661660 }
662661
663- pml4. flush_pages ( start..=end) ;
662+ if needs_flush {
663+ pml4. flush_pages ( start..=end) ;
664+ }
664665 }
665666
666667 /// Try to copy user memory from `src` into `dest`.
@@ -1266,12 +1267,18 @@ impl ActivePageTableEntry<Level1> {
12661267 }
12671268
12681269 /// Unmap a page if it's mapped or do nothing if it isn't.
1269- pub unsafe fn try_unmap ( & self ) {
1270+ ///
1271+ /// Returns true if there previously was an entry and that entry had been
1272+ /// accessed.
1273+ pub unsafe fn try_unmap ( & self ) -> bool {
12701274 let old_entry = atomic_swap ( & self . entry , 0 ) ;
1271- if PresentPageTableEntry :: try_from ( old_entry) . is_ok ( ) {
1275+ if let Ok ( entry ) = PresentPageTableEntry :: try_from ( old_entry) {
12721276 unsafe {
12731277 self . parent_table_entry ( ) . release_reference_count_fast ( ) ;
12741278 }
1279+ entry. accessed ( )
1280+ } else {
1281+ false
12751282 }
12761283 }
12771284
@@ -1415,6 +1422,7 @@ impl Clear for ActivePageTableEntry<Level1> {
14151422const PRESENT_BIT : usize = 0 ;
14161423const WRITE_BIT : usize = 1 ;
14171424const USER_BIT : usize = 2 ;
1425+ const ACCESSED_BIT : usize = 5 ;
14181426const DIRTY_BIT : usize = 6 ;
14191427const GLOBAL_BIT : usize = 8 ;
14201428const DISABLE_EXECUTE_BIT : usize = 63 ;
@@ -1442,7 +1450,8 @@ bitflags! {
14421450 const USER = 1 << 2 ;
14431451 const GLOBAL = 1 << 3 ;
14441452 const COW = 1 << 4 ;
1445- const DIRTY = 1 << 5 ;
1453+ const ACCESSED = 1 << 5 ;
1454+ const DIRTY = 1 << 6 ;
14461455 }
14471456}
14481457
@@ -1466,6 +1475,8 @@ impl PresentPageTableEntry {
14661475 ) ;
14671476 let cow = flags. contains ( PageTableFlags :: COW ) ;
14681477 entry. set_bit ( COW_BIT , cow) ;
1478+ let accessed = flags. contains ( PageTableFlags :: ACCESSED ) ;
1479+ entry. set_bit ( ACCESSED_BIT , accessed) ;
14691480 let dirty = flags. contains ( PageTableFlags :: DIRTY ) ;
14701481 entry. set_bit ( DIRTY_BIT , dirty) ;
14711482
@@ -1487,6 +1498,7 @@ impl PresentPageTableEntry {
14871498 flags. set ( PageTableFlags :: GLOBAL , self . global ( ) ) ;
14881499 flags. set ( PageTableFlags :: EXECUTABLE , self . executable ( ) ) ;
14891500 flags. set ( PageTableFlags :: COW , self . cow ( ) ) ;
1501+ flags. set ( PageTableFlags :: ACCESSED , self . accessed ( ) ) ;
14901502 flags. set ( PageTableFlags :: DIRTY , self . dirty ( ) ) ;
14911503 flags
14921504 }
@@ -1511,6 +1523,10 @@ impl PresentPageTableEntry {
15111523 self . 0 . get ( ) . get_bit ( COW_BIT )
15121524 }
15131525
1526+ pub fn accessed ( & self ) -> bool {
1527+ self . 0 . get ( ) . get_bit ( ACCESSED_BIT )
1528+ }
1529+
15141530 pub fn dirty ( & self ) -> bool {
15151531 self . 0 . get ( ) . get_bit ( DIRTY_BIT )
15161532 }
0 commit comments