File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -496,6 +496,29 @@ impl SandboxMemoryManager<HostSharedMemory> {
496496 }
497497 }
498498
499+ /// Flush all snapshot and scratch memory from CPU caches using clflush,
500+ /// then issue an mfence to ensure completion.
501+ #[ cfg( target_arch = "x86_64" ) ]
502+ pub ( crate ) fn flush_caches ( & self ) {
503+ use core:: arch:: x86_64:: { _mm_clflush, _mm_mfence} ;
504+ const CACHE_LINE : usize = 64 ;
505+
506+ let snap_ptr = self . shared_mem . base_addr ( ) as * const u8 ;
507+ let snap_len = self . shared_mem . mem_size ( ) ;
508+ let scratch_ptr = self . scratch_mem . base_addr ( ) as * const u8 ;
509+ let scratch_len = self . scratch_mem . mem_size ( ) ;
510+
511+ unsafe {
512+ for offset in ( 0 ..snap_len) . step_by ( CACHE_LINE ) {
513+ _mm_clflush ( snap_ptr. add ( offset) ) ;
514+ }
515+ for offset in ( 0 ..scratch_len) . step_by ( CACHE_LINE ) {
516+ _mm_clflush ( scratch_ptr. add ( offset) ) ;
517+ }
518+ _mm_mfence ( ) ;
519+ }
520+ }
521+
499522 /// This function restores a memory snapshot from a given snapshot.
500523 pub ( crate ) fn restore_snapshot (
501524 & mut self ,
Original file line number Diff line number Diff line change @@ -294,6 +294,14 @@ impl MultiUseSandbox {
294294 } ) ?;
295295
296296 let ( gsnapshot, gscratch) = self . mem_mgr . restore_snapshot ( & snapshot) ?;
297+
298+ // Flush all snapshot and scratch memory from CPU caches and drain
299+ // the store buffer. On AMD SVM with NPT, the guest reads through
300+ // nested page tables which may not see host-side cached writes.
301+ // clflush evicts each cache line; mfence ensures completion.
302+ #[ cfg( target_arch = "x86_64" ) ]
303+ self . mem_mgr . flush_caches ( ) ;
304+
297305 if let Some ( gsnapshot) = gsnapshot {
298306 self . vm
299307 . update_snapshot_mapping ( gsnapshot)
You can’t perform that action at this time.
0 commit comments