diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2024-09-03 00:23:06 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2024-09-03 00:23:06 +0000 |
commit | 78ff80b8c4b191df6400b4889ddcb86d47422c16 (patch) | |
tree | aa7d31ef4b658f0125f1e7b27e10475a4a63a8a5 /sys | |
parent | e123c83c6ef63eea0e754d6cfabba302dd802f5f (diff) |
move psp functions to psp.c and remove the ifdefs
ok bluhm@ hshoexer@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/conf/files.amd64 | 4 | ||||
-rw-r--r-- | sys/dev/ic/ccp.c | 644 | ||||
-rw-r--r-- | sys/dev/ic/ccpvar.h | 249 | ||||
-rw-r--r-- | sys/dev/ic/psp.c | 659 | ||||
-rw-r--r-- | sys/dev/ic/pspvar.h | 255 | ||||
-rw-r--r-- | sys/dev/pci/ccp_pci.c | 9 |
6 files changed, 922 insertions, 898 deletions
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index a3452d9729c..0325062efb6 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.amd64,v 1.109 2023/07/08 08:01:10 tobhe Exp $ +# $OpenBSD: files.amd64,v 1.110 2024/09/03 00:23:05 jsg Exp $ maxpartitions 16 maxusers 2 16 128 @@ -65,6 +65,8 @@ file arch/amd64/amd64/powernow-k8.c !small_kernel file arch/amd64/amd64/est.c !small_kernel file arch/amd64/amd64/k1x-pstate.c !small_kernel +file dev/ic/psp.c ccp + include "dev/rasops/files.rasops" include "dev/wsfont/files.wsfont" diff --git a/sys/dev/ic/ccp.c b/sys/dev/ic/ccp.c index 42ae5f8e7c2..024291c86cc 100644 --- a/sys/dev/ic/ccp.c +++ b/sys/dev/ic/ccp.c @@ -1,8 +1,7 @@ -/* $OpenBSD: ccp.c,v 1.9 2024/09/01 19:25:06 bluhm Exp $ */ +/* $OpenBSD: ccp.c,v 1.10 2024/09/03 00:23:05 jsg Exp $ */ /* * Copyright (c) 2018 David Gwynne <dlg@openbsd.org> - * Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,21 +18,11 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/buf.h> #include <sys/device.h> -#include <sys/malloc.h> -#include <sys/kernel.h> #include <sys/timeout.h> -#include <sys/pledge.h> #include <machine/bus.h> -#ifdef __amd64__ -#include <sys/proc.h> -#include <uvm/uvm.h> -#include <crypto/xform.h> -#endif - #include <dev/ic/ccpvar.h> #define CCP_REG_TRNG 0xc @@ -46,13 +35,6 @@ struct cfdriver ccp_cd = { DV_DULL }; -#ifdef __amd64__ -struct ccp_softc *ccp_softc; - -int psp_get_pstatus(struct psp_platform_status *); -int psp_init(struct psp_init *); -#endif - void ccp_attach(struct ccp_softc *sc) { @@ -77,627 +59,3 @@ ccp_rng(void *arg) timeout_add_msec(&sc->sc_tick, 100); } - -#ifdef __amd64__ -int -psp_sev_intr(struct ccp_softc *sc, uint32_t status) -{ - if (!(status & PSP_CMDRESP_COMPLETE)) - return (0); - - wakeup(sc); - - return (1); -} - -int -psp_attach(struct ccp_softc *sc) -{ - struct psp_platform_status pst; - struct psp_init init; - size_t size; - int nsegs; - - if (!(sc->sc_capabilities & PSP_CAP_SEV)) - return (0); - - rw_init(&sc->sc_lock, "ccp_lock"); - - /* create and map SEV command buffer */ - sc->sc_cmd_size = size = PAGE_SIZE; - if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, - BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, - &sc->sc_cmd_map) != 0) - return (0); - - if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1, - &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) - goto fail_0; - - if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size, - &sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0) - goto fail_1; - - if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva, - size, NULL, BUS_DMA_WAITOK) != 0) - goto fail_2; - - sc->sc_sev_intr = psp_sev_intr; - ccp_softc = sc; - - if (psp_get_pstatus(&pst) || pst.state != 0) - goto fail_3; - - /* - * create and map Trusted Memory Region (TMR); size 1 Mbyte, - * needs to be aligned to 1 Mbyte. - */ - sc->sc_tmr_size = size = PSP_TMR_SIZE; - if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, - BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, - &sc->sc_tmr_map) != 0) - goto fail_3; - - if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1, - &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) - goto fail_4; - - if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size, - &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0) - goto fail_5; - - if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva, - size, NULL, BUS_DMA_WAITOK) != 0) - goto fail_6; - - memset(&init, 0, sizeof(init)); - init.enable_es = 1; - init.tmr_length = PSP_TMR_SIZE; - init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr; - if (psp_init(&init)) - goto fail_7; - - printf(", SEV"); - - psp_get_pstatus(&pst); - if ((pst.state == 1) && (pst.cfges_build & 0x1)) - printf(", SEV-ES"); - - sc->sc_psp_attached = 1; - - return (1); - -fail_7: - bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map); -fail_6: - bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size); -fail_5: - bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1); -fail_4: - bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map); -fail_3: - bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map); -fail_2: - bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size); -fail_1: - bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1); -fail_0: - bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map); - - ccp_softc = NULL; - sc->sc_psp_attached = -1; - - return (0); -} - -static int -ccp_wait(struct ccp_softc *sc, uint32_t *status, int poll) -{ - uint32_t cmdword; - int count; - - if (poll) { - count = 0; - while (count++ < 10) { - cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - PSP_REG_CMDRESP); - if (cmdword & PSP_CMDRESP_RESPONSE) - goto done; - delay(5000); - } - - /* timeout */ - return (1); - } - - if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(1)) == EWOULDBLOCK) - return (1); - -done: - if (status) { - *status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - PSP_REG_CMDRESP); - } - - return (0); -} - -static int -ccp_docmd(struct ccp_softc *sc, int cmd, uint64_t paddr) -{ - uint32_t plo, phi, cmdword, status; - - plo = ((paddr >> 0) & 0xffffffff); - phi = ((paddr >> 32) & 0xffffffff); - cmdword = (cmd & 0x3ff) << 16; - if (!cold) - cmdword |= PSP_CMDRESP_IOC; - - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRLO, plo); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRHI, phi); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_CMDRESP, cmdword); - - if (ccp_wait(sc, &status, cold)) - return (1); - - /* Did PSP sent a response code? */ - if (status & PSP_CMDRESP_RESPONSE) { - if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS) - return (1); - } - - return (0); -} - -int -psp_init(struct psp_init *uinit) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_init *init; - int ret; - - init = (struct psp_init *)sc->sc_cmd_kva; - bzero(init, sizeof(*init)); - - init->enable_es = uinit->enable_es; - init->tmr_paddr = uinit->tmr_paddr; - init->tmr_length = uinit->tmr_length; - - ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr); - if (ret != 0) - return (EIO); - - wbinvd_on_all_cpus(); - - return (0); -} - -int -psp_get_pstatus(struct psp_platform_status *ustatus) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_platform_status *status; - int ret; - - status = (struct psp_platform_status *)sc->sc_cmd_kva; - bzero(status, sizeof(*status)); - - ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - bcopy(status, ustatus, sizeof(*ustatus)); - - return (0); -} - -int -psp_df_flush(void) -{ - struct ccp_softc *sc = ccp_softc; - int ret; - - wbinvd_on_all_cpus(); - - ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0); - - if (ret != 0) - return (EIO); - - return (0); -} - -int -psp_decommission(struct psp_decommission *udecom) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_decommission *decom; - int ret; - - decom = (struct psp_decommission *)sc->sc_cmd_kva; - bzero(decom, sizeof(*decom)); - - decom->handle = udecom->handle; - - ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - return (0); -} - -int -psp_get_gstatus(struct psp_guest_status *ustatus) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_guest_status *status; - int ret; - - status = (struct psp_guest_status *)sc->sc_cmd_kva; - bzero(status, sizeof(*status)); - - status->handle = ustatus->handle; - - ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - ustatus->policy = status->policy; - ustatus->asid = status->asid; - ustatus->state = status->state; - - return (0); -} - -int -psp_launch_start(struct psp_launch_start *ustart) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_launch_start *start; - int ret; - - start = (struct psp_launch_start *)sc->sc_cmd_kva; - bzero(start, sizeof(*start)); - - start->handle = ustart->handle; - start->policy = ustart->policy; - - ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - /* If requested, return new handle. */ - if (ustart->handle == 0) - ustart->handle = start->handle; - - return (0); -} - -int -psp_launch_update_data(struct psp_launch_update_data *ulud, struct proc *p) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_launch_update_data *ludata; - pmap_t pmap; - vaddr_t v, next, end; - size_t size, len, off; - int ret; - - /* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */ - if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 || - (ulud->length % AES_XTS_BLOCKSIZE) != 0) - return (EINVAL); - - ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva; - bzero(ludata, sizeof(*ludata)); - - ludata->handle = ulud->handle; - - /* Drain caches before we encrypt memory. */ - wbinvd_on_all_cpus(); - - /* - * Launch update one physical page at a time. We could - * optimise this for contiguous pages of physical memory. - * - * vmd(8) provides the guest physical address, thus convert - * to system physical address. - */ - pmap = vm_map_pmap(&p->p_vmspace->vm_map); - size = ulud->length; - end = ulud->paddr + ulud->length; - for (v = ulud->paddr; v < end; v = next) { - off = v & PAGE_MASK; - - len = MIN(PAGE_SIZE - off, size); - - /* Wire mapping. */ - if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0)) - return (EINVAL); - if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr)) - return (EINVAL); - ludata->length = len; - - ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - size -= len; - next = v + len; - } - - return (0); -} - -int -psp_launch_measure(struct psp_launch_measure *ulm) -{ - struct psp_launch_measure *lm; - struct ccp_softc *sc = ccp_softc; - int ret; - uint64_t paddr; - - if (ulm->measure_len != sizeof(ulm->psp_measure)) - return (EINVAL); - - lm = (struct psp_launch_measure *)sc->sc_cmd_kva; - bzero(lm, sizeof(*lm)); - - lm->handle = ulm->handle; - paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; - lm->measure_paddr = - paddr + offsetof(struct psp_launch_measure, psp_measure); - lm->measure_len = sizeof(lm->psp_measure); - - ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr); - - if (ret != 0 || lm->measure_len != ulm->measure_len) - return (EIO); - - bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len); - - return (0); -} - -int -psp_launch_finish(struct psp_launch_finish *ulf) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_launch_finish *lf; - int ret; - - lf = (struct psp_launch_finish *)sc->sc_cmd_kva; - bzero(lf, sizeof(*lf)); - - lf->handle = ulf->handle; - - ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - return (0); -} - -int -psp_attestation(struct psp_attestation *uat) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_attestation *at; - int ret; - uint64_t paddr; - - if (uat->attest_len != sizeof(uat->psp_report)) - return (EINVAL); - - at = (struct psp_attestation *)sc->sc_cmd_kva; - bzero(at, sizeof(*at)); - - at->handle = uat->handle; - paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; - at->attest_paddr = - paddr + offsetof(struct psp_attestation, psp_report); - bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce)); - at->attest_len = sizeof(at->psp_report); - - ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr); - - if (ret != 0 || at->attest_len != uat->attest_len) - return (EIO); - - bcopy(&at->psp_report, &uat->psp_report, uat->attest_len); - - return (0); -} - -int -psp_activate(struct psp_activate *uact) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_activate *act; - int ret; - - act = (struct psp_activate *)sc->sc_cmd_kva; - bzero(act, sizeof(*act)); - - act->handle = uact->handle; - act->asid = uact->asid; - - ret = ccp_docmd(sc, PSP_CMD_ACTIVATE, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - return (0); -} - -int -psp_deactivate(struct psp_deactivate *udeact) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_deactivate *deact; - int ret; - - deact = (struct psp_deactivate *)sc->sc_cmd_kva; - bzero(deact, sizeof(*deact)); - - deact->handle = udeact->handle; - - ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - return (0); -} - -int -psp_guest_shutdown(struct psp_guest_shutdown *ugshutdown) -{ - struct psp_deactivate deact; - struct psp_decommission decom; - int ret; - - bzero(&deact, sizeof(deact)); - deact.handle = ugshutdown->handle; - if ((ret = psp_deactivate(&deact)) != 0) - return (ret); - - if ((ret = psp_df_flush()) != 0) - return (ret); - - bzero(&decom, sizeof(decom)); - decom.handle = ugshutdown->handle; - if ((ret = psp_decommission(&decom)) != 0) - return (ret); - - return (0); -} - -int -psp_snp_get_pstatus(struct psp_snp_platform_status *ustatus) -{ - struct ccp_softc *sc = ccp_softc; - struct psp_snp_platform_status *status; - int ret; - - status = (struct psp_snp_platform_status *)sc->sc_cmd_kva; - bzero(status, sizeof(*status)); - - ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS, - sc->sc_cmd_map->dm_segs[0].ds_addr); - - if (ret != 0) - return (EIO); - - bcopy(status, ustatus, sizeof(*ustatus)); - - return (0); -} - -int -pspopen(dev_t dev, int flag, int mode, struct proc *p) -{ - if (ccp_softc == NULL) - return (ENODEV); - - return (0); -} - -int -pspclose(dev_t dev, int flag, int mode, struct proc *p) -{ - return (0); -} - -int -pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) -{ - int ret; - - rw_enter_write(&ccp_softc->sc_lock); - - switch (cmd) { - case PSP_IOC_GET_PSTATUS: - ret = psp_get_pstatus((struct psp_platform_status *)data); - break; - case PSP_IOC_DF_FLUSH: - ret = psp_df_flush(); - break; - case PSP_IOC_DECOMMISSION: - ret = psp_decommission((struct psp_decommission *)data); - break; - case PSP_IOC_GET_GSTATUS: - ret = psp_get_gstatus((struct psp_guest_status *)data); - break; - case PSP_IOC_LAUNCH_START: - ret = psp_launch_start((struct psp_launch_start *)data); - break; - case PSP_IOC_LAUNCH_UPDATE_DATA: - ret = psp_launch_update_data( - (struct psp_launch_update_data *)data, p); - break; - case PSP_IOC_LAUNCH_MEASURE: - ret = psp_launch_measure((struct psp_launch_measure *)data); - break; - case PSP_IOC_LAUNCH_FINISH: - ret = psp_launch_finish((struct psp_launch_finish *)data); - break; - case PSP_IOC_ATTESTATION: - ret = psp_attestation((struct psp_attestation *)data); - break; - case PSP_IOC_ACTIVATE: - ret = psp_activate((struct psp_activate *)data); - break; - case PSP_IOC_DEACTIVATE: - ret = psp_deactivate((struct psp_deactivate *)data); - break; - case PSP_IOC_GUEST_SHUTDOWN: - ret = psp_guest_shutdown((struct psp_guest_shutdown *)data); - break; - case PSP_IOC_SNP_GET_PSTATUS: - ret = - psp_snp_get_pstatus((struct psp_snp_platform_status *)data); - break; - default: - ret = ENOTTY; - break; - } - - rw_exit_write(&ccp_softc->sc_lock); - - return (ret); -} - -int -pledge_ioctl_psp(struct proc *p, long com) -{ - switch (com) { - case PSP_IOC_GET_PSTATUS: - case PSP_IOC_DF_FLUSH: - case PSP_IOC_GET_GSTATUS: - case PSP_IOC_LAUNCH_START: - case PSP_IOC_LAUNCH_UPDATE_DATA: - case PSP_IOC_LAUNCH_MEASURE: - case PSP_IOC_LAUNCH_FINISH: - case PSP_IOC_ACTIVATE: - case PSP_IOC_GUEST_SHUTDOWN: - return (0); - default: - return (pledge_fail(p, EPERM, PLEDGE_VMM)); - } -} -#endif /* __amd64__ */ diff --git a/sys/dev/ic/ccpvar.h b/sys/dev/ic/ccpvar.h index 7add1e0a46e..59fb2e9e613 100644 --- a/sys/dev/ic/ccpvar.h +++ b/sys/dev/ic/ccpvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ccpvar.h,v 1.4 2024/09/01 19:25:06 bluhm Exp $ */ +/* $OpenBSD: ccpvar.h,v 1.5 2024/09/03 00:23:05 jsg Exp $ */ /* * Copyright (c) 2018 David Gwynne <dlg@openbsd.org> @@ -18,6 +18,7 @@ */ #include <sys/timeout.h> +#include <sys/rwlock.h> struct ccp_softc { struct device sc_dev; @@ -28,7 +29,6 @@ struct ccp_softc { int sc_psp_attached; -#ifdef __amd64__ bus_dma_tag_t sc_dmat; uint32_t sc_capabilities; int (*sc_sev_intr)(struct ccp_softc *, uint32_t); @@ -45,251 +45,6 @@ struct ccp_softc { caddr_t sc_tmr_kva; struct rwlock sc_lock; -#endif }; -#ifdef __amd64__ - -#include <sys/ioctl.h> -#include <sys/rwlock.h> - -/* AMD 17h */ -#define PSP_REG_INTEN 0x10690 -#define PSP_REG_INTSTS 0x10694 -#define PSP_REG_CMDRESP 0x10980 -#define PSP_REG_ADDRLO 0x109e0 -#define PSP_REG_ADDRHI 0x109e4 -#define PSP_REG_CAPABILITIES 0x109fc - -#define PSP_PSTATE_UNINIT 0x0 -#define PSP_PSTATE_INIT 0x1 -#define PSP_PSTATE_WORKING 0x2 - -#define PSP_GSTATE_UNINIT 0x0 -#define PSP_GSTATE_LUPDATE 0x1 -#define PSP_GSTATE_LSECRET 0x2 -#define PSP_GSTATE_RUNNING 0x3 -#define PSP_GSTATE_SUPDATE 0x4 -#define PSP_GSTATE_RUPDATE 0x5 -#define PSP_GSTATE_SENT 0x6 - -#define PSP_CAP_SEV (1 << 0) -#define PSP_CAP_TEE (1 << 1) -#define PSP_CAP_DBC_THRU_EXT (1 << 2) -#define PSP_CAP_SECURITY_REPORTING (1 << 7) -#define PSP_CAP_SECURITY_FUSED_PART (1 << 8) -#define PSP_CAP_SECURITY_DEBUG_LOCK_ON (1 << 10) -#define PSP_CAP_SECURITY_TSME_STATUS (1 << 13) -#define PSP_CAP_SECURITY_ANTI_ROLLBACK_STATUS (1 << 15) -#define PSP_CAP_SECURITY_RPMC_PRODUCTION_ENABLED (1 << 16) -#define PSP_CAP_SECURITY_RPMC_SPIROM_AVAILABLE (1 << 17) -#define PSP_CAP_SECURITY_HSP_TPM_AVAILABLE (1 << 18) -#define PSP_CAP_SECURITY_ROM_ARMOR_ENFORCED (1 << 19) - -#define PSP_CAP_BITS "\20\001SEV\002TEE\003DBC_THRU_EXT\010REPORTING\011FUSED_PART\013DEBUG_LOCK_ON\016TSME_STATUS\020ANTI_ROLLBACK_STATUS\021RPMC_PRODUCTION_ENABLED\022RPMC_SPIROM_AVAILABLE\023HSP_TPM_AVAILABLE\024ROM_ARMOR_ENFORCED" - -#define PSP_CMDRESP_IOC (1 << 0) -#define PSP_CMDRESP_COMPLETE (1 << 1) -#define PSP_CMDRESP_RESPONSE (1 << 31) - -#define PSP_STATUS_MASK 0xffff -#define PSP_STATUS_SUCCESS 0x0000 -#define PSP_STATUS_INVALID_PLATFORM_STATE 0x0001 - -#define PSP_TMR_SIZE (1024*1024) /* 1 Mb */ - -#define PSP_SUCCESS 0x0000 -#define PSP_INVALID_ADDRESS 0x0009 - -/* Selection of PSP commands of the SEV API Version 0.24 */ - -#define PSP_CMD_INIT 0x1 -#define PSP_CMD_PLATFORMSTATUS 0x4 -#define PSP_CMD_DF_FLUSH 0xa -#define PSP_CMD_DECOMMISSION 0x20 -#define PSP_CMD_ACTIVATE 0x21 -#define PSP_CMD_DEACTIVATE 0x22 -#define PSP_CMD_GUESTSTATUS 0x23 -#define PSP_CMD_LAUNCH_START 0x30 -#define PSP_CMD_LAUNCH_UPDATE_DATA 0x31 -#define PSP_CMD_LAUNCH_MEASURE 0x33 -#define PSP_CMD_LAUNCH_FINISH 0x35 -#define PSP_CMD_ATTESTATION 0x36 - -struct psp_platform_status { - /* Output parameters from PSP_CMD_PLATFORMSTATUS */ - uint8_t api_major; - uint8_t api_minor; - uint8_t state; - uint8_t owner; - uint32_t cfges_build; - uint32_t guest_count; -} __packed; - -struct psp_guest_status { - /* Input parameter for PSP_CMD_GUESTSTATUS */ - uint32_t handle; - - /* Output parameters from PSP_CMD_GUESTSTATUS */ - uint32_t policy; - uint32_t asid; - uint8_t state; -} __packed; - -struct psp_launch_start { - /* Input/Output parameter for PSP_CMD_LAUNCH_START */ - uint32_t handle; - - /* Input parameters for PSP_CMD_LAUNCH_START */ - uint32_t policy; - - /* The following input parameters are not used yet */ - uint64_t dh_cert_paddr; - uint32_t dh_cert_len; - uint32_t reserved; - uint64_t session_paddr; - uint32_t session_len; -} __packed; - -struct psp_launch_update_data { - /* Input parameters for PSP_CMD_LAUNCH_UPDATE_DATA */ - uint32_t handle; - uint32_t reserved; - uint64_t paddr; - uint32_t length; -} __packed; - -struct psp_measure { - /* Output buffer for PSP_CMD_LAUNCH_MEASURE */ - uint8_t measure[32]; - uint8_t measure_nonce[16]; -} __packed; - -struct psp_launch_measure { - /* Input parameters for PSP_CMD_LAUNCH_MEASURE */ - uint32_t handle; - uint32_t reserved; - uint64_t measure_paddr; - - /* Input/output parameter for PSP_CMD_LAUNCH_MEASURE */ - uint32_t measure_len; - uint32_t padding; - - /* Output buffer from PSP_CMD_LAUNCH_MEASURE */ - struct psp_measure psp_measure; /* 64bit aligned */ -#define measure psp_measure.measure -#define measure_nonce psp_measure.measure_nonce -} __packed; - -struct psp_launch_finish { - /* Input parameter for PSP_CMD_LAUNCH_FINISH */ - uint32_t handle; -} __packed; - -struct psp_report { - /* Output buffer for PSP_CMD_ATTESTATION */ - uint8_t report_nonce[16]; - uint8_t report_launch_digest[32]; - uint32_t report_policy; - uint32_t report_sig_usage; - uint32_t report_sig_algo; - uint32_t reserved2; - uint8_t report_sig1[144]; -} __packed; - -struct psp_attestation { - /* Input parameters for PSP_CMD_ATTESTATION */ - uint32_t handle; - uint32_t reserved; - uint64_t attest_paddr; - uint8_t attest_nonce[16]; - - /* Input/output parameter from PSP_CMD_ATTESTATION */ - uint32_t attest_len; - uint32_t padding; - - /* Output parameter from PSP_CMD_ATTESTATION */ - struct psp_report psp_report; /* 64bit aligned */ -#define report_nonce psp_report.report_nonce -#define report_launch_digest psp_report.report_launch_digest -#define report_policy psp_report.report_policy -#define report_sig_usage psp_report.report_sig_usage; -#define report_report_sig_alg psp_report.report_sig_algo; -#define report_report_sig1 psp_report.report_sig1; -} __packed; - -struct psp_activate { - /* Input parameters for PSP_CMD_ACTIVATE */ - uint32_t handle; - uint32_t asid; -} __packed; - -struct psp_deactivate { - /* Input parameter for PSP_CMD_DEACTIVATE */ - uint32_t handle; -} __packed; - -struct psp_decommission { - /* Input parameter for PSP_CMD_DECOMMISSION */ - uint32_t handle; -} __packed; - -struct psp_init { - /* Output parameters from PSP_CMD_INIT */ - uint32_t enable_es; - uint32_t reserved; - uint64_t tmr_paddr; - uint32_t tmr_length; -} __packed; - - -struct psp_guest_shutdown { - /* Input parameter for PSP_CMD_GUEST_SHUTDOWN */ - uint32_t handle; -} __packed; - -/* Selection of PSP commands of the SEV-SNP ABI Version 1.55 */ - -#define PSP_CMD_SNP_PLATFORMSTATUS 0x81 - -struct psp_snp_platform_status { - uint8_t api_major; - uint8_t api_minor; - uint8_t state; - uint8_t is_rmp_init; - uint32_t build; - uint32_t features; - uint32_t guest_count; - uint64_t current_tcb; - uint64_t reported_tcb; -} __packed; - -#define PSP_IOC_GET_PSTATUS _IOR('P', 0, struct psp_platform_status) -#define PSP_IOC_DF_FLUSH _IO('P', 1) -#define PSP_IOC_DECOMMISSION _IOW('P', 2, struct psp_decommission) -#define PSP_IOC_GET_GSTATUS _IOWR('P', 3, struct psp_guest_status) -#define PSP_IOC_LAUNCH_START _IOWR('P', 4, struct psp_launch_start) -#define PSP_IOC_LAUNCH_UPDATE_DATA \ - _IOW('P', 5, struct psp_launch_update_data) -#define PSP_IOC_LAUNCH_MEASURE _IOWR('P', 6, struct psp_launch_measure) -#define PSP_IOC_LAUNCH_FINISH _IOW('P', 7, struct psp_launch_finish) -#define PSP_IOC_ATTESTATION _IOWR('P', 8, struct psp_attestation) -#define PSP_IOC_ACTIVATE _IOW('P', 9, struct psp_activate) -#define PSP_IOC_DEACTIVATE _IOW('P', 10, struct psp_deactivate) -#define PSP_IOC_SNP_GET_PSTATUS _IOR('P', 11, struct psp_snp_platform_status) -#define PSP_IOC_GUEST_SHUTDOWN _IOW('P', 255, struct psp_guest_shutdown) -#endif /* __amd64__ */ - -#ifdef _KERNEL - void ccp_attach(struct ccp_softc *); - -#ifdef __amd64__ -int psp_attach(struct ccp_softc *); - -int pspclose(dev_t, int, int, struct proc *); -int pspopen(dev_t, int, int, struct proc *); -int pspioctl(dev_t, u_long, caddr_t, int, struct proc *); -#endif - -#endif /* _KERNEL */ diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c new file mode 100644 index 00000000000..d6a80998e09 --- /dev/null +++ b/sys/dev/ic/psp.c @@ -0,0 +1,659 @@ +/* $OpenBSD: psp.c,v 1.1 2024/09/03 00:23:05 jsg Exp $ */ + +/* + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/timeout.h> +#include <sys/pledge.h> + +#include <machine/bus.h> + +#include <sys/proc.h> +#include <uvm/uvm.h> +#include <crypto/xform.h> + +#include <dev/ic/ccpvar.h> +#include <dev/ic/pspvar.h> + +struct ccp_softc *ccp_softc; + +int psp_get_pstatus(struct psp_platform_status *); +int psp_init(struct psp_init *); + +int +psp_sev_intr(struct ccp_softc *sc, uint32_t status) +{ + if (!(status & PSP_CMDRESP_COMPLETE)) + return (0); + + wakeup(sc); + + return (1); +} + +int +psp_attach(struct ccp_softc *sc) +{ + struct psp_platform_status pst; + struct psp_init init; + size_t size; + int nsegs; + + if (!(sc->sc_capabilities & PSP_CAP_SEV)) + return (0); + + rw_init(&sc->sc_lock, "ccp_lock"); + + /* create and map SEV command buffer */ + sc->sc_cmd_size = size = PAGE_SIZE; + if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, + &sc->sc_cmd_map) != 0) + return (0); + + if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1, + &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) + goto fail_0; + + if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size, + &sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0) + goto fail_1; + + if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva, + size, NULL, BUS_DMA_WAITOK) != 0) + goto fail_2; + + sc->sc_sev_intr = psp_sev_intr; + ccp_softc = sc; + + if (psp_get_pstatus(&pst) || pst.state != 0) + goto fail_3; + + /* + * create and map Trusted Memory Region (TMR); size 1 Mbyte, + * needs to be aligned to 1 Mbyte. + */ + sc->sc_tmr_size = size = PSP_TMR_SIZE; + if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, + &sc->sc_tmr_map) != 0) + goto fail_3; + + if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1, + &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) + goto fail_4; + + if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size, + &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0) + goto fail_5; + + if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva, + size, NULL, BUS_DMA_WAITOK) != 0) + goto fail_6; + + memset(&init, 0, sizeof(init)); + init.enable_es = 1; + init.tmr_length = PSP_TMR_SIZE; + init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr; + if (psp_init(&init)) + goto fail_7; + + printf(", SEV"); + + psp_get_pstatus(&pst); + if ((pst.state == 1) && (pst.cfges_build & 0x1)) + printf(", SEV-ES"); + + sc->sc_psp_attached = 1; + + return (1); + +fail_7: + bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map); +fail_6: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size); +fail_5: + bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1); +fail_4: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map); +fail_3: + bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map); +fail_2: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size); +fail_1: + bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1); +fail_0: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map); + + ccp_softc = NULL; + sc->sc_psp_attached = -1; + + return (0); +} + +static int +ccp_wait(struct ccp_softc *sc, uint32_t *status, int poll) +{ + uint32_t cmdword; + int count; + + if (poll) { + count = 0; + while (count++ < 10) { + cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PSP_REG_CMDRESP); + if (cmdword & PSP_CMDRESP_RESPONSE) + goto done; + delay(5000); + } + + /* timeout */ + return (1); + } + + if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(1)) == EWOULDBLOCK) + return (1); + +done: + if (status) { + *status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PSP_REG_CMDRESP); + } + + return (0); +} + +static int +ccp_docmd(struct ccp_softc *sc, int cmd, uint64_t paddr) +{ + uint32_t plo, phi, cmdword, status; + + plo = ((paddr >> 0) & 0xffffffff); + phi = ((paddr >> 32) & 0xffffffff); + cmdword = (cmd & 0x3ff) << 16; + if (!cold) + cmdword |= PSP_CMDRESP_IOC; + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRLO, plo); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRHI, phi); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_CMDRESP, cmdword); + + if (ccp_wait(sc, &status, cold)) + return (1); + + /* Did PSP sent a response code? */ + if (status & PSP_CMDRESP_RESPONSE) { + if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS) + return (1); + } + + return (0); +} + +int +psp_init(struct psp_init *uinit) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_init *init; + int ret; + + init = (struct psp_init *)sc->sc_cmd_kva; + bzero(init, sizeof(*init)); + + init->enable_es = uinit->enable_es; + init->tmr_paddr = uinit->tmr_paddr; + init->tmr_length = uinit->tmr_length; + + ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr); + if (ret != 0) + return (EIO); + + wbinvd_on_all_cpus(); + + return (0); +} + +int +psp_get_pstatus(struct psp_platform_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_platform_status *status; + int ret; + + status = (struct psp_platform_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + bcopy(status, ustatus, sizeof(*ustatus)); + + return (0); +} + +int +psp_df_flush(void) +{ + struct ccp_softc *sc = ccp_softc; + int ret; + + wbinvd_on_all_cpus(); + + ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_decommission(struct psp_decommission *udecom) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_decommission *decom; + int ret; + + decom = (struct psp_decommission *)sc->sc_cmd_kva; + bzero(decom, sizeof(*decom)); + + decom->handle = udecom->handle; + + ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_get_gstatus(struct psp_guest_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_guest_status *status; + int ret; + + status = (struct psp_guest_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + status->handle = ustatus->handle; + + ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + ustatus->policy = status->policy; + ustatus->asid = status->asid; + ustatus->state = status->state; + + return (0); +} + +int +psp_launch_start(struct psp_launch_start *ustart) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_start *start; + int ret; + + start = (struct psp_launch_start *)sc->sc_cmd_kva; + bzero(start, sizeof(*start)); + + start->handle = ustart->handle; + start->policy = ustart->policy; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + /* If requested, return new handle. */ + if (ustart->handle == 0) + ustart->handle = start->handle; + + return (0); +} + +int +psp_launch_update_data(struct psp_launch_update_data *ulud, struct proc *p) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_update_data *ludata; + pmap_t pmap; + vaddr_t v, next, end; + size_t size, len, off; + int ret; + + /* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */ + if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 || + (ulud->length % AES_XTS_BLOCKSIZE) != 0) + return (EINVAL); + + ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva; + bzero(ludata, sizeof(*ludata)); + + ludata->handle = ulud->handle; + + /* Drain caches before we encrypt memory. */ + wbinvd_on_all_cpus(); + + /* + * Launch update one physical page at a time. We could + * optimise this for contiguous pages of physical memory. + * + * vmd(8) provides the guest physical address, thus convert + * to system physical address. + */ + pmap = vm_map_pmap(&p->p_vmspace->vm_map); + size = ulud->length; + end = ulud->paddr + ulud->length; + for (v = ulud->paddr; v < end; v = next) { + off = v & PAGE_MASK; + + len = MIN(PAGE_SIZE - off, size); + + /* Wire mapping. */ + if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0)) + return (EINVAL); + if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr)) + return (EINVAL); + ludata->length = len; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + size -= len; + next = v + len; + } + + return (0); +} + +int +psp_launch_measure(struct psp_launch_measure *ulm) +{ + struct psp_launch_measure *lm; + struct ccp_softc *sc = ccp_softc; + int ret; + uint64_t paddr; + + if (ulm->measure_len != sizeof(ulm->psp_measure)) + return (EINVAL); + + lm = (struct psp_launch_measure *)sc->sc_cmd_kva; + bzero(lm, sizeof(*lm)); + + lm->handle = ulm->handle; + paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; + lm->measure_paddr = + paddr + offsetof(struct psp_launch_measure, psp_measure); + lm->measure_len = sizeof(lm->psp_measure); + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr); + + if (ret != 0 || lm->measure_len != ulm->measure_len) + return (EIO); + + bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len); + + return (0); +} + +int +psp_launch_finish(struct psp_launch_finish *ulf) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_finish *lf; + int ret; + + lf = (struct psp_launch_finish *)sc->sc_cmd_kva; + bzero(lf, sizeof(*lf)); + + lf->handle = ulf->handle; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_attestation(struct psp_attestation *uat) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_attestation *at; + int ret; + uint64_t paddr; + + if (uat->attest_len != sizeof(uat->psp_report)) + return (EINVAL); + + at = (struct psp_attestation *)sc->sc_cmd_kva; + bzero(at, sizeof(*at)); + + at->handle = uat->handle; + paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; + at->attest_paddr = + paddr + offsetof(struct psp_attestation, psp_report); + bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce)); + at->attest_len = sizeof(at->psp_report); + + ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr); + + if (ret != 0 || at->attest_len != uat->attest_len) + return (EIO); + + bcopy(&at->psp_report, &uat->psp_report, uat->attest_len); + + return (0); +} + +int +psp_activate(struct psp_activate *uact) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_activate *act; + int ret; + + act = (struct psp_activate *)sc->sc_cmd_kva; + bzero(act, sizeof(*act)); + + act->handle = uact->handle; + act->asid = uact->asid; + + ret = ccp_docmd(sc, PSP_CMD_ACTIVATE, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_deactivate(struct psp_deactivate *udeact) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_deactivate *deact; + int ret; + + deact = (struct psp_deactivate *)sc->sc_cmd_kva; + bzero(deact, sizeof(*deact)); + + deact->handle = udeact->handle; + + ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_guest_shutdown(struct psp_guest_shutdown *ugshutdown) +{ + struct psp_deactivate deact; + struct psp_decommission decom; + int ret; + + bzero(&deact, sizeof(deact)); + deact.handle = ugshutdown->handle; + if ((ret = psp_deactivate(&deact)) != 0) + return (ret); + + if ((ret = psp_df_flush()) != 0) + return (ret); + + bzero(&decom, sizeof(decom)); + decom.handle = ugshutdown->handle; + if ((ret = psp_decommission(&decom)) != 0) + return (ret); + + return (0); +} + +int +psp_snp_get_pstatus(struct psp_snp_platform_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_snp_platform_status *status; + int ret; + + status = (struct psp_snp_platform_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + bcopy(status, ustatus, sizeof(*ustatus)); + + return (0); +} + +int +pspopen(dev_t dev, int flag, int mode, struct proc *p) +{ + if (ccp_softc == NULL) + return (ENODEV); + + return (0); +} + +int +pspclose(dev_t dev, int flag, int mode, struct proc *p) +{ + return (0); +} + +int +pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + int ret; + + rw_enter_write(&ccp_softc->sc_lock); + + switch (cmd) { + case PSP_IOC_GET_PSTATUS: + ret = psp_get_pstatus((struct psp_platform_status *)data); + break; + case PSP_IOC_DF_FLUSH: + ret = psp_df_flush(); + break; + case PSP_IOC_DECOMMISSION: + ret = psp_decommission((struct psp_decommission *)data); + break; + case PSP_IOC_GET_GSTATUS: + ret = psp_get_gstatus((struct psp_guest_status *)data); + break; + case PSP_IOC_LAUNCH_START: + ret = psp_launch_start((struct psp_launch_start *)data); + break; + case PSP_IOC_LAUNCH_UPDATE_DATA: + ret = psp_launch_update_data( + (struct psp_launch_update_data *)data, p); + break; + case PSP_IOC_LAUNCH_MEASURE: + ret = psp_launch_measure((struct psp_launch_measure *)data); + break; + case PSP_IOC_LAUNCH_FINISH: + ret = psp_launch_finish((struct psp_launch_finish *)data); + break; + case PSP_IOC_ATTESTATION: + ret = psp_attestation((struct psp_attestation *)data); + break; + case PSP_IOC_ACTIVATE: + ret = psp_activate((struct psp_activate *)data); + break; + case PSP_IOC_DEACTIVATE: + ret = psp_deactivate((struct psp_deactivate *)data); + break; + case PSP_IOC_GUEST_SHUTDOWN: + ret = psp_guest_shutdown((struct psp_guest_shutdown *)data); + break; + case PSP_IOC_SNP_GET_PSTATUS: + ret = + psp_snp_get_pstatus((struct psp_snp_platform_status *)data); + break; + default: + ret = ENOTTY; + break; + } + + rw_exit_write(&ccp_softc->sc_lock); + + return (ret); +} + +int +pledge_ioctl_psp(struct proc *p, long com) +{ + switch (com) { + case PSP_IOC_GET_PSTATUS: + case PSP_IOC_DF_FLUSH: + case PSP_IOC_GET_GSTATUS: + case PSP_IOC_LAUNCH_START: + case PSP_IOC_LAUNCH_UPDATE_DATA: + case PSP_IOC_LAUNCH_MEASURE: + case PSP_IOC_LAUNCH_FINISH: + case PSP_IOC_ACTIVATE: + case PSP_IOC_GUEST_SHUTDOWN: + return (0); + default: + return (pledge_fail(p, EPERM, PLEDGE_VMM)); + } +} diff --git a/sys/dev/ic/pspvar.h b/sys/dev/ic/pspvar.h new file mode 100644 index 00000000000..84f715d83e0 --- /dev/null +++ b/sys/dev/ic/pspvar.h @@ -0,0 +1,255 @@ +/* $OpenBSD: pspvar.h,v 1.1 2024/09/03 00:23:05 jsg Exp $ */ + +/* + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/ioctl.h> + +/* AMD 17h */ +#define PSP_REG_INTEN 0x10690 +#define PSP_REG_INTSTS 0x10694 +#define PSP_REG_CMDRESP 0x10980 +#define PSP_REG_ADDRLO 0x109e0 +#define PSP_REG_ADDRHI 0x109e4 +#define PSP_REG_CAPABILITIES 0x109fc + +#define PSP_PSTATE_UNINIT 0x0 +#define PSP_PSTATE_INIT 0x1 +#define PSP_PSTATE_WORKING 0x2 + +#define PSP_GSTATE_UNINIT 0x0 +#define PSP_GSTATE_LUPDATE 0x1 +#define PSP_GSTATE_LSECRET 0x2 +#define PSP_GSTATE_RUNNING 0x3 +#define PSP_GSTATE_SUPDATE 0x4 +#define PSP_GSTATE_RUPDATE 0x5 +#define PSP_GSTATE_SENT 0x6 + +#define PSP_CAP_SEV (1 << 0) +#define PSP_CAP_TEE (1 << 1) +#define PSP_CAP_DBC_THRU_EXT (1 << 2) +#define PSP_CAP_SECURITY_REPORTING (1 << 7) +#define PSP_CAP_SECURITY_FUSED_PART (1 << 8) +#define PSP_CAP_SECURITY_DEBUG_LOCK_ON (1 << 10) +#define PSP_CAP_SECURITY_TSME_STATUS (1 << 13) +#define PSP_CAP_SECURITY_ANTI_ROLLBACK_STATUS (1 << 15) +#define PSP_CAP_SECURITY_RPMC_PRODUCTION_ENABLED (1 << 16) +#define PSP_CAP_SECURITY_RPMC_SPIROM_AVAILABLE (1 << 17) +#define PSP_CAP_SECURITY_HSP_TPM_AVAILABLE (1 << 18) +#define PSP_CAP_SECURITY_ROM_ARMOR_ENFORCED (1 << 19) + +#define PSP_CAP_BITS "\20\001SEV\002TEE\003DBC_THRU_EXT\010REPORTING\011FUSED_PART\013DEBUG_LOCK_ON\016TSME_STATUS\020ANTI_ROLLBACK_STATUS\021RPMC_PRODUCTION_ENABLED\022RPMC_SPIROM_AVAILABLE\023HSP_TPM_AVAILABLE\024ROM_ARMOR_ENFORCED" + +#define PSP_CMDRESP_IOC (1 << 0) +#define PSP_CMDRESP_COMPLETE (1 << 1) +#define PSP_CMDRESP_RESPONSE (1 << 31) + +#define PSP_STATUS_MASK 0xffff +#define PSP_STATUS_SUCCESS 0x0000 +#define PSP_STATUS_INVALID_PLATFORM_STATE 0x0001 + +#define PSP_TMR_SIZE (1024*1024) /* 1 Mb */ + +#define PSP_SUCCESS 0x0000 +#define PSP_INVALID_ADDRESS 0x0009 + +/* Selection of PSP commands of the SEV API Version 0.24 */ + +#define PSP_CMD_INIT 0x1 +#define PSP_CMD_PLATFORMSTATUS 0x4 +#define PSP_CMD_DF_FLUSH 0xa +#define PSP_CMD_DECOMMISSION 0x20 +#define PSP_CMD_ACTIVATE 0x21 +#define PSP_CMD_DEACTIVATE 0x22 +#define PSP_CMD_GUESTSTATUS 0x23 +#define PSP_CMD_LAUNCH_START 0x30 +#define PSP_CMD_LAUNCH_UPDATE_DATA 0x31 +#define PSP_CMD_LAUNCH_MEASURE 0x33 +#define PSP_CMD_LAUNCH_FINISH 0x35 +#define PSP_CMD_ATTESTATION 0x36 + +struct psp_platform_status { + /* Output parameters from PSP_CMD_PLATFORMSTATUS */ + uint8_t api_major; + uint8_t api_minor; + uint8_t state; + uint8_t owner; + uint32_t cfges_build; + uint32_t guest_count; +} __packed; + +struct psp_guest_status { + /* Input parameter for PSP_CMD_GUESTSTATUS */ + uint32_t handle; + + /* Output parameters from PSP_CMD_GUESTSTATUS */ + uint32_t policy; + uint32_t asid; + uint8_t state; +} __packed; + +struct psp_launch_start { + /* Input/Output parameter for PSP_CMD_LAUNCH_START */ + uint32_t handle; + + /* Input parameters for PSP_CMD_LAUNCH_START */ + uint32_t policy; + + /* The following input parameters are not used yet */ + uint64_t dh_cert_paddr; + uint32_t dh_cert_len; + uint32_t reserved; + uint64_t session_paddr; + uint32_t session_len; +} __packed; + +struct psp_launch_update_data { + /* Input parameters for PSP_CMD_LAUNCH_UPDATE_DATA */ + uint32_t handle; + uint32_t reserved; + uint64_t paddr; + uint32_t length; +} __packed; + +struct psp_measure { + /* Output buffer for PSP_CMD_LAUNCH_MEASURE */ + uint8_t measure[32]; + uint8_t measure_nonce[16]; +} __packed; + +struct psp_launch_measure { + /* Input parameters for PSP_CMD_LAUNCH_MEASURE */ + uint32_t handle; + uint32_t reserved; + uint64_t measure_paddr; + + /* Input/output parameter for PSP_CMD_LAUNCH_MEASURE */ + uint32_t measure_len; + uint32_t padding; + + /* Output buffer from PSP_CMD_LAUNCH_MEASURE */ + struct psp_measure psp_measure; /* 64bit aligned */ +#define measure psp_measure.measure +#define measure_nonce psp_measure.measure_nonce +} __packed; + +struct psp_launch_finish { + /* Input parameter for PSP_CMD_LAUNCH_FINISH */ + uint32_t handle; +} __packed; + +struct psp_report { + /* Output buffer for PSP_CMD_ATTESTATION */ + uint8_t report_nonce[16]; + uint8_t report_launch_digest[32]; + uint32_t report_policy; + uint32_t report_sig_usage; + uint32_t report_sig_algo; + uint32_t reserved2; + uint8_t report_sig1[144]; +} __packed; + +struct psp_attestation { + /* Input parameters for PSP_CMD_ATTESTATION */ + uint32_t handle; + uint32_t reserved; + uint64_t attest_paddr; + uint8_t attest_nonce[16]; + + /* Input/output parameter from PSP_CMD_ATTESTATION */ + uint32_t attest_len; + uint32_t padding; + + /* Output parameter from PSP_CMD_ATTESTATION */ + struct psp_report psp_report; /* 64bit aligned */ +#define report_nonce psp_report.report_nonce +#define report_launch_digest psp_report.report_launch_digest +#define report_policy psp_report.report_policy +#define report_sig_usage psp_report.report_sig_usage; +#define report_report_sig_alg psp_report.report_sig_algo; +#define report_report_sig1 psp_report.report_sig1; +} __packed; + +struct psp_activate { + /* Input parameters for PSP_CMD_ACTIVATE */ + uint32_t handle; + uint32_t asid; +} __packed; + +struct psp_deactivate { + /* Input parameter for PSP_CMD_DEACTIVATE */ + uint32_t handle; +} __packed; + +struct psp_decommission { + /* Input parameter for PSP_CMD_DECOMMISSION */ + uint32_t handle; +} __packed; + +struct psp_init { + /* Output parameters from PSP_CMD_INIT */ + uint32_t enable_es; + uint32_t reserved; + uint64_t tmr_paddr; + uint32_t tmr_length; +} __packed; + + +struct psp_guest_shutdown { + /* Input parameter for PSP_CMD_GUEST_SHUTDOWN */ + uint32_t handle; +} __packed; + +/* Selection of PSP commands of the SEV-SNP ABI Version 1.55 */ + +#define PSP_CMD_SNP_PLATFORMSTATUS 0x81 + +struct psp_snp_platform_status { + uint8_t api_major; + uint8_t api_minor; + uint8_t state; + uint8_t is_rmp_init; + uint32_t build; + uint32_t features; + uint32_t guest_count; + uint64_t current_tcb; + uint64_t reported_tcb; +} __packed; + +#define PSP_IOC_GET_PSTATUS _IOR('P', 0, struct psp_platform_status) +#define PSP_IOC_DF_FLUSH _IO('P', 1) +#define PSP_IOC_DECOMMISSION _IOW('P', 2, struct psp_decommission) +#define PSP_IOC_GET_GSTATUS _IOWR('P', 3, struct psp_guest_status) +#define PSP_IOC_LAUNCH_START _IOWR('P', 4, struct psp_launch_start) +#define PSP_IOC_LAUNCH_UPDATE_DATA \ + _IOW('P', 5, struct psp_launch_update_data) +#define PSP_IOC_LAUNCH_MEASURE _IOWR('P', 6, struct psp_launch_measure) +#define PSP_IOC_LAUNCH_FINISH _IOW('P', 7, struct psp_launch_finish) +#define PSP_IOC_ATTESTATION _IOWR('P', 8, struct psp_attestation) +#define PSP_IOC_ACTIVATE _IOW('P', 9, struct psp_activate) +#define PSP_IOC_DEACTIVATE _IOW('P', 10, struct psp_deactivate) +#define PSP_IOC_SNP_GET_PSTATUS _IOR('P', 11, struct psp_snp_platform_status) +#define PSP_IOC_GUEST_SHUTDOWN _IOW('P', 255, struct psp_guest_shutdown) + +#ifdef _KERNEL + +int psp_attach(struct ccp_softc *); + +int pspclose(dev_t, int, int, struct proc *); +int pspopen(dev_t, int, int, struct proc *); +int pspioctl(dev_t, u_long, caddr_t, int, struct proc *); + +#endif /* _KERNEL */ diff --git a/sys/dev/pci/ccp_pci.c b/sys/dev/pci/ccp_pci.c index 1edd1a1981f..1285603eb9e 100644 --- a/sys/dev/pci/ccp_pci.c +++ b/sys/dev/pci/ccp_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp_pci.c,v 1.11 2024/06/13 17:59:08 bluhm Exp $ */ +/* $OpenBSD: ccp_pci.c,v 1.12 2024/09/03 00:23:05 jsg Exp $ */ /* * Copyright (c) 2018 David Gwynne <dlg@openbsd.org> @@ -27,16 +27,15 @@ #include <dev/pci/pcivar.h> #include <dev/ic/ccpvar.h> +#include <dev/ic/pspvar.h> #define CCP_PCI_BAR 0x18 int ccp_pci_match(struct device *, void *, void *); void ccp_pci_attach(struct device *, struct device *, void *); -#ifdef __amd64__ void psp_pci_attach(struct device *, struct device *, void *); int psp_pci_intr(void *); -#endif const struct cfattach ccp_pci_ca = { sizeof(struct ccp_softc), @@ -79,14 +78,11 @@ ccp_pci_attach(struct device *parent, struct device *self, void *aux) return; } -#ifdef __amd64__ psp_pci_attach(parent, self, aux); -#endif ccp_attach(sc); } -#ifdef __amd64__ void psp_pci_attach(struct device *parent, struct device *self, void *aux) { @@ -140,4 +136,3 @@ psp_pci_intr(void *arg) return (1); } -#endif /* __amd64__ */ |