Download raw body.
vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK
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 <hshoexer@genua.de>
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 {
vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK