Index | Thread | Search

From:
Hans-Jörg Höxer <hshoexer@genua.de>
Subject:
SEV-ES: psp(4): VMSA launch update and encryption
To:
<tech@openbsd.org>
Cc:
<Hans-Joerg_Hoexer@genua.de>
Date:
Tue, 15 Apr 2025 15:12:36 +0200

Download raw body.

Thread
  • Hans-Jörg Höxer:

    SEV-ES: psp(4): VMSA launch update and encryption

Hi,

this diff implements the functions needed for launch updating and
encrypting the VMSA.  This will be used by vmd(8) when launching SEV-ES
enabled VMs.

Comments?

Take care,
HJ.
--------------------------------------------------------------------------
commit 4961fb2dd6d59933c77d3e129c9e4eca5a256721
Author: Hans-Joerg Hoexer <hshoexer@genua.de>
Date:   Wed Jun 5 12:45:31 2024 +0200

    psp: add psp_encrypt_state() and psp_launch_update_vmsa()
    
    When launching a SEV-ES enabled VM, vmd(8) will have to encrypt the
    initial state of the vCPU in the VMSA allocated by vmm(4).  And the
    VMSA has to be measure by the PSP.  Provided functions for this.

diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c
index bd991481062..995c05571d6 100644
--- a/sys/dev/ic/psp.c
+++ b/sys/dev/ic/psp.c
@@ -29,6 +29,7 @@
 
 #include <uvm/uvm_extern.h>
 #include <crypto/xform.h>
+#include <machine/vmmvar.h>
 
 #include <dev/ic/ccpvar.h>
 #include <dev/ic/pspvar.h>
@@ -537,6 +538,32 @@ out:
 	return (error);
 }
 
+int
+psp_launch_update_vmsa(struct psp_softc *sc,
+    struct psp_launch_update_vmsa *uluv)
+{
+	struct psp_launch_update_vmsa	*luvmsa;
+	int				 error;
+
+	luvmsa = (struct psp_launch_update_vmsa *)sc->sc_cmd_kva;
+	bzero(luvmsa, sizeof(*luvmsa));
+
+	luvmsa->handle = uluv->handle;
+	luvmsa->paddr = uluv->paddr;
+	luvmsa->length = PAGE_SIZE;
+
+	/* Drain caches before we encrypt the VMSA. */
+	wbinvd_on_all_cpus_acked();
+
+	error = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_VMSA,
+	    sc->sc_cmd_map->dm_segs[0].ds_addr);
+
+	if (error != 0)
+		return (EIO);
+
+	return (0);
+}
+
 int
 psp_launch_measure(struct psp_softc *sc, struct psp_launch_measure *ulm)
 {
@@ -633,6 +660,26 @@ psp_activate(struct psp_softc *sc, struct psp_activate *uact)
 	return (error);
 }
 
+int
+psp_encrypt_state(struct psp_softc *sc, struct psp_encrypt_state *ues)
+{
+	struct psp_launch_update_vmsa	luvmsa;
+	uint64_t			vmsa_paddr;
+	int				error;
+
+	error = svm_get_vmsa_pa(ues->vmid, ues->vcpuid, &vmsa_paddr);
+	if (error != 0)
+		return (error);
+
+	bzero(&luvmsa, sizeof(luvmsa));
+	luvmsa.handle = ues->handle;
+	luvmsa.paddr = vmsa_paddr;
+
+	error = psp_launch_update_vmsa(sc, &luvmsa);
+
+	return (error);
+}
+
 int
 psp_deactivate(struct psp_softc *sc, struct psp_deactivate *udeact)
 {
@@ -838,6 +885,9 @@ pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 		error = psp_snp_get_pstatus(sc,
 		    (struct psp_snp_platform_status *)data);
 		break;
+	case PSP_IOC_ENCRYPT_STATE:
+		error = psp_encrypt_state(sc, (struct psp_encrypt_state *)data);
+		break;
 	default:
 		error = ENOTTY;
 		break;
@@ -862,6 +912,7 @@ pledge_ioctl_psp(struct proc *p, long com)
 	case PSP_IOC_LAUNCH_MEASURE:
 	case PSP_IOC_LAUNCH_FINISH:
 	case PSP_IOC_ACTIVATE:
+	case PSP_IOC_ENCRYPT_STATE:
 	case PSP_IOC_GUEST_SHUTDOWN:
 		return (0);
 	default:
diff --git a/sys/dev/ic/pspvar.h b/sys/dev/ic/pspvar.h
index fa36a3a90db..f73dbdffb8f 100644
--- a/sys/dev/ic/pspvar.h
+++ b/sys/dev/ic/pspvar.h
@@ -86,6 +86,7 @@
 #define PSP_CMD_GUESTSTATUS		0x23
 #define PSP_CMD_LAUNCH_START		0x30
 #define PSP_CMD_LAUNCH_UPDATE_DATA	0x31
+#define PSP_CMD_LAUNCH_UPDATE_VMSA	0x32
 #define PSP_CMD_LAUNCH_MEASURE		0x33
 #define PSP_CMD_LAUNCH_FINISH		0x35
 #define PSP_CMD_ATTESTATION		0x36
@@ -133,6 +134,24 @@ struct psp_launch_update_data {
 	uint32_t		length;
 } __packed;
 
+struct psp_launch_update_vmsa {
+	/* Input parameters for PSP_CMD_LAUNCH_UPDATE_VMSA */
+	uint32_t		handle;
+	uint32_t		reserved;
+	uint64_t		paddr;
+	uint32_t		length;
+} __packed;
+
+struct psp_encrypt_state {
+	/*
+         * Input parameters state encryption
+	 */
+	uint32_t		handle;
+	uint32_t		asid;
+	uint32_t		vmid;
+	uint32_t		vcpuid;
+} __packed;
+
 struct psp_measure {
 	/* Output buffer for PSP_CMD_LAUNCH_MEASURE */
 	uint8_t			measure[32];
@@ -258,6 +277,7 @@ struct psp_snp_platform_status {
 #define PSP_IOC_SNP_GET_PSTATUS	_IOR('P', 11, struct psp_snp_platform_status)
 #define PSP_IOC_INIT		_IO('P', 12)
 #define PSP_IOC_SHUTDOWN	_IO('P', 13)
+#define PSP_IOC_ENCRYPT_STATE	_IOW('P', 254, struct psp_encrypt_state)
 #define PSP_IOC_GUEST_SHUTDOWN	_IOW('P', 255, struct psp_guest_shutdown)
 
 #ifdef _KERNEL