diff --git a/kernel/src/requests.rs b/kernel/src/requests.rs index 9b797e7eb..e3c382c79 100644 --- a/kernel/src/requests.rs +++ b/kernel/src/requests.rs @@ -134,6 +134,15 @@ pub fn request_loop() { // the guest to execute. When halting, assume that the hypervisor // will schedule the guest VMPL on its own. if update_mappings().is_ok() { + // Process any pending #HV events before leaving the SVSM. This + // must be done before updating guest APIC state so that any + // additional guest APIC updates generated by the host will block + // the VMPL transition and permit reevaluation of guest APIC + // state. + if let Some(hv_doorbell) = this_cpu().hv_doorbell() { + hv_doorbell.process_pending_events(); + } + // Make VMSA runnable again by setting EFER.SVME. This requires a // separate scope so the CPU reference does not outlive the use of // the VMSA reference. diff --git a/kernel/src/sev/ghcb.rs b/kernel/src/sev/ghcb.rs index a838e0513..58bde7eba 100644 --- a/kernel/src/sev/ghcb.rs +++ b/kernel/src/sev/ghcb.rs @@ -693,13 +693,7 @@ pub fn switch_to_vmpl(vmpl: u32) { // correctly block the VMPL switch so that events can be processed. let hv_doorbell = this_cpu().hv_doorbell(); let ptr = match hv_doorbell { - Some(doorbell) => { - // Process any pending #HV events before leaving the SVSM. No event - // can cancel the request to enter the guest VMPL, so proceed with - // guest entry once events have been handled. - doorbell.process_pending_events(); - ptr::from_ref(doorbell) - } + Some(doorbell) => ptr::from_ref(doorbell), None => ptr::null(), }; unsafe {