hypervisor: mshv: Clear SW_EXIT_INFO1 in case of no error

There were some scenarios where we are not clearing SW_EXIT_INFO1 to
indicate that there were no error while handling the GHCB exit.
Recently, new Linux guests got stricter with checking the value of
SW_EXIT_INFO1 after coming back from VMGEXIT and started crashing. Fix
this behavior by clearing out SW_EXIT_INFO1 in case of no error.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This commit is contained in:
Jinank Jain 2024-07-22 13:22:41 +05:30 committed by Liu Wei
parent 5fddf76a3b
commit 330e1aac36

View File

@ -926,15 +926,7 @@ impl cpu::Vcpu for MshvVcpu {
)?; )?;
// Clear the SW_EXIT_INFO1 register to indicate no error // Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg = self.clear_swexit_info1(ghcb_gpa)?;
mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd.gpa_write(&mut swei1_rw_gpa_arg).map_err(
|e| cpu::HypervisorCpuError::GpaWrite(e.into()),
)?;
} }
SVM_NAE_HV_DOORBELL_PAGE_QUERY => { SVM_NAE_HV_DOORBELL_PAGE_QUERY => {
let mut reg_assocs = [ hv_register_assoc { let mut reg_assocs = [ hv_register_assoc {
@ -956,6 +948,9 @@ impl cpu::Vcpu for MshvVcpu {
self.fd.gpa_write(&mut swei2_rw_gpa_arg).map_err( self.fd.gpa_write(&mut swei2_rw_gpa_arg).map_err(
|e| cpu::HypervisorCpuError::GpaWrite(e.into()), |e| cpu::HypervisorCpuError::GpaWrite(e.into()),
)?; )?;
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
} }
SVM_NAE_HV_DOORBELL_PAGE_CLEAR => { SVM_NAE_HV_DOORBELL_PAGE_CLEAR => {
let mut swei2_rw_gpa_arg = let mut swei2_rw_gpa_arg =
@ -1056,14 +1051,7 @@ impl cpu::Vcpu for MshvVcpu {
} }
// Clear the SW_EXIT_INFO1 register to indicate no error // Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa { self.clear_swexit_info1(ghcb_gpa)?;
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
} }
SVM_EXITCODE_MMIO_READ => { SVM_EXITCODE_MMIO_READ => {
let src_gpa = let src_gpa =
@ -1092,6 +1080,9 @@ impl cpu::Vcpu for MshvVcpu {
self.fd self.fd
.gpa_write(&mut arg) .gpa_write(&mut arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
} }
SVM_EXITCODE_MMIO_WRITE => { SVM_EXITCODE_MMIO_WRITE => {
let dst_gpa = let dst_gpa =
@ -1120,6 +1111,9 @@ impl cpu::Vcpu for MshvVcpu {
cpu::HypervisorCpuError::RunVcpu(e.into()) cpu::HypervisorCpuError::RunVcpu(e.into())
})?; })?;
} }
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
} }
SVM_EXITCODE_SNP_GUEST_REQUEST => { SVM_EXITCODE_SNP_GUEST_REQUEST => {
let req_gpa = let req_gpa =
@ -1165,15 +1159,8 @@ impl cpu::Vcpu for MshvVcpu {
.sev_snp_ap_create(&mshv_ap_create_req) .sev_snp_ap_create(&mshv_ap_create_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa { // Clear the SW_EXIT_INFO1 register to indicate no error
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET, self.clear_swexit_info1(ghcb_gpa)?;
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
} }
_ => panic!( _ => panic!(
"GHCB_INFO_NORMAL: Unhandled exit code: {:0x}", "GHCB_INFO_NORMAL: Unhandled exit code: {:0x}",
@ -1510,6 +1497,27 @@ impl MshvVcpu {
.set_vcpu_events(events) .set_vcpu_events(events)
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
} }
///
/// Clear SW_EXIT_INFO1 register for SEV-SNP guests.
///
#[cfg(feature = "sev_snp")]
fn clear_swexit_info1(
&self,
ghcb_gpa: u64,
) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
// Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
Ok(cpu::VmExit::Ignore)
}
} }
/// Wrapper over Mshv VM ioctls. /// Wrapper over Mshv VM ioctls.