Download raw body.
vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK
On Wed, Apr 30, 2025 at 04:26:37PM +0200, Hans-Jörg Höxer wrote:
> 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.
ok mlarkin when you are ready.
-ml
>
> ---------------------------------------------------------------
> 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