On Thu, Oct 01, 2026 at 05:41:55PM +1000, Jonathan Gray wrote:
> On Wed, Sep 30, 2026 at 09:44:34PM +0200, Sebastian Albert wrote:
> > >Synopsis: amd64: GPF panic at boot on KVM guests lacking MSR_DE_CFG
> > (AMD family 17h)
> > >Category: amd64
> > >Environment:
> > System : OpenBSD 7.9
> > Details : OpenBSD 7.9 (GENERIC.MP) #15: Sun Sep 27 02:47:36 MDT
> > 2026
> >
> > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> >
> > Architecture: OpenBSD.amd64
> > Machine : amd64
> > >Description:
> > OpenBSD 7.9/amd64 (and, judging from the source, 8.0 as well) panics
> > very early during boot on a KVM-based VPS (hoster 1blu.de, Virtuozzo)
> > with an AMD EPYC (Zen 1) CPU. Both bsd.rd from install79.iso and
> > miniroot79.img fail the same way, before the installer starts:
> >
> > fatal protection fault in supervisor mode
> > trap type 4 code 0 rip ... cs 8 rflags ... cr2 0 cpl e
> > panic: trap type 4, code=0, pc=...
> >
> > CPU as seen by a FreeBSD 15.1 guest on the same VM:
> >
> > Origin="AuthenticAMD" Id=0x800f12 Family=0x17 Model=0x1 Stepping=2
> > Features2=...<...,HV>
> > Hypervisor: Origin = "KVMKVMKVM"
> >
> > The hypervisor does not implement MSR_DE_CFG (0xc0011029). Reading it
> > from the FreeBSD guest faults:
> >
> > # cpucontrol -m 0xc0011029 /dev/cpuctl0
> > cpucontrol: ioctl(/dev/cpuctl0, CPUCTL_RDMSR (0xc0011029)): Bad address
> >
> > In cpu_init() (sys/arch/amd64/amd64/cpu.c), the "Mitigation G-2"
> > block reads MSR_DE_CFG unconditionally on all AMD families >= 10h
> > (except 11h). The two newer MSR blocks below it (Zenbleed and FPDSS)
> > already skip the access when CPUIDECX_HV is set, but the G-2 block
> > does not, so the unguarded rdmsr() raises #GP and the kernel panics.
> >
> > FreeBSD and Linux boot fine on the same VM, since they access this MSR
> > in a fault-tolerant way.
> >
> > The hoster declined to change the virtual CPU model.
> >
> > Note: the system information attached by sendbug is from a different
> > (working) machine, since OpenBSD cannot be booted on the affected VM.
> >
> > >How-To-Repeat:
> >
> > Boot bsd.rd (install79.iso or miniroot79.img, amd64) on a KVM guest
> > with an AMD family 17h CPU where the hypervisor does not provide
> > MSR_DE_CFG (0xc0011029), e.g. a 1blu.de "VPS R24" instance.
> > The kernel panics during CPU identification with trap type 4.
> >
> > Whether the MSR is available can be checked from another guest OS,
> > e.g. FreeBSD: cpucontrol -m 0xc0011029 /dev/cpuctl0
> >
> > >Fix:
> > Read MSR_DE_CFG with rdmsr_safe() so the mitigation is still applied
> > where the MSR is available (bare metal, or hypervisors that emulate
> > it) and is skipped where the access faults:
> >
> > File sys/arch/amd64/amd64/cpu.c
> >
> > * This MSR is available on all AMD families >= 10h, except 11h
> > * where LFENCE is always serializing.
> > + * Hypervisors may not implement it, so read it carefully.
> > */
> > - if (family >= 0x10 && family != 0x11) {
> > - nmsr = msr = rdmsr(MSR_DE_CFG);
> > - nmsr |= DE_CFG_SERIALIZE_LFENCE;
> > + if (family >= 0x10 && family != 0x11 &&
> > + rdmsr_safe(MSR_DE_CFG, &msr) == 0) {
> > + nmsr = msr | DE_CFG_SERIALIZE_LFENCE;
> > if (msr != nmsr)
> > wrmsr(MSR_DE_CFG, nmsr);
> > }
> >
> > An alternative would be to add a (cpu_ecxfeature & CPUIDECX_HV) == 0
> > check, as done for the Zenbleed and FPDSS blocks, but that would drop
> > the mitigation on hypervisors that do implement the MSR.
>
> The limited AMD documentation on mitigations does not mention
> hypervisors at all.
>
> It seems we can only assume hypervisors implement all workarounds.
> And don't implement most MSRs.
Thanks for the report, I've committed the diff below.
>
> Index: sys/arch/amd64/amd64/cpu.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/amd64/cpu.c,v
> diff -u -p -r1.207 cpu.c
> --- sys/arch/amd64/amd64/cpu.c 28 Sep 2026 04:50:24 -0000 1.207
> +++ sys/arch/amd64/amd64/cpu.c 1 Oct 2026 07:26:15 -0000
> @@ -1287,7 +1287,8 @@ cpu_fix_msrs(struct cpu_info *ci)
> * This MSR is available on all AMD families >= 10h, except 11h
> * where LFENCE is always serializing.
> */
> - if (family >= 0x10 && family != 0x11) {
> + if (family >= 0x10 && family != 0x11 &&
> + (cpu_ecxfeature & CPUIDECX_HV) == 0) {
> nmsr = msr = rdmsr(MSR_DE_CFG);
> nmsr |= DE_CFG_SERIALIZE_LFENCE;
> if (msr != nmsr)
> Index: sys/arch/i386/i386/machdep.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/i386/machdep.c,v
> diff -u -p -r1.680 machdep.c
> --- sys/arch/i386/i386/machdep.c 14 May 2026 01:39:38 -0000 1.680
> +++ sys/arch/i386/i386/machdep.c 1 Oct 2026 07:26:19 -0000
> @@ -2013,7 +2013,8 @@ identifycpu(struct cpu_info *ci)
> * where LFENCE is always serializing.
> */
> if (!strcmp(cpu_vendor, "AuthenticAMD")) {
> - if (ci->ci_family >= 0x10 && ci->ci_family != 0x11) {
> + if (ci->ci_family >= 0x10 && ci->ci_family != 0x11 &&
> + (cpu_ecxfeature & CPUIDECX_HV) == 0) {
> nmsr = msr = rdmsr(MSR_DE_CFG);
> nmsr |= DE_CFG_SERIALIZE_LFENCE;
> if (msr != nmsr)
>
>