CVSROOT: /cvs
Module name: src
Changes by: [email protected] 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@