@@ -308,7 +308,7 @@ mod x86_64 {
308
308
#[ inline]
309
309
pub unsafe fn write ( frame : PhysFrame , flags : Cr3Flags ) {
310
310
unsafe {
311
- Cr3 :: write_raw ( frame, flags. bits ( ) as u16 ) ;
311
+ Cr3 :: write_raw_impl ( false , frame, flags. bits ( ) as u16 ) ;
312
312
}
313
313
}
314
314
@@ -322,7 +322,22 @@ mod x86_64 {
322
322
#[ inline]
323
323
pub unsafe fn write_pcid ( frame : PhysFrame , pcid : Pcid ) {
324
324
unsafe {
325
- Cr3 :: write_raw ( frame, pcid. value ( ) ) ;
325
+ Cr3 :: write_raw_impl ( false , frame, pcid. value ( ) ) ;
326
+ }
327
+ }
328
+
329
+ /// Write a new P4 table address into the CR3 register without flushing existing TLB entries for
330
+ /// the PCID.
331
+ ///
332
+ /// ## Safety
333
+ ///
334
+ /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
335
+ /// changing the page mapping.
336
+ /// [`Cr4Flags::PCID`] must be set before calling this method.
337
+ #[ inline]
338
+ pub unsafe fn write_pcid_no_flush ( frame : PhysFrame , pcid : Pcid ) {
339
+ unsafe {
340
+ Cr3 :: write_raw_impl ( true , frame, pcid. value ( ) ) ;
326
341
}
327
342
}
328
343
@@ -334,8 +349,13 @@ mod x86_64 {
334
349
/// changing the page mapping.
335
350
#[ inline]
336
351
pub unsafe fn write_raw ( frame : PhysFrame , val : u16 ) {
352
+ unsafe { Self :: write_raw_impl ( false , frame, val) }
353
+ }
354
+
355
+ #[ inline]
356
+ unsafe fn write_raw_impl ( top_bit : bool , frame : PhysFrame , val : u16 ) {
337
357
let addr = frame. start_address ( ) ;
338
- let value = addr. as_u64 ( ) | val as u64 ;
358
+ let value = ( ( top_bit as u64 ) << 63 ) | addr. as_u64 ( ) | val as u64 ;
339
359
340
360
unsafe {
341
361
asm ! ( "mov cr3, {}" , in( reg) value, options( nostack, preserves_flags) ) ;
0 commit comments