From: Chris Cunningham Subject: vmm(4): use SEV ASID bounds when allocating SVM ASIDs To: "tech@openbsd.org" Date: Sun, 14 Jun 2026 14:25:53 +0000 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 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. 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 */