From: Hans-Jörg Höxer Subject: SEV-ES: vmd(8): Initial state encryption for SEV-ES guests 2/2 To: Date: Wed, 21 May 2025 16:07:28 +0200 Hi, second bit for vmd(8): When launching a SEV-ES guest, we have to ask the psp(4) to initially encrypt the VMSA. Take care, HJ. -------------------------------------------------------------------------- commit 7678920aca8a51bc4c3ead181916e2036b46a8f3 Author: Hans-Joerg Hoexer Date: Wed Jun 5 18:59:26 2024 +0200 vmd(8): Initial state encryption for SEV-ES guests For SEV-ES enabled guest send the LAUNCH ENCRYPT STATE command to psp(4), so the VMSA gets encrypted. Refactor code of the launch protocol. diff --git a/usr.sbin/vmd/psp.c b/usr.sbin/vmd/psp.c index aa5a53bb4bd..da6c521f823 100644 --- a/usr.sbin/vmd/psp.c +++ b/usr.sbin/vmd/psp.c @@ -173,6 +173,27 @@ psp_launch_update(uint32_t handle, vaddr_t v, size_t len) * the PSP, the measurement is not really meaningful. Thus we just * log it for now. */ +int +psp_encrypt_state(uint32_t handle, uint32_t asid, uint32_t vmid, + uint32_t vcpuid) +{ + struct psp_encrypt_state es; + + memset(&es, 0, sizeof(es)); + es.handle = handle; + es.asid = asid; + es.vmid = vmid; + es.vcpuid = vcpuid; + + if (ioctl(env->vmd_psp_fd, PSP_IOC_ENCRYPT_STATE, &es) < 0) { + log_warn("%s: ioctl", __func__); + return (-1); + } + + return (0); +} + + int psp_launch_measure(uint32_t handle) { diff --git a/usr.sbin/vmd/sev.c b/usr.sbin/vmd/sev.c index 752bb37d163..c2add19bfd9 100644 --- a/usr.sbin/vmd/sev.c +++ b/usr.sbin/vmd/sev.c @@ -148,7 +148,6 @@ sev_encrypt_memory(struct vmd_vm *vm) struct vm_create_params *vcp = &vmc->vmc_params; struct vm_mem_range *vmr; size_t i; - uint8_t gstate; if (!vcp->vcp_sev) return (0); @@ -167,23 +166,6 @@ sev_encrypt_memory(struct vmd_vm *vm) log_debug("%s: encrypted %zu:0x%lx size 0x%lx", __func__, i, vmr->vmr_va, vmr->vmr_size); } - if (psp_launch_measure(vm->vm_sev_handle)) { - log_warnx("%s: failed to launch measure", __func__); - return (-1); - } - if (psp_launch_finish(vm->vm_sev_handle)) { - log_warnx("%s: failed to launch finish", __func__); - return (-1); - } - - if (psp_get_gstate(vm->vm_sev_handle, NULL, NULL, &gstate)) { - log_warnx("%s: failed to get guest state", __func__); - return (-1); - } - if (gstate != PSP_GSTATE_RUNNING) { - log_warnx("%s: invalid guest state: 0x%hx", __func__, gstate); - return (-1); - } return (0); } @@ -222,6 +204,57 @@ sev_activate(struct vmd_vm *vm, int vcpu_id) } +int +sev_encrypt_state(struct vmd_vm *vm, int vcpu_id) +{ + struct vmop_create_params *vmc = &vm->vm_params; + struct vm_create_params *vcp = &vmc->vmc_params; + + if (!vcp->vcp_seves) + return (0); + + if (psp_encrypt_state(vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id], + vcp->vcp_id, vcpu_id)) { + log_warnx("%s: failed to encrypt statet: 0x%x 0x%x 0x%0x 0x%0x", + __func__, vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id], + vm->vm_vmid, vcpu_id); + return (-1); + } + + return (0); +} + +int +sev_launch_finalize(struct vmd_vm *vm) +{ + struct vmop_create_params *vmc = &vm->vm_params; + struct vm_create_params *vcp = &vmc->vmc_params; + uint8_t gstate; + + if (!vcp->vcp_sev) + return (0); + + if (psp_launch_measure(vm->vm_sev_handle)) { + log_warnx("%s: failed to launch measure", __func__); + return (-1); + } + if (psp_launch_finish(vm->vm_sev_handle)) { + log_warnx("%s: failed to launch finish", __func__); + return (-1); + } + + if (psp_get_gstate(vm->vm_sev_handle, NULL, NULL, &gstate)) { + log_warnx("%s: failed to get guest state", __func__); + return (-1); + } + if (gstate != PSP_GSTATE_RUNNING) { + log_warnx("%s: invalid guest state: 0x%hx", __func__, gstate); + return (-1); + } + + return (0); +} + /* * Deactivate and decommission a guest's SEV crypto state. */ diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index a9429dbd21d..acba8c81755 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -895,6 +895,18 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg_state *vrs) } } + if (sev_encrypt_state(current_vm, i)) { + log_warnx("%s: state encryption failed for VCPU " + "%zu failed - exiting.", __progname, i); + return (EIO); + } + + if (sev_launch_finalize(current_vm)) { + log_warnx("%s: state encryption failed for VCPU " + "%zu failed - exiting.", __progname, i); + return (EIO); + } + ret = pthread_cond_init(&vcpu_run_cond[i], NULL); if (ret) { log_warnx("%s: cannot initialize cond var (%d)", diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index e0b7c27eb46..a8745e8a2a3 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -588,6 +588,7 @@ int psp_df_flush(void); int psp_get_gstate(uint32_t, uint32_t *, uint32_t *, uint8_t *); int psp_launch_start(uint32_t *, int); int psp_launch_update(uint32_t, vaddr_t, size_t); +int psp_encrypt_state(uint32_t, uint32_t, uint32_t, uint32_t); int psp_launch_measure(uint32_t); int psp_launch_finish(uint32_t); int psp_activate(uint32_t, uint32_t); @@ -599,6 +600,8 @@ int sev_init(struct vmd_vm *); int sev_register_encryption(vaddr_t, size_t); int sev_encrypt_memory(struct vmd_vm *); int sev_activate(struct vmd_vm *, int); +int sev_encrypt_state(struct vmd_vm *, int); +int sev_launch_finalize(struct vmd_vm *); int sev_shutdown(struct vmd_vm *); #endif /* VMD_H */