Download raw body.
SEV-ES: vmd(8): Initial state encryption for SEV-ES guests 2/2
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 <hshoexer@genua.de>
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 */
SEV-ES: vmd(8): Initial state encryption for SEV-ES guests 2/2