From: Hans-Jörg Höxer Subject: vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK To: Cc: Date: Wed, 30 Apr 2025 16:26:37 +0200 Hi, this is diff 2/3. As vmm(4) cannot access a SEV-ES guests rflags register, we have to use the GUEST_INTERRUPT_MASK field from the VMCB for SEV-ES enabled guests. Take care, HJ. --------------------------------------------------------------- commit 939134e1a692824d0f8d94ea566102637ff2b800 Author: Hans-Joerg Hoexer Date: Tue Nov 12 14:55:11 2024 +0100 vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK Due to state encryption we can not determine the state of the interrupt enable flag from the FLAGS register. Therefore the VMCB provides at offset 0x68 bit 1 the current state of this flag. However, only when this is a SEV-ES enabled guest. Otherwise, we have to use the FLAGS register. diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c index 3d5c58de71d..28809aa57d2 100644 --- a/sys/arch/amd64/amd64/vmm_machdep.c +++ b/sys/arch/amd64/amd64/vmm_machdep.c @@ -98,6 +98,7 @@ int vmx_load_pdptes(struct vcpu *); int vmx_handle_exit(struct vcpu *); int svm_handle_exit(struct vcpu *); int svm_handle_efercr(struct vcpu *, uint64_t); +int svm_get_iflag(struct vcpu *, uint64_t); int svm_handle_msr(struct vcpu *); int vmm_handle_xsetbv(struct vcpu *, uint64_t *); int vmx_handle_xsetbv(struct vcpu *); @@ -4149,7 +4150,7 @@ svm_handle_hlt(struct vcpu *vcpu) /* All HLT insns are 1 byte */ vcpu->vc_gueststate.vg_rip += 1; - if (!(rflags & PSL_I)) { + if (!svm_get_iflag(vcpu, rflags)) { DPRINTF("%s: guest halted with interrupts disabled\n", __func__); return (EIO); @@ -4245,7 +4246,7 @@ svm_handle_exit(struct vcpu *vcpu) switch (exit_reason) { case SVM_VMEXIT_VINTR: - if (!(rflags & PSL_I)) { + if (!svm_get_iflag(vcpu, rflags)) { DPRINTF("%s: impossible interrupt window exit " "config\n", __func__); ret = EINVAL; @@ -4369,6 +4370,23 @@ svm_handle_efercr(struct vcpu *vcpu, uint64_t exit_reason) return (0); } +/* + * svm_get_iflag + * + * With SEV-ES the hypervisor has no access to the flags register. + * Only the the state of the PSL_I is proivded by v_intr_shadow in + * the VMCB. + */ +int +svm_get_iflag(struct vcpu *vcpu, uint64_t rflags) +{ + struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; + + if (vcpu->vc_seves) + return (vmcb->v_intr_shadow & SMV_GUEST_INTR_MASK); + return (rflags & PSL_I); +} + /* * vmx_handle_exit * @@ -6421,7 +6439,7 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp) */ ret = svm_handle_exit(vcpu); - if (vcpu->vc_gueststate.vg_rflags & PSL_I) + if (svm_get_iflag(vcpu, vcpu->vc_gueststate.vg_rflags)) vcpu->vc_irqready = 1; else vcpu->vc_irqready = 0; diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index 22c60907f1a..22d892ae2f3 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -627,6 +627,8 @@ struct vmcb_segment { #define SVM_ENABLE_SEV (1ULL << 1) #define SVM_SEVES_ENABLE (1ULL << 2) +#define SMV_GUEST_INTR_MASK (1ULL << 1) + #define SVM_LBRVIRT_ENABLE (1ULL << 0) struct vmcb {