From 8fd0310db9b816c5f3dae2cf5e714359e96478a9 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Mon, 26 Aug 2024 11:14:34 +0200 Subject: [PATCH] hypervisor: mshv: implement extended guest requests with empty certs Previously we didn't handle extended guest requests at all and always returned an error. This lead to issues with some guests that expected extended requests to succeed. Instead, handle extended requests like normal requests and write zeros to the extended area to signal to the guest that we don't want to supply any additional certificate data. Signed-off-by: Tom Dohrmann --- hypervisor/src/mshv/mod.rs | 33 +++++++++++++++++----------- hypervisor/src/mshv/snp_constants.rs | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 0d8ce8aed..6000513d9 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -977,18 +977,6 @@ impl cpu::Vcpu for MshvVcpu { } } } - SVM_EXITCODE_SNP_EXTENDED_GUEST_REQUEST => { - warn!("Fetching extended guest request is not supported"); - // Extended guest request is not supported by the Hypervisor - // Returning the error to the guest - // 0x6 means `The NAE event was not valid` - // Reference: GHCB Spec, page 42 - let value: u64 = 0x6; - self.gpa_write( - ghcb_gpa + GHCB_SW_EXITINFO2_OFFSET, - &value.to_le_bytes(), - )?; - } SVM_EXITCODE_IOIO_PROT => { let exit_info1 = info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1 as u32; @@ -1082,7 +1070,26 @@ impl cpu::Vcpu for MshvVcpu { // 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 + | SVM_EXITCODE_SNP_EXTENDED_GUEST_REQUEST => { + if exit_code == SVM_EXITCODE_SNP_EXTENDED_GUEST_REQUEST { + info!("Fetching extended guest request is not supported"); + // We don't support extended guest request, so we just write empty data. + // This matches the behavior of KVM in Linux 6.11. + + // Read RAX & RBX from the GHCB. + let mut data = [0; 8]; + self.gpa_read(ghcb_gpa + GHCB_RAX_OFFSET, &mut data)?; + let data_gpa = u64::from_le_bytes(data); + self.gpa_read(ghcb_gpa + GHCB_RBX_OFFSET, &mut data)?; + let data_npages = u64::from_le_bytes(data); + + if data_npages > 0 { + // The certificates are terminated by 24 zero bytes. + self.gpa_write(data_gpa, &[0; 24])?; + } + } + let req_gpa = info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1; let rsp_gpa = diff --git a/hypervisor/src/mshv/snp_constants.rs b/hypervisor/src/mshv/snp_constants.rs index 307326ddd..69b123647 100644 --- a/hypervisor/src/mshv/snp_constants.rs +++ b/hypervisor/src/mshv/snp_constants.rs @@ -20,5 +20,6 @@ pub const ECDSA_SIG_Y_COMPONENT_END: usize = // 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_EXITINFO1_OFFSET: u64 = 0x398; pub const GHCB_SW_EXITINFO2_OFFSET: u64 = 0x3A0;