From 38923a1915850ed4b92810be9822ffb79ad5d579 Mon Sep 17 00:00:00 2001 From: bluhm Date: Thu, 24 Oct 2024 18:52:59 +0000 Subject: [PATCH] Attach psp(4) version 1. Some AMD CPUs come with an older platform security processor. It is detectet by PCI Id and has different register offsets. Move the dynamic register offsets into psp_softc. The PCI attach code is now in a separate psp_pci.c file and detects the version of the psp along with the ccp. The attach code is more verbose to display where problems might occur. Now the ccp_wait() has 2 seconds timeout, both for polling and interrupt. Also prevent a useless bus_space_read_4(). OK hshoexer@ --- sys/dev/ic/psp.c | 71 +++++++++++++++++------- sys/dev/ic/pspvar.h | 17 +++++- sys/dev/pci/ccp_pci.c | 65 ++++------------------ sys/dev/pci/files.pci | 3 +- sys/dev/pci/psp_pci.c | 126 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+), 76 deletions(-) create mode 100644 sys/dev/pci/psp_pci.c diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c index 95babb7d3db..e3eda5c96a8 100644 --- a/sys/dev/ic/psp.c +++ b/sys/dev/ic/psp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psp.c,v 1.5 2024/10/04 16:58:26 bluhm Exp $ */ +/* $OpenBSD: psp.c,v 1.6 2024/10/24 18:52:59 bluhm Exp $ */ /* * Copyright (c) 2023, 2024 Hans-Joerg Hoexer @@ -37,7 +37,12 @@ struct psp_softc { bus_space_handle_t sc_ioh; bus_dma_tag_t sc_dmat; - uint32_t sc_capabilities; + + bus_size_t sc_reg_inten; + bus_size_t sc_reg_intsts; + bus_size_t sc_reg_cmdresp; + bus_size_t sc_reg_addrlo; + bus_size_t sc_reg_addrhi; bus_dmamap_t sc_cmd_map; bus_dma_segment_t sc_cmd_seg; @@ -74,8 +79,8 @@ psp_sev_intr(void *arg) struct psp_softc *sc = (struct psp_softc *)csc->sc_psp; uint32_t status; - status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, status); + status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts, status); if (!(status & PSP_CMDRESP_COMPLETE)) return (0); @@ -101,10 +106,25 @@ psp_attach(struct device *parent, struct device *self, void *aux) size_t size; int nsegs; + printf(":"); sc->sc_iot = arg->iot; sc->sc_ioh = arg->ioh; sc->sc_dmat = arg->dmat; - sc->sc_capabilities = arg->capabilities; + if (arg->version == 1) { + sc->sc_reg_inten = PSPV1_REG_INTEN; + sc->sc_reg_intsts = PSPV1_REG_INTSTS; + sc->sc_reg_cmdresp = PSPV1_REG_CMDRESP; + sc->sc_reg_addrlo = PSPV1_REG_ADDRLO; + sc->sc_reg_addrhi = PSPV1_REG_ADDRHI; + } else { + sc->sc_reg_inten = PSP_REG_INTEN; + sc->sc_reg_intsts = PSP_REG_INTSTS; + sc->sc_reg_cmdresp = PSP_REG_CMDRESP; + sc->sc_reg_addrlo = PSP_REG_ADDRLO; + sc->sc_reg_addrhi = PSP_REG_ADDRHI; + } + if (arg->version) + printf(" vers %d,", arg->version); rw_init(&sc->sc_lock, "psp_lock"); @@ -127,8 +147,16 @@ psp_attach(struct device *parent, struct device *self, void *aux) size, NULL, BUS_DMA_WAITOK) != 0) goto fail_2; - if (psp_get_pstatus(sc, &pst) || pst.state != 0) + if (psp_get_pstatus(sc, &pst)) { + printf(" platform status"); goto fail_3; + } + if (pst.state != PSP_PSTATE_UNINIT) { + printf(" uninitialized state"); + goto fail_3; + } + printf(" api %u.%u, build %u,", + pst.api_major, pst.api_minor, pst.cfges_build >> 24); /* * create and map Trusted Memory Region (TMR); size 1 Mbyte, @@ -156,15 +184,20 @@ psp_attach(struct device *parent, struct device *self, void *aux) 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(sc, &init)) + if (psp_init(sc, &init)) { + printf(" init"); goto fail_7; + } - printf(": SEV"); + printf(" SEV"); psp_get_pstatus(sc, &pst); - if ((pst.state == 1) && (pst.cfges_build & 0x1)) + if ((pst.state == PSP_PSTATE_INIT) && (pst.cfges_build & 0x1)) printf(", SEV-ES"); + /* enable interrupts */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_inten, -1); + printf("\n"); return; @@ -186,7 +219,7 @@ fail_1: fail_0: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map); - printf("\n"); + printf(" failed\n"); return; } @@ -199,9 +232,9 @@ ccp_wait(struct psp_softc *sc, uint32_t *status, int poll) if (poll) { count = 0; - while (count++ < 100) { + while (count++ < 400) { cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - PSP_REG_CMDRESP); + sc->sc_reg_cmdresp); if (cmdword & PSP_CMDRESP_RESPONSE) goto done; delay(5000); @@ -214,12 +247,10 @@ ccp_wait(struct psp_softc *sc, uint32_t *status, int poll) if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(2)) == EWOULDBLOCK) return (1); + cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp); done: - if (status) { - *status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - PSP_REG_CMDRESP); - } - + if (status != NULL) + *status = cmdword; return (0); } @@ -234,9 +265,9 @@ ccp_docmd(struct psp_softc *sc, int cmd, uint64_t paddr) 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); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrlo, plo); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrhi, phi); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp, cmdword); if (ccp_wait(sc, &status, cold)) return (1); diff --git a/sys/dev/ic/pspvar.h b/sys/dev/ic/pspvar.h index a1d7c83849e..c3bad155aca 100644 --- a/sys/dev/ic/pspvar.h +++ b/sys/dev/ic/pspvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pspvar.h,v 1.2 2024/09/04 07:45:08 jsg Exp $ */ +/* $OpenBSD: pspvar.h,v 1.3 2024/10/24 18:52:59 bluhm Exp $ */ /* * Copyright (c) 2023, 2024 Hans-Joerg Hoexer @@ -19,6 +19,13 @@ #include /* AMD 17h */ +#define PSPV1_REG_INTEN 0x10610 +#define PSPV1_REG_INTSTS 0x10614 +#define PSPV1_REG_CMDRESP 0x10580 +#define PSPV1_REG_ADDRLO 0x105e0 +#define PSPV1_REG_ADDRHI 0x105e4 +#define PSPV1_REG_CAPABILITIES 0x105fc + #define PSP_REG_INTEN 0x10690 #define PSP_REG_INTSTS 0x10694 #define PSP_REG_CMDRESP 0x10980 @@ -252,10 +259,18 @@ struct psp_attach_args { bus_dma_tag_t dmat; uint32_t capabilities; + int version; }; int pspsubmatch(struct device *, void *, void *); int pspprint(void *aux, const char *pnp); int psp_sev_intr(void *); +struct ccp_softc; +struct pci_attach_args; + +int psp_pci_match(struct ccp_softc *, struct pci_attach_args *); +void psp_pci_intr_map(struct ccp_softc *, struct pci_attach_args *); +void psp_pci_attach(struct ccp_softc *, struct pci_attach_args *); + #endif /* _KERNEL */ diff --git a/sys/dev/pci/ccp_pci.c b/sys/dev/pci/ccp_pci.c index 8e1168689f4..49991d12563 100644 --- a/sys/dev/pci/ccp_pci.c +++ b/sys/dev/pci/ccp_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp_pci.c,v 1.13 2024/09/04 07:45:08 jsg Exp $ */ +/* $OpenBSD: ccp_pci.c,v 1.14 2024/10/24 18:52:59 bluhm Exp $ */ /* * Copyright (c) 2018 David Gwynne @@ -36,9 +36,6 @@ int ccp_pci_match(struct device *, void *, void *); void ccp_pci_attach(struct device *, struct device *, void *); -void ccp_pci_intr_map(struct ccp_softc *, struct pci_attach_args *); -void ccp_pci_psp_attach(struct ccp_softc *, struct pci_attach_args *); - const struct cfattach ccp_pci_ca = { sizeof(struct ccp_softc), ccp_pci_match, @@ -67,6 +64,9 @@ ccp_pci_attach(struct device *parent, struct device *self, void *aux) struct ccp_softc *sc = (struct ccp_softc *)self; struct pci_attach_args *pa = aux; pcireg_t memtype; +#if NPSP > 0 + int psp_matched; +#endif memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, CCP_PCI_BAR); if (PCI_MAPREG_TYPE(memtype) != PCI_MAPREG_TYPE_MEM) { @@ -80,59 +80,16 @@ ccp_pci_attach(struct device *parent, struct device *self, void *aux) return; } - ccp_pci_intr_map(sc, pa); - - ccp_attach(sc); - - ccp_pci_psp_attach(sc, pa); -} - -void -ccp_pci_intr_map(struct ccp_softc *sc, struct pci_attach_args *pa) -{ #if NPSP > 0 - pci_intr_handle_t ih; - const char *intrstr = NULL; - - /* clear and disable interrupts */ - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, 0); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, -1); - - if (pci_intr_map_msix(pa, 0, &ih) != 0 && - pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { - printf(": couldn't map interrupt\n"); - return; - } - - intrstr = pci_intr_string(pa->pa_pc, ih); - sc->sc_irqh = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, psp_sev_intr, - sc, sc->sc_dev.dv_xname); - if (sc->sc_irqh != NULL) - printf(": %s", intrstr); + psp_matched = psp_pci_match(sc, aux); + if (psp_matched) + psp_pci_intr_map(sc, pa); #endif -} -void -ccp_pci_psp_attach(struct ccp_softc *sc, struct pci_attach_args *pa) -{ -#if NPSP > 0 - struct psp_attach_args arg; - struct device *self = (struct device *)sc; - - memset(&arg, 0, sizeof(arg)); - arg.iot = sc->sc_iot; - arg.ioh = sc->sc_ioh; - arg.dmat = pa->pa_dmat; - arg.capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - PSP_REG_CAPABILITIES); - - sc->sc_psp = config_found_sm(self, &arg, pspprint, pspsubmatch); - if (sc->sc_psp == NULL) { - pci_intr_disestablish(pa->pa_pc, sc->sc_irqh); - return; - } + ccp_attach(sc); - /* enable interrupts */ - bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, -1); +#if NPSP > 0 + if (psp_matched) + psp_pci_attach(sc, pa); #endif } diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 76cecece306..42c5d61f7f5 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.366 2024/08/14 14:40:46 patrick Exp $ +# $OpenBSD: files.pci,v 1.367 2024/10/24 18:52:59 bluhm Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -830,6 +830,7 @@ file dev/pci/if_bwfm_pci.c bwfm_pci # AMD Cryptographic Co-processor attach ccp at pci with ccp_pci file dev/pci/ccp_pci.c ccp_pci +file dev/pci/psp_pci.c psp # Broadcom NetXtreme-C/E device bnxt: ether, ifnet, ifmedia, intrmap, stoeplitz diff --git a/sys/dev/pci/psp_pci.c b/sys/dev/pci/psp_pci.c new file mode 100644 index 00000000000..e1356ceeb8a --- /dev/null +++ b/sys/dev/pci/psp_pci.c @@ -0,0 +1,126 @@ +/* $OpenBSD: psp_pci.c,v 1.1 2024/10/24 18:52:59 bluhm Exp $ */ + +/* + * Copyright (c) 2023-2024 Hans-Joerg Hoexer + * Copyright (c) 2024 Alexander Bluhm + * + * 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 + +static const struct pci_matchid psp_pci_devices[] = { + { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_CCP_1 }, + { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_3X_CCP }, + { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_19_1X_PSP }, +}; + +int +psp_pci_match(struct ccp_softc *sc, struct pci_attach_args *pa) +{ + bus_size_t reg_capabilities; + uint32_t capabilities; + + if (!pci_matchbyid(pa, psp_pci_devices, nitems(psp_pci_devices))) + return (0); + + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_17_CCP_1) + reg_capabilities = PSPV1_REG_CAPABILITIES; + else + reg_capabilities = PSP_REG_CAPABILITIES; + capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + reg_capabilities); + if (!ISSET(capabilities, PSP_CAP_SEV)) + return (0); + + return (1); +} + +void +psp_pci_intr_map(struct ccp_softc *sc, struct pci_attach_args *pa) +{ + pci_intr_handle_t ih; + const char *intrstr = NULL; + bus_size_t reg_inten, reg_intsts; + + /* clear and disable interrupts */ + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_17_CCP_1) { + reg_inten = PSPV1_REG_INTEN; + reg_intsts = PSPV1_REG_INTSTS; + } else { + reg_inten = PSP_REG_INTEN; + reg_intsts = PSP_REG_INTSTS; + } + bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_inten, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_intsts, -1); + + if (pci_intr_map_msix(pa, 0, &ih) != 0 && + pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { + printf(": couldn't map interrupt\n"); + return; + } + + intrstr = pci_intr_string(pa->pa_pc, ih); + sc->sc_irqh = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, psp_sev_intr, + sc, sc->sc_dev.dv_xname); + if (sc->sc_irqh != NULL) + printf(": %s", intrstr); +} + +void +psp_pci_attach(struct ccp_softc *sc, struct pci_attach_args *pa) +{ + struct psp_attach_args arg; + struct device *self = (struct device *)sc; + bus_size_t reg_capabilities; + + memset(&arg, 0, sizeof(arg)); + arg.iot = sc->sc_iot; + arg.ioh = sc->sc_ioh; + arg.dmat = pa->pa_dmat; + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_AMD_17_CCP_1: + arg.version = 1; + reg_capabilities = PSPV1_REG_CAPABILITIES; + break; + case PCI_PRODUCT_AMD_17_3X_CCP: + arg.version = 2; + reg_capabilities = PSP_REG_CAPABILITIES; + break; + case PCI_PRODUCT_AMD_19_1X_PSP: + arg.version = 4; + reg_capabilities = PSP_REG_CAPABILITIES; + break; + default: + reg_capabilities = PSP_REG_CAPABILITIES; + break; + } + arg.capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + reg_capabilities); + + sc->sc_psp = config_found_sm(self, &arg, pspprint, pspsubmatch); + if (sc->sc_psp == NULL) { + pci_intr_disestablish(pa->pa_pc, sc->sc_irqh); + return; + } +} -- 2.20.1