Download raw body.
SEV-ES: vmm(4): GHCB MSR protocol for CPUID
On Tue, May 20, 2025 at 02:05:28PM +0200, Hans-Jörg Höxer wrote:
> Hi,
>
> my last two diffs for vmm(4) and SEV-ES:
>
> When a SEV-ES guest is in locore, it will not be able yet to use a
> GHCB to communicate with vmm(4). Therefore, AMD specifies a "GHCB
> MSR protocol" that uses the lowere 12 bits of the GHCB MSR to request
> services from vmm(4). Guest writes to the GHCB MSR will show up in
> the v_ghcb_gpa member of the VMCB and are thus accesible by vmm(4).
> The response of vmm(4) can be provided by writing it to the VMCB.
>
> In locore a SEV-ES guest will need to request CPUID from vmm(4)
> using the GHCB MSR protocol. This diff provides this service.
>
> Take care,
> HJ.
>
Diff looks ok; one question though. Is the locore side of this diff still
coming or did that already go in? Eg, is there a corresponding change for
the guest to use the GHCB MSR protocol?
ok mlarkin in any case.
> ---------------------------------------------------------------------------
> commit 8278f4051b90ee94e19db25d019100a736ee7317
> Author: Hans-Joerg Hoexer <hshoexer@genua.de>
> Date: Mon Nov 18 13:59:19 2024 +0100
>
> vmm(4): GHCB MSR protocol for CPUID
>
> When a SEV-ES guest is in locore, it will not be able yet to use a
> GHCB to communicate with vmm(4). Therefore, AMD specifies a "GHCB
> MSR protocol" that uses the lowere 12 bits of the GHCB MSR to request
> services from vmm(4). Guest writes to the GHCB MSR will show up in
> the v_ghcb_gpa member of the VMCB and are thus accesible by vmm(4).
> The response of vmm(4) can be provided by writing it to the VMCB.
>
> In locore a SEV-ES guest will need to request CPUID from vmm(4)
> using the GHCB MSR protocol. This diff provides this service.
>
> diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c
> index 9049bc6340d..2e90b7340f2 100644
> --- a/sys/arch/amd64/amd64/vmm_machdep.c
> +++ b/sys/arch/amd64/amd64/vmm_machdep.c
> @@ -4514,13 +4514,67 @@ svm_handle_gexit(struct vcpu *vcpu)
> struct vm *vm = vcpu->vc_parent;
> struct ghcb_sa *ghcb;
> paddr_t ghcb_gpa, ghcb_hpa;
> + uint32_t req, resp;
> + uint64_t result;
> int syncout, error = 0;
>
> - if (vcpu->vc_svm_ghcb_va == 0) {
> + if (vcpu->vc_svm_ghcb_va == 0 && (vmcb->v_ghcb_gpa & ~PG_FRAME) == 0 &&
> + (vmcb->v_ghcb_gpa & PG_FRAME) != 0) {
> + /*
> + * Guest provides a valid guest physcial address
> + * for GHCB and it is not set yet -> assign it.
> + *
> + * We only accept a GHCB once; we decline re-definition.
> + */
> ghcb_gpa = vmcb->v_ghcb_gpa & PG_FRAME;
> if (!pmap_extract(vm->vm_map->pmap, ghcb_gpa, &ghcb_hpa))
> return (EINVAL);
> vcpu->vc_svm_ghcb_va = (vaddr_t)PMAP_DIRECT_MAP(ghcb_hpa);
> + } else if ((vmcb->v_ghcb_gpa & ~PG_FRAME) != 0) {
> + /*
> + * Low bits in use, thus must be a MSR protocol
> + * request.
> + */
> + req = (vmcb->v_ghcb_gpa & 0xffffffff);
> +
> + /* we only support cpuid */
> + if ((req & ~PG_FRAME) != MSR_PROTO_CPUID_REQ)
> + return (EINVAL);
> +
> + /* Emulate CPUID */
> + vmcb->v_exitcode = SVM_VMEXIT_CPUID;
> + vmcb->v_rax = vmcb->v_ghcb_gpa >> 32;
> + vcpu->vc_gueststate.vg_rax = 0;
> + vcpu->vc_gueststate.vg_rbx = 0;
> + vcpu->vc_gueststate.vg_rcx = 0;
> + vcpu->vc_gueststate.vg_rdx = 0;
> + error = vmm_handle_cpuid(vcpu);
> + if (error)
> + goto out;
> +
> + switch (req >> 30) {
> + case 0: /* eax: emulate cpuid and return eax */
> + result = vmcb->v_rax;
> + break;
> + case 1: /* return ebx */
> + result = vcpu->vc_gueststate.vg_rbx;
> + break;
> + case 2: /* return ecx */
> + result = vcpu->vc_gueststate.vg_rcx;
> + break;
> + case 3: /* return edx */
> + result = vcpu->vc_gueststate.vg_rdx;
> + break;
> + default:
> + DPRINTF("%s: unknown request 0x%x\n", __func__, req);
> + return (EINVAL);
> + }
> +
> + /* build response */
> + resp = MSR_PROTO_CPUID_RESP | (req & 0xc0000000);
> + vmcb->v_ghcb_gpa = (result << 32) | resp;
> +
> + return (0);
> }
>
> /* Verify GHCB and synchronize guest state information. */
> diff --git a/sys/arch/amd64/include/ghcb.h b/sys/arch/amd64/include/ghcb.h
> index 802bf7f015e..954e1fa3e3b 100644
> --- a/sys/arch/amd64/include/ghcb.h
> +++ b/sys/arch/amd64/include/ghcb.h
> @@ -101,6 +101,12 @@ struct ghcb_sync {
> };
>
>
> +/* Definitions used with the MSR protocol */
> +#define MSR_PROTO_CPUID_REQ 0x4
> +#define MSR_PROTO_CPUID_RESP 0x5
> +#define MSR_PROTO_TERMINATE 0x100
> +
> +
> void ghcb_clear(struct ghcb_sa *);
> int ghcb_valbm_set(uint8_t *, int);
> int ghcb_valbm_isset(uint8_t *, int);
SEV-ES: vmm(4): GHCB MSR protocol for CPUID