11use core:: fmt:: Debug ;
22use core:: ptr;
3-
43use free_list:: PageLayout ;
54use x86_64:: registers:: control:: { Cr0 , Cr0Flags , Cr2 , Cr3 } ;
65#[ cfg( feature = "common-os" ) ]
@@ -11,9 +10,7 @@ pub use x86_64::structures::paging::PageTableFlags as PageTableEntryFlags;
1110use x86_64:: structures:: paging:: frame:: PhysFrameRange ;
1211use x86_64:: structures:: paging:: mapper:: { MapToError , MappedFrame , TranslateResult , UnmapError } ;
1312use x86_64:: structures:: paging:: page:: PageRange ;
14- use x86_64:: structures:: paging:: {
15- FrameAllocator , Mapper , OffsetPageTable , Page , PageTable , PhysFrame , Size4KiB , Translate ,
16- } ;
13+ use x86_64:: structures:: paging:: { FrameAllocator , Mapper , OffsetPageTable , Page , PageTable , PhysFrame , Size4KiB , Translate } ;
1714
1815use crate :: arch:: x86_64:: kernel:: processor;
1916use crate :: arch:: x86_64:: mm:: { PhysAddr , VirtAddr } ;
@@ -325,24 +322,6 @@ fn make_p4_writable() {
325322
326323 let mut pt = unsafe { identity_mapped_page_table ( ) } ;
327324
328- let p4_page = {
329- let ( p4_frame, _) = Cr3 :: read_raw ( ) ;
330- let p4_addr = x86_64:: VirtAddr :: new ( p4_frame. start_address ( ) . as_u64 ( ) ) ;
331- Page :: < Size4KiB > :: from_start_address ( p4_addr) . unwrap ( )
332- } ;
333-
334- let TranslateResult :: Mapped { frame, flags, .. } = pt. translate ( p4_page. start_address ( ) ) else {
335- unreachable ! ( )
336- } ;
337-
338- let make_writable = || unsafe {
339- let flags = flags | PageTableEntryFlags :: WRITABLE ;
340- match frame {
341- MappedFrame :: Size1GiB ( _) => pt. set_flags_p3_entry ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
342- MappedFrame :: Size2MiB ( _) => pt. set_flags_p2_entry ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
343- MappedFrame :: Size4KiB ( _) => pt. update_flags ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
344- }
345- } ;
346325
347326 unsafe fn without_protect < F , R > ( f : F ) -> R
348327 where
@@ -359,7 +338,53 @@ fn make_p4_writable() {
359338 ret
360339 }
361340
362- unsafe { without_protect ( make_writable) }
341+ let ( p4_frame, _) = Cr3 :: read_raw ( ) ;
342+ unsafe {
343+ without_protect ( ||
344+ make_page_table_writable ( & mut pt, p4_frame, 4 )
345+ ) ;
346+ } ;
347+
348+ }
349+
350+
351+ unsafe fn make_page_table_writable ( page_table : & mut OffsetPageTable < ' static > , pt_frame : PhysFrame , level : u8 ) {
352+ let pt_address = page_table. phys_offset ( ) + pt_frame. start_address ( ) . as_u64 ( ) ;
353+ let pt = unsafe {
354+ pt_address. as_ptr :: < PageTable > ( ) . as_ref ( ) . unwrap ( )
355+ } ;
356+
357+ // Unmap the page table
358+ let TranslateResult :: Mapped { frame, flags, .. } = page_table. translate ( pt_address) else {
359+ unreachable ! ( )
360+ } ;
361+
362+ if !flags. contains ( PageTableEntryFlags :: WRITABLE ) {
363+ let flags = flags | PageTableEntryFlags :: WRITABLE ;
364+ let page = Page :: < Size4KiB > :: containing_address ( pt_address) ;
365+ unsafe {
366+ match frame {
367+ MappedFrame :: Size1GiB ( _) => page_table. set_flags_p3_entry ( page, flags) . unwrap ( ) . ignore ( ) ,
368+ MappedFrame :: Size2MiB ( _) => page_table. set_flags_p2_entry ( page, flags) . unwrap ( ) . ignore ( ) ,
369+ MappedFrame :: Size4KiB ( _) => page_table. update_flags ( page, flags) . unwrap ( ) . ignore ( ) ,
370+ }
371+ }
372+ warn ! ( "Page table {pt_frame:x?}, was mapped from RO memory!" ) ;
373+ }
374+
375+ for entry in pt. iter ( ) {
376+ if entry. is_unused ( ) {
377+ continue ;
378+ }
379+
380+ let is_page_table = level > 1 && !entry. flags ( ) . contains ( PageTableEntryFlags :: HUGE_PAGE ) ;
381+ if is_page_table {
382+ let phys = entry. frame ( ) . unwrap ( ) ;
383+ unsafe {
384+ make_page_table_writable ( page_table, phys, level - 1 ) ;
385+ }
386+ }
387+ }
363388}
364389
365390pub unsafe fn log_page_tables ( ) {
0 commit comments