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)
> 
> 

Reply via email to