-/* $OpenBSD: ccp.c,v 1.3 2020/05/29 04:42:25 deraadt Exp $ */
+/* $OpenBSD: ccp.c,v 1.4 2024/06/12 12:54:54 bluhm 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 <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_set(&sc->sc_tick, ccp_rng, sc);
ccp_rng(sc);
- printf("\n");
+ if (sc->sc_psp_attached)
+ printf(", RNG\n");
+ else
+ printf(": RNG\n");
}
static void
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;
+
+ printf(", SEV");
+
+ /*
+ * create and map Trusted Memory Region (TMR); size 1 Mbyte,
+ * needs to be aligend 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;
+
+ 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;
+
+ 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 & 0x3f) << 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) {
+ printf("%s: command failed: 0x%x\n", __func__,
+ (status & PSP_STATUS_MASK));
+ 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);
+
+ wbinvd_on_all_cpus();
+
+ if (ret != 0)
+ return (EIO);
+
+ 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_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_SNP_GET_PSTATUS:
+ ret =
+ psp_snp_get_pstatus((struct psp_snp_platform_status *)data);
+ break;
+ default:
+ printf("%s: unkown ioctl code 0x%lx\n", __func__, cmd);
+ ret = ENOTTY;
+ }
+
+ rw_exit_write(&ccp_softc->sc_lock);
+
+ return (ret);
+}
+#endif /* __amd64__ */
-/* $OpenBSD: ccpvar.h,v 1.1 2018/04/20 04:37:21 dlg Exp $ */
+/* $OpenBSD: ccpvar.h,v 1.2 2024/06/12 12:54:54 bluhm 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
bus_space_handle_t sc_ioh;
struct timeout sc_tick;
+
+ bus_size_t sc_size;
+ 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);
+ void * sc_ih;
+
+ bus_dmamap_t sc_cmd_map;
+ bus_dma_segment_t sc_cmd_seg;
+ size_t sc_cmd_size;
+ caddr_t sc_cmd_kva;
+
+ bus_dmamap_t sc_tmr_map;
+ bus_dma_segment_t sc_tmr_seg;
+ size_t sc_tmr_size;
+ 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;
+
+
+/* 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)
+#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 */