@@ -169,7 +169,7 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size1GiB> for MappedPageTable<'a, P> {
169
169
fn unmap (
170
170
& mut self ,
171
171
page : Page < Size1GiB > ,
172
- ) -> Result < ( PhysFrame < Size1GiB > , MapperFlush < Size1GiB > ) , UnmapError > {
172
+ ) -> Result < ( PhysFrame < Size1GiB > , PageTableFlags , MapperFlush < Size1GiB > ) , UnmapError > {
173
173
let p4 = & mut self . level_4_table ;
174
174
let p3 = self
175
175
. page_table_walker
@@ -189,7 +189,39 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size1GiB> for MappedPageTable<'a, P> {
189
189
. map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p3_entry. addr ( ) ) ) ?;
190
190
191
191
p3_entry. set_unused ( ) ;
192
- Ok ( ( frame, MapperFlush :: new ( page) ) )
192
+ Ok ( ( frame, flags, MapperFlush :: new ( page) ) )
193
+ }
194
+
195
+ fn clear ( & mut self , page : Page < Size1GiB > ) -> Result < UnmappedFrame < Size1GiB > , UnmapError > {
196
+ let p4 = & mut self . level_4_table ;
197
+ let p3 = self
198
+ . page_table_walker
199
+ . next_table_mut ( & mut p4[ page. p4_index ( ) ] ) ?;
200
+
201
+ let p3_entry = & mut p3[ page. p3_index ( ) ] ;
202
+ let flags = p3_entry. flags ( ) ;
203
+
204
+ if !flags. contains ( PageTableFlags :: HUGE_PAGE ) {
205
+ return Err ( UnmapError :: ParentEntryHugePage ) ;
206
+ }
207
+
208
+ if !flags. contains ( PageTableFlags :: PRESENT ) {
209
+ let cloned = p3_entry. clone ( ) ;
210
+ p3_entry. set_unused ( ) ;
211
+ return Ok ( UnmappedFrame :: NotPresent { entry : cloned } ) ;
212
+ }
213
+
214
+ let frame = PhysFrame :: from_start_address ( p3_entry. addr ( ) )
215
+ . map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p3_entry. addr ( ) ) ) ?;
216
+ let flags = p3_entry. flags ( ) ;
217
+
218
+ p3_entry. set_unused ( ) ;
219
+
220
+ Ok ( UnmappedFrame :: Present {
221
+ frame,
222
+ flags,
223
+ flush : MapperFlush :: new ( page) ,
224
+ } )
193
225
}
194
226
195
227
unsafe fn update_flags (
@@ -277,7 +309,7 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size2MiB> for MappedPageTable<'a, P> {
277
309
fn unmap (
278
310
& mut self ,
279
311
page : Page < Size2MiB > ,
280
- ) -> Result < ( PhysFrame < Size2MiB > , MapperFlush < Size2MiB > ) , UnmapError > {
312
+ ) -> Result < ( PhysFrame < Size2MiB > , PageTableFlags , MapperFlush < Size2MiB > ) , UnmapError > {
281
313
let p4 = & mut self . level_4_table ;
282
314
let p3 = self
283
315
. page_table_walker
@@ -300,7 +332,40 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size2MiB> for MappedPageTable<'a, P> {
300
332
. map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p2_entry. addr ( ) ) ) ?;
301
333
302
334
p2_entry. set_unused ( ) ;
303
- Ok ( ( frame, MapperFlush :: new ( page) ) )
335
+ Ok ( ( frame, flags, MapperFlush :: new ( page) ) )
336
+ }
337
+
338
+ fn clear ( & mut self , page : Page < Size2MiB > ) -> Result < UnmappedFrame < Size2MiB > , UnmapError > {
339
+ let p4 = & mut self . level_4_table ;
340
+ let p3 = self
341
+ . page_table_walker
342
+ . next_table_mut ( & mut p4[ page. p4_index ( ) ] ) ?;
343
+ let p2 = self
344
+ . page_table_walker
345
+ . next_table_mut ( & mut p3[ page. p3_index ( ) ] ) ?;
346
+
347
+ let p2_entry = & mut p2[ page. p2_index ( ) ] ;
348
+ let flags = p2_entry. flags ( ) ;
349
+
350
+ if !flags. contains ( PageTableFlags :: HUGE_PAGE ) {
351
+ return Err ( UnmapError :: ParentEntryHugePage ) ;
352
+ }
353
+
354
+ if !flags. contains ( PageTableFlags :: PRESENT ) {
355
+ let cloned = p2_entry. clone ( ) ;
356
+ p2_entry. set_unused ( ) ;
357
+ return Ok ( UnmappedFrame :: NotPresent { entry : cloned } ) ;
358
+ }
359
+ let frame = PhysFrame :: from_start_address ( p2_entry. addr ( ) )
360
+ . map_err ( |AddressNotAligned | UnmapError :: InvalidFrameAddress ( p2_entry. addr ( ) ) ) ?;
361
+ let flags = p2_entry. flags ( ) ;
362
+
363
+ p2_entry. set_unused ( ) ;
364
+ Ok ( UnmappedFrame :: Present {
365
+ frame,
366
+ flags,
367
+ flush : MapperFlush :: new ( page) ,
368
+ } )
304
369
}
305
370
306
371
unsafe fn update_flags (
@@ -405,7 +470,7 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size4KiB> for MappedPageTable<'a, P> {
405
470
fn unmap (
406
471
& mut self ,
407
472
page : Page < Size4KiB > ,
408
- ) -> Result < ( PhysFrame < Size4KiB > , MapperFlush < Size4KiB > ) , UnmapError > {
473
+ ) -> Result < ( PhysFrame < Size4KiB > , PageTableFlags , MapperFlush < Size4KiB > ) , UnmapError > {
409
474
let p4 = & mut self . level_4_table ;
410
475
let p3 = self
411
476
. page_table_walker
@@ -423,9 +488,43 @@ impl<'a, P: PageTableFrameMapping> Mapper<Size4KiB> for MappedPageTable<'a, P> {
423
488
FrameError :: FrameNotPresent => UnmapError :: PageNotMapped ,
424
489
FrameError :: HugeFrame => UnmapError :: ParentEntryHugePage ,
425
490
} ) ?;
491
+ let flags = p1_entry. flags ( ) ;
492
+
493
+ p1_entry. set_unused ( ) ;
494
+ Ok ( ( frame, flags, MapperFlush :: new ( page) ) )
495
+ }
496
+
497
+ fn clear ( & mut self , page : Page < Size4KiB > ) -> Result < UnmappedFrame < Size4KiB > , UnmapError > {
498
+ let p4 = & mut self . level_4_table ;
499
+ let p3 = self
500
+ . page_table_walker
501
+ . next_table_mut ( & mut p4[ page. p4_index ( ) ] ) ?;
502
+ let p2 = self
503
+ . page_table_walker
504
+ . next_table_mut ( & mut p3[ page. p3_index ( ) ] ) ?;
505
+ let p1 = self
506
+ . page_table_walker
507
+ . next_table_mut ( & mut p2[ page. p2_index ( ) ] ) ?;
508
+
509
+ let p1_entry = & mut p1[ page. p1_index ( ) ] ;
510
+
511
+ let frame = match p1_entry. frame ( ) {
512
+ Ok ( frame) => frame,
513
+ Err ( FrameError :: HugeFrame ) => return Err ( UnmapError :: ParentEntryHugePage ) ,
514
+ Err ( FrameError :: FrameNotPresent ) => {
515
+ let cloned = p1_entry. clone ( ) ;
516
+ p1_entry. set_unused ( ) ;
517
+ return Ok ( UnmappedFrame :: NotPresent { entry : cloned } ) ;
518
+ }
519
+ } ;
520
+ let flags = p1_entry. flags ( ) ;
426
521
427
522
p1_entry. set_unused ( ) ;
428
- Ok ( ( frame, MapperFlush :: new ( page) ) )
523
+ Ok ( UnmappedFrame :: Present {
524
+ frame,
525
+ flags,
526
+ flush : MapperFlush :: new ( page) ,
527
+ } )
429
528
}
430
529
431
530
unsafe fn update_flags (
0 commit comments