Index | Thread | Search

From:
Mike Larkin <mlarkin@nested.page>
Subject:
Re: vmm(4): For SEV-ES use GUEST_INTERRUPT_MASK
To:
tech@openbsd.org, Hans-Joerg_Hoexer@genua.de
Date:
Sun, 18 May 2025 23:56:43 -0700

Download raw body.

Thread
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 {