From: Alexander Bluhm Subject: Re: SEV-ES: respect minimum ASID value To: tech@openbsd.org, Hans-Joerg_Hoexer@genua.de Date: Wed, 23 Apr 2025 21:55:15 +0200 On Tue, Apr 15, 2025 at 03:54:31PM +0200, Hans-J?rg H?xer wrote: > Hi, > > With SEV-ES we have to respect a "minimum ASID" when running both SEV-ES > and non-SEV-ES guests. The minimum ASID value is configured in the BIOS. > Non-SEV-ES guests will have to use ASIDs starting at that value; SEV-ES > enabled VMs use ASIDs starting at 1. Setting the minimum ASID in the > BIOS to 1, disables SEV-ES. > > At runtime the minimum ASID is determined by CPUID. > > This change determins the minimum ASID value in identifycpu() and uses it > when allocating ASIDs for SVM based VMs. For Intel VMX there's no change. > > Comments? I figured out what the problem with my SEV setup is. (actually hshoexer figured it out) To test SEV-ES I have changed the BIOS setting. Now the host kernel no longer handles SEV without ES correctly. Diff below fixes it. > --------------------------------------------------------------------------- > commit 76cad15af8a10628e446aa31f08cdab99a28a0bc > Author: Hans-Joerg Hoexer > Date: Wed Jul 10 13:25:04 2024 +0200 > > vmm: minimum ASID for non-SEVES guests > > Introduce vmm_alloc_asid() to be used by SVM base VMs. No change > vor VMX based VMs. > > diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c > index 18ecbc8f4c8..1a9a99e9bbb 100644 > --- a/sys/arch/amd64/amd64/identcpu.c > +++ b/sys/arch/amd64/amd64/identcpu.c > @@ -67,6 +67,7 @@ int cpuspeed; > > int amd64_has_xcrypt; > int amd64_pos_cbit; /* C bit position for SEV */ > +int amd64_min_noes_asid; > int has_rdrand; > int has_rdseed; > > @@ -710,6 +711,7 @@ identifycpu(struct cpu_info *ci) > 'd', CPUID_MEMBER(ci_feature_amdsev_edx), > CPUID_AMDSEV_EDX_BITS); > amd64_pos_cbit = (ci->ci_feature_amdsev_ebx & 0x3f); > + amd64_min_noes_asid = (ci->ci_feature_amdsev_edx); > } > > printf("\n"); > diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c > index 5a8c9a14612..f75a5feb815 100644 > --- a/sys/arch/amd64/amd64/vmm_machdep.c > +++ b/sys/arch/amd64/amd64/vmm_machdep.c > @@ -125,6 +125,7 @@ int vmx_fault_page(struct vcpu *, paddr_t); > int vmx_handle_np_fault(struct vcpu *); > int svm_handle_np_fault(struct vcpu *); > int vmm_alloc_vpid(uint16_t *); > +int vmm_alloc_asid(uint16_t *, struct vcpu *); > void vmm_free_vpid(uint16_t); > const char *vcpu_state_decode(u_int); > const char *vmx_exit_reason_decode(uint32_t); > @@ -232,6 +233,9 @@ extern struct vmm_softc *vmm_softc; > extern vaddr_t idt_vaddr; > extern struct gate_descriptor *idt; > > +/* Minimum ASID value for an SEV enabled, SEV-ES disabled guest. */ > +extern int amd64_min_noes_asid; > + > /* Constants used in "CR access exit" */ > #define CR_WRITE 0 > #define CR_READ 1 > @@ -2766,7 +2770,7 @@ vcpu_init_svm(struct vcpu *vcpu, struct vm_create_params *vcp) > int ret = 0; > > /* Allocate an ASID early to avoid km_alloc if we're out of ASIDs. */ > - if (vmm_alloc_vpid(&vcpu->vc_vpid)) > + if (vmm_alloc_asid(&vcpu->vc_vpid, vcpu)) > return (ENOMEM); > > /* Allocate VMCB VA */ > @@ -6354,27 +6358,32 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp) > } > > /* > - * vmm_alloc_vpid > + * _vmm_alloc_vpid > * > * Sets the memory location pointed to by "vpid" to the next available VPID > - * or ASID. > + * or ASID. For SEV-ES consider minimum ASID value for non-ES enabled guests. > * > * Parameters: > * vpid: Pointer to location to receive the next VPID/ASID > + * vcpu: Pointer to VCPU data structure > * > * Return Values: > * 0: The operation completed successfully > * ENOMEM: No VPIDs/ASIDs were available. Content of 'vpid' is unchanged. > */ > int > -vmm_alloc_vpid(uint16_t *vpid) > +_vmm_alloc_vpid(uint16_t *vpid, struct vcpu *vcpu) > { > - uint16_t i; > + uint16_t i, minasid; > uint8_t idx, bit; > struct vmm_softc *sc = vmm_softc; > > rw_enter_write(&vmm_softc->vpid_lock); > - for (i = 1; i <= sc->max_vpid; i++) { > + if (vcpu == NULL || vcpu->vc_seves) > + minasid = 1; > + else > + minasid = amd64_min_noes_asid; > + for (i = minasid; i <= sc->max_vpid; i++) { > idx = i / 8; > bit = i - (idx * 8); > > @@ -6396,6 +6405,18 @@ vmm_alloc_vpid(uint16_t *vpid) > return ENOMEM; > } > > +int > +vmm_alloc_vpid(uint16_t *vpid) > +{ > + return _vmm_alloc_vpid(vpid, NULL); > +} > + > +int > +vmm_alloc_asid(uint16_t *asid, struct vcpu *vcpu) > +{ > + return _vmm_alloc_vpid(asid, vcpu); > +} > + > /* > * vmm_free_vpid > *