From: Mike Larkin Subject: Re: AMD SEV psp version 1 attach To: Alexander Bluhm Cc: Mark Kettenis , tech@openbsd.org, hshoexer@genua.de Date: Thu, 24 Oct 2024 22:57:01 -0700 On Tue, Oct 22, 2024 at 01:24:49PM +0200, Alexander Bluhm wrote: > On Mon, Oct 21, 2024 at 02:22:14PM +0200, Alexander Bluhm wrote: > > As hshoexer@ has tested it I added version 4 PCI Id. > > One PCI_PRODUCT_AMD_19_1X_PSP was missing. New diff. > > ok? > I am ok with this. I suppose it's probably time for me to get some SEV capable hardware though. bluhm/hshoexer, do you have a list of compatible EPYC cpus? Are there any ryzen products that have SEV? ok mlarkin, in any case. > bluhm > > Index: dev/ic/psp.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/dev/ic/psp.c,v > diff -u -p -r1.5 psp.c > --- dev/ic/psp.c 4 Oct 2024 16:58:26 -0000 1.5 > +++ dev/ic/psp.c 22 Oct 2024 09:49:22 -0000 > @@ -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 > 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 > 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 > 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 > > 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 > 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, > 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); > Index: dev/ic/pspvar.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/dev/ic/pspvar.h,v > diff -u -p -r1.2 pspvar.h > --- dev/ic/pspvar.h 4 Sep 2024 07:45:08 -0000 1.2 > +++ dev/ic/pspvar.h 22 Oct 2024 09:49:22 -0000 > @@ -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 */ > Index: dev/pci/ccp_pci.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/ccp_pci.c,v > diff -u -p -r1.13 ccp_pci.c > --- dev/pci/ccp_pci.c 4 Sep 2024 07:45:08 -0000 1.13 > +++ dev/pci/ccp_pci.c 22 Oct 2024 09:49:22 -0000 > @@ -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, st > 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, st > 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 > } > Index: dev/pci/files.pci > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/files.pci,v > diff -u -p -r1.366 files.pci > --- dev/pci/files.pci 14 Aug 2024 14:40:46 -0000 1.366 > +++ dev/pci/files.pci 22 Oct 2024 09:49:22 -0000 > @@ -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 > Index: dev/pci/psp_pci.c > =================================================================== > RCS file: dev/pci/psp_pci.c > diff -N dev/pci/psp_pci.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ dev/pci/psp_pci.c 22 Oct 2024 09:50:05 -0000 > @@ -0,0 +1,126 @@ > +/* $OpenBSD$ */ > + > +/* > + * 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; > + } > +} >