diff --git a/igvmbld/igvmbld.c b/igvmbld/igvmbld.c index a96de1e09..990d5e7bd 100644 --- a/igvmbld/igvmbld.c +++ b/igvmbld/igvmbld.c @@ -357,7 +357,7 @@ void generate_initial_vmsa(SEV_VMSA *vmsa) vmsa->rip = 0x10000; vmsa->rsp = vmsa->rip - sizeof(Stage2Stack); - vmsa->sev_features = SevFeature_Snp; + vmsa->sev_features = SevFeature_Snp | SevFeature_RestrictInj; } void setup_igvm_platform_header(void) diff --git a/igvmbld/sev-snp.h b/igvmbld/sev-snp.h index 639cd5a1f..604f9a1ce 100644 --- a/igvmbld/sev-snp.h +++ b/igvmbld/sev-snp.h @@ -77,3 +77,4 @@ enum { }; #define SevFeature_Snp 0x0001 +#define SevFeature_RestrictInj 0x0008 diff --git a/src/cpu/idt/common.rs b/src/cpu/idt/common.rs index 245c535f9..a72dda964 100644 --- a/src/cpu/idt/common.rs +++ b/src/cpu/idt/common.rs @@ -30,7 +30,7 @@ pub const _AC_VECTOR: usize = 17; pub const _MCE_VECTOR: usize = 18; pub const _XF_VECTOR: usize = 19; pub const _CP_VECTOR: usize = 21; -pub const _HV_VECTOR: usize = 28; +pub const HV_VECTOR: usize = 28; pub const VC_VECTOR: usize = 29; pub const _SX_VECTOR: usize = 30; diff --git a/src/cpu/idt/stage2.rs b/src/cpu/idt/stage2.rs index ee8b5722d..bc2f09ea9 100644 --- a/src/cpu/idt/stage2.rs +++ b/src/cpu/idt/stage2.rs @@ -4,7 +4,7 @@ // // Author: Joerg Roedel -use super::common::{load_idt, Idt, IdtEntry, DF_VECTOR, GLOBAL_IDT, VC_VECTOR}; +use super::common::{load_idt, Idt, IdtEntry, DF_VECTOR, GLOBAL_IDT, HV_VECTOR, VC_VECTOR}; use crate::address::VirtAddr; use crate::cpu::control_regs::read_cr2; use crate::cpu::vc::{stage2_handle_vc_exception, stage2_handle_vc_exception_no_ghcb}; @@ -49,6 +49,10 @@ pub extern "C" fn stage2_generic_idt_handler(ctx: &mut X86ExceptionContext) { ); } VC_VECTOR => stage2_handle_vc_exception(ctx), + HV_VECTOR => + // #HV does not require processing during stage 2 and can be + // completely ignored. + {} _ => { let err = ctx.error_code; let vec = ctx.vector; diff --git a/src/cpu/idt/svsm.rs b/src/cpu/idt/svsm.rs index 4850d28c4..3b4efd6e2 100644 --- a/src/cpu/idt/svsm.rs +++ b/src/cpu/idt/svsm.rs @@ -11,7 +11,8 @@ use super::super::tss::IST_DF; use super::super::vc::handle_vc_exception; use super::common::PF_ERROR_WRITE; use super::common::{ - load_idt, Idt, IdtEntry, BP_VECTOR, DF_VECTOR, GLOBAL_IDT, GP_VECTOR, PF_VECTOR, VC_VECTOR, + load_idt, Idt, IdtEntry, BP_VECTOR, DF_VECTOR, GLOBAL_IDT, GP_VECTOR, HV_VECTOR, PF_VECTOR, + VC_VECTOR, }; use crate::address::VirtAddr; use crate::cpu::X86ExceptionContext; @@ -87,6 +88,12 @@ pub extern "C" fn generic_idt_handler(ctx: &mut X86ExceptionContext) { } VC_VECTOR => handle_vc_exception(ctx), BP_VECTOR => handle_debug_exception(ctx, ctx.vector), + HV_VECTOR => + // #HV processing is not required in the SVSM. If a maskable + // interrupt occurs, it will be processed prior to the next exit. + // There are no NMI sources, and #MC cannot be handled anyway + // and can safely be ignored. + {} _ => { let err = ctx.error_code; let vec = ctx.vector; diff --git a/src/cpu/vmsa.rs b/src/cpu/vmsa.rs index 025863233..09d7a4683 100644 --- a/src/cpu/vmsa.rs +++ b/src/cpu/vmsa.rs @@ -138,4 +138,7 @@ pub fn init_guest_vmsa(v: &mut VMSA, rip: u64) { v.vmpl = GUEST_VMPL as u8; v.sev_features = read_msr(0xc0010131) >> 2; + + // Ensure that guest VMSAs do not enable restricted injection. + v.sev_features &= !0b1000; } diff --git a/src/sev/status.rs b/src/sev/status.rs index 162259eb3..b01bf3774 100644 --- a/src/sev/status.rs +++ b/src/sev/status.rs @@ -155,19 +155,15 @@ pub fn sev_snp_enabled() -> bool { pub fn sev_status_verify() { let required = SEVStatusFlags::SEV | SEVStatusFlags::SEV_ES | SEVStatusFlags::SEV_SNP; - let not_supported = SEVStatusFlags::VTOM - | SEVStatusFlags::REFLECT_VC + let supported = SEVStatusFlags::DBGSWP | SEVStatusFlags::REST_INJ - | SEVStatusFlags::ALT_INJ - | SEVStatusFlags::DBGSWP | SEVStatusFlags::PREV_HOST_IBS | SEVStatusFlags::BTB_ISOLATION - | SEVStatusFlags::SECURE_TSC | SEVStatusFlags::VMSA_REG_PROT; let status = sev_flags(); let required_check = status & required; - let supported_check = status & not_supported; + let not_supported_check = status & !(supported | required); if required_check != required { log::error!( @@ -177,8 +173,8 @@ pub fn sev_status_verify() { panic!("Required SEV features not available"); } - if !supported_check.is_empty() { - log::error!("Unsupported features enabled: {}", supported_check); + if !not_supported_check.is_empty() { + log::error!("Unsupported features enabled: {}", not_supported_check); panic!("Unsupported SEV features enabled"); } }