hypervisor: mshv: modify GuestRequest handling for CVM

VMM needs to handle VMG exit for guest request. This patch
removes the old method that uses gpa_read/write(IOCTL and hypercall),
which is expensive and update the GHCB page using
mapped(root partition) struct.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam 2024-11-07 11:12:52 -08:00 committed by Wei Liu
parent a458351d8b
commit e4a5219f53
2 changed files with 10 additions and 38 deletions

View File

@ -907,9 +907,7 @@ impl cpu::Vcpu for MshvVcpu {
GHCB_INFO_NORMAL => { GHCB_INFO_NORMAL => {
let exit_code = let exit_code =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_code as u32; info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_code as u32;
// SAFETY: Accessing a union element from bindgen generated bindings.
let pfn = unsafe { ghcb_msr.__bindgen_anon_2.gpa_page_number() };
let ghcb_gpa = pfn << GHCB_INFO_BIT_WIDTH;
match exit_code { match exit_code {
SVM_EXITCODE_HV_DOORBELL_PAGE => { SVM_EXITCODE_HV_DOORBELL_PAGE => {
let exit_info1 = let exit_info1 =
@ -1060,7 +1058,7 @@ impl cpu::Vcpu for MshvVcpu {
assert!(data_len <= 0x8); assert!(data_len <= 0x8);
let mut data = vec![0; data_len]; let mut data = vec![0; data_len];
// SAFETY: Accessing the field from a mapped address // SAFETY: Accessing data from a mapped address
let bytes_shared_ghcb = let bytes_shared_ghcb =
unsafe { (*ghcb).shared[0].to_le_bytes() }; unsafe { (*ghcb).shared[0].to_le_bytes() };
data.copy_from_slice(&bytes_shared_ghcb[..data_len]); data.copy_from_slice(&bytes_shared_ghcb[..data_len]);
@ -1081,15 +1079,16 @@ impl cpu::Vcpu for MshvVcpu {
// We don't support extended guest request, so we just write empty data. // We don't support extended guest request, so we just write empty data.
// This matches the behavior of KVM in Linux 6.11. // This matches the behavior of KVM in Linux 6.11.
// Read RAX & RBX from the GHCB. // Read RBX from the GHCB.
let mut data = [0; 8]; // SAFETY: Accessing data from a mapped address
self.gpa_read(ghcb_gpa + GHCB_RAX_OFFSET, &mut data)?; let data_gpa = unsafe { (*ghcb).rax };
let data_gpa = u64::from_le_bytes(data); // SAFETY: Accessing data from a mapped address
self.gpa_read(ghcb_gpa + GHCB_RBX_OFFSET, &mut data)?; let data_npages = unsafe { (*ghcb).rbx };
let data_npages = u64::from_le_bytes(data);
if data_npages > 0 { if data_npages > 0 {
// The certificates are terminated by 24 zero bytes. // The certificates are terminated by 24 zero bytes.
// TODO: Need to check if data_gpa is the address of the shared buffer in the GHCB page
// in that case we should clear the shared buffer(24 bytes)
self.gpa_write(data_gpa, &[0; 24])?; self.gpa_write(data_gpa, &[0; 24])?;
} }
} }
@ -1110,7 +1109,7 @@ impl cpu::Vcpu for MshvVcpu {
req_gpa, rsp_gpa req_gpa, rsp_gpa
); );
self.gpa_write(ghcb_gpa + GHCB_SW_EXITINFO2_OFFSET, &[0; 8])?; set_svm_field_u64_ptr!(ghcb, exit_info2, 0);
} }
SVM_EXITCODE_SNP_AP_CREATION => { SVM_EXITCODE_SNP_AP_CREATION => {
let vmsa_gpa = let vmsa_gpa =
@ -1519,27 +1518,6 @@ impl MshvVcpu {
Ok(cpu::VmExit::Ignore) Ok(cpu::VmExit::Ignore)
} }
#[cfg(feature = "sev_snp")]
fn gpa_read(&self, gpa: u64, data: &mut [u8]) -> cpu::Result<()> {
for (gpa, chunk) in (gpa..)
.step_by(HV_READ_WRITE_GPA_MAX_SIZE as usize)
.zip(data.chunks_mut(HV_READ_WRITE_GPA_MAX_SIZE as usize))
{
let mut rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: gpa,
byte_count: chunk.len() as u32,
..Default::default()
};
self.fd
.gpa_read(&mut rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaRead(e.into()))?;
chunk.copy_from_slice(&rw_gpa_arg.data[..chunk.len()]);
}
Ok(())
}
#[cfg(feature = "sev_snp")] #[cfg(feature = "sev_snp")]
fn gpa_write(&self, gpa: u64, data: &[u8]) -> cpu::Result<()> { fn gpa_write(&self, gpa: u64, data: &[u8]) -> cpu::Result<()> {
for (gpa, chunk) in (gpa..) for (gpa, chunk) in (gpa..)

View File

@ -16,9 +16,3 @@ pub const ECDSA_SIG_X_COMPONENT_END: usize =
pub const ECDSA_SIG_Y_COMPONENT_START: usize = ECDSA_SIG_X_COMPONENT_END; pub const ECDSA_SIG_Y_COMPONENT_START: usize = ECDSA_SIG_X_COMPONENT_END;
pub const ECDSA_SIG_Y_COMPONENT_END: usize = pub const ECDSA_SIG_Y_COMPONENT_END: usize =
ECDSA_SIG_X_COMPONENT_END + ECDSA_SIG_Y_COMPONENT_SIZE_IN_BYTES; ECDSA_SIG_X_COMPONENT_END + ECDSA_SIG_Y_COMPONENT_SIZE_IN_BYTES;
// These constants are derived from GHCB spec Sect. 2.6 Table 3 GHCB Layout
// Link: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf
pub const GHCB_RAX_OFFSET: u64 = 0x01F8;
pub const GHCB_RBX_OFFSET: u64 = 0x0318;
pub const GHCB_SW_EXITINFO2_OFFSET: u64 = 0x3A0;