CVSROOT:        /cvs
Module name:    src
Changes by:     bl...@cvs.openbsd.org   2025/06/23 05:33:39

Modified files:
        sys/arch/amd64/amd64: locore0.S 
        sys/arch/amd64/include: ghcb.h trap.h vmmvar.h 

Log message:
In locore0 handle #VC trap for AMD SEV-ES guest.

When locore is executed by a SEV-ES enabled guest, the first CPUID
instruction will raise a #VC trap that must be handled.  However,
at that point in time the guest does not know whether it is a guest
at all, if it is running on an AMD CPU, if SEV-ES is enabled, etc.

To resolve this chicken-egg situation, undconditionally setup a #VC
trap handler.  If we are not a SEV-ES enabled guest, or we are
running on some non-AMD CPU, it will not raise #VC (hopefully).  On
Intel CPUs the vector for #VC is reserved.

As vmd(8) configures the runtime for locore0 to be in 32 bit
compatibility mode, a raised #VC exception will switch to long mode.
Then the CPU will expect a 64 bit entry in the IDT.  When running
on KVM/qemu, locore0 is execute in 32 bit legacy mode.  There the
CPU will expect a 32 bit entry in the IDT.  To accommodate both
situations, set up both 64 and 32 bit handler in the IDT.
Additionally, vmd(8) has to setup a long mode segment in the GDT.

Both #VC trap handler use the MSR protocol to talk to the hypervisor
to emulate CPUID.  The MSR protocol only supports "simple" CPUID
without subfunctions.

Note: When SEV-ES is enabled, the hypervisor can not intercept
writes to EFER beforehand, only after the write.  Thus on vmm(4)
with directly executed kernel, we are in compatibility mode and
EFER_LMA is set.  As resetting EFER_LMA raises #GP, we have to
preserve it.

from hshoexer@; OK mlarkin@

Reply via email to