From: Hans-Jörg Höxer Subject: SEV-ES: psp(4): VMSA launch update and encryption To: Cc: Date: Tue, 15 Apr 2025 15:12:36 +0200 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 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 #include +#include #include #include @@ -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