Re: vmm(4): use SEV ASID bounds when allocating SVM ASIDs

hshoexer <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
Hi,

On Sun, Jun 14, 2026 at 02:25:53PM +0000, Chris Cunningham wrote:
> Hello,
> 
> I have a couple of patches that I've been running on a 7.8 host for a
> while now, and I think they may be addressing issues that still exist
> at top-of-tree. Just in case you'd rather have one patch per email,
> I'll send the second one separately.
> 
> This first one is about vmm(4). On an AMD Ryzen Threadripper PRO 9995WX
> box, every ordinary non-SEV VM refused to start, always with:
> 
> vmm_alloc_vpid_vcpu: no available ASIDs
> 
> The machine is:
> 
> ASUS Pro WS WRX90E-SAGE SE
> AMD Ryzen Threadripper PRO 9995WX
> 512GB RAM
> 
> After some digging it came down to CPUID leaf 0x8000001f. Here's the
> cpu0 line from dmesg:
> 
> cpu0: cpuid 8000001F eax=cffffffb<SME,SEV,SEVES,SEVSNP,VMPL,RMPQUERY,VMPLSSS,SECTSC,TSCAUXVIRT,HWECACHECOH,REQ64BITHOST,RESTINJ,ALTINJ,DBGSTSW,IBSDISALLOW,VTE,VMGEXITPARAM,VTOMMSR,IBSVIRT,VMSARPROT,SMTPROT> ecx=3ee edx=cf680a81
> 
> ECX reports 1006 encrypted guest ASIDs, which looks sane, but EDX
> (MinSevNoEsAsid) comes back much larger than that. NASID from CPUID
> 0x8000000a EBX is only 32768. EDX also isn't stable across CPUs/boots
> on this box -- I've seen 0x823c67d2, 0x9c866294 and 0xcf680a81 at
> different times. My best guess is that it's because the board's AMD
> PSP/CCP shows up "not configured" in dmesg, so nothing ever populates
> EDX with a real boundary, but I haven't confirmed that part.

Is SEV enabled in the firmware?

> The trouble is that we store EDX straight into amd64_min_noes_asid and
> then use it as the minimum ASID for every non-SEV-ES guest, ordinary
> non-SEV guests included. With a bogus value that's non-zero and well
> past the range vmm actually scans, vmm_alloc_vpid_vcpu() never finds a
> free ASID and bails out.
> 
> The diff below keeps ECX as the upper bound of the encrypted-ASID
> range, and only trusts EDX as the lower bound for plain SEV guests when
> it's actually in range. Ordinary non-SEV guests now start at ECX + 1.
> If the encrypted range somehow covers everything vmm would scan,
> allocation just fails rather than dipping into ASIDs meant for
> encrypted guests.
> 
> With this applied the same host happily starts ordinary vmd guests
> again.
> 
> Thanks,
> Chris
> 
> diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c
> index 51e8344d573..67dafb40e63 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_num_sev_asids;
> int amd64_min_noes_asid;
> int has_rdrand;
> int has_rdseed;
> @@ -711,7 +712,12 @@ 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;
> + amd64_num_sev_asids = ci->ci_feature_amdsev_ecx;
> + if (ci->ci_feature_amdsev_edx >= 1 &&
> + ci->ci_feature_amdsev_edx <= ci->ci_feature_amdsev_ecx)
> + amd64_min_noes_asid = ci->ci_feature_amdsev_edx;
> + else
> + amd64_min_noes_asid = 0;
> if (cpu_sev_guestmode && CPU_IS_PRIMARY(ci))
> printf("\n%s: SEV%s guest mode", ci->ci_dev->dv_xname,
> ISSET(cpu_sev_guestmode, SEV_STAT_ES_ENABLED) ?
> diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c
> index 787b65e29e1..2b0e02c2095 100644
> --- a/sys/arch/amd64/amd64/vmm_machdep.c
> +++ b/sys/arch/amd64/amd64/vmm_machdep.c
> @@ -6926,7 +6926,17 @@ vmm_alloc_vpid_vcpu(uint16_t *vpid, struct vcpu *vcpu)
> struct vmm_softc *sc = vmm_softc;
> 
> rw_enter_write(&vmm_softc->vpid_lock);
> - if (vcpu == NULL || vcpu->vc_seves || amd64_min_noes_asid == 0)
> + if (vcpu == NULL || vcpu->vc_seves)
> + minasid = 1;
> + else if (vcpu->vc_sev && amd64_min_noes_asid != 0)
> + minasid = amd64_min_noes_asid;
> + else if (!vcpu->vc_sev && amd64_num_sev_asids != 0) {
> + if (amd64_num_sev_asids < sc->max_vpid)
> + minasid = amd64_num_sev_asids + 1;
> + else
> + minasid = sc->max_vpid + 1;
> + }
> + else if (amd64_min_noes_asid == 0)
> minasid = 1;
> else
> minasid = amd64_min_noes_asid;
> diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
> index 15423f5d5f2..b771214d400 100644
> --- a/sys/arch/amd64/include/cpu.h
> +++ b/sys/arch/amd64/include/cpu.h
> @@ -419,6 +419,7 @@ void identifycpu(struct cpu_info *);
> int cpu_amd64speed(int *);
> extern int cpuspeed;
> extern int amd64_pos_cbit;
> +extern int amd64_num_sev_asids;
> extern int amd64_min_noes_asid;
> /* machdep.c */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.