-# $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
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"
-/* $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
#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
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)
{
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__ */
-/* $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>
*/
#include <sys/timeout.h>
+#include <sys/rwlock.h>
struct ccp_softc {
struct device sc_dev;
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);
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 */
--- /dev/null
+/* $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));
+ }
+}
--- /dev/null
+/* $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 */
-/* $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>
#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),
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)
{
return (1);
}
-#endif /* __amd64__ */