From: Hans-Jörg Höxer Subject: Re: [EXT] unifdef psp To: , , Date: Mon, 2 Sep 2024 15:30:37 +0200 Hi, On Mon, Sep 02, 2024 at 10:17:03PM +1000, Jonathan Gray wrote: > move psp functions out of ccp.c into a file only built on amd64 > > the ccp pci attachment is not built on arm64 so does not need ifdefs > > the vmd diff will need to be changed to include pspvar.h instead of ccpvar.h ok, fine with me > diff --git sys/arch/amd64/conf/files.amd64 sys/arch/amd64/conf/files.amd64 > index a3452d9729c..011c21dc917 100644 > --- sys/arch/amd64/conf/files.amd64 > +++ sys/arch/amd64/conf/files.amd64 > @@ -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 sys/dev/ic/ccp.c sys/dev/ic/ccp.c > index 42ae5f8e7c2..3256ca11eae 100644 > --- sys/dev/ic/ccp.c > +++ sys/dev/ic/ccp.c > @@ -2,7 +2,6 @@ > > /* > * Copyright (c) 2018 David Gwynne > - * Copyright (c) 2023, 2024 Hans-Joerg Hoexer > * > * 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 > #include > -#include > #include > -#include > -#include > #include > -#include > > #include > > -#ifdef __amd64__ > -#include > -#include > -#include > -#endif > - > #include > > #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 sys/dev/ic/ccpvar.h sys/dev/ic/ccpvar.h > index 7add1e0a46e..c5c59663880 100644 > --- sys/dev/ic/ccpvar.h > +++ sys/dev/ic/ccpvar.h > @@ -18,6 +18,7 @@ > */ > > #include > +#include > > 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 > -#include > - > -/* 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 sys/dev/ic/psp.c sys/dev/ic/psp.c > new file mode 100644 > index 00000000000..134c82d68e9 > --- /dev/null > +++ sys/dev/ic/psp.c > @@ -0,0 +1,659 @@ > +/* $OpenBSD: ccp.c,v 1.9 2024/09/01 19:25:06 bluhm Exp $ */ > + > +/* > + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer > + * > + * 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 > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > +#include > + > +#include > +#include > + > +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 sys/dev/ic/pspvar.h sys/dev/ic/pspvar.h > new file mode 100644 > index 00000000000..2d4a79ed664 > --- /dev/null > +++ sys/dev/ic/pspvar.h > @@ -0,0 +1,255 @@ > +/* $OpenBSD: ccpvar.h,v 1.4 2024/09/01 19:25:06 bluhm Exp $ */ > + > +/* > + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer > + * > + * 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 > + > +/* 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 sys/dev/pci/ccp_pci.c sys/dev/pci/ccp_pci.c > index 1edd1a1981f..5aba34b934c 100644 > --- sys/dev/pci/ccp_pci.c > +++ sys/dev/pci/ccp_pci.c > @@ -27,16 +27,15 @@ > #include > > #include > +#include > > #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__ */