summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-10-29 21:16:37 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-10-29 21:16:37 +0000
commit7c3c367038a9258f03a26aacaa252e63951a4f02 (patch)
tree3d15257234a2aad06294ea1ed81741ba1ca4ffc0
parent0f0ae5717b36f68bd462b01b298b65ead5f85138 (diff)
Move psp(4) initialization from attach to device open.
In preparation for automatic loading of the AMD SEV firmware, factor out the code that initializes the PSP. As the firmware must be loaded before the initialization, delay initialization to first use of the PSP. Initialization is triggered by opening /dev/psp for the first time. A later diff will add firmware loading in a similar way. Also provide a ioctl(2) for initialization. Not used right now. Will be later used by vmd(8) to reset the PSP. from hshoexer@; OK mlarkin@
-rw-r--r--sys/dev/ic/psp.c124
-rw-r--r--sys/dev/ic/pspvar.h3
2 files changed, 76 insertions, 51 deletions
diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c
index e3eda5c96a8..ea1b561f3ef 100644
--- a/sys/dev/ic/psp.c
+++ b/sys/dev/ic/psp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: psp.c,v 1.6 2024/10/24 18:52:59 bluhm Exp $ */
+/* $OpenBSD: psp.c,v 1.7 2024/10/29 21:16:36 bluhm Exp $ */
/*
* Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
@@ -55,10 +55,14 @@ struct psp_softc {
caddr_t sc_tmr_kva;
struct rwlock sc_lock;
+
+ uint32_t sc_flags;
+#define PSPF_INITIALIZED 0x1
};
int psp_get_pstatus(struct psp_softc *, struct psp_platform_status *);
int psp_init(struct psp_softc *, struct psp_init *);
+int psp_reinit(struct psp_softc *);
int psp_match(struct device *, void *, void *);
void psp_attach(struct device *, struct device *, void *);
@@ -102,7 +106,6 @@ psp_attach(struct device *parent, struct device *self, void *aux)
struct psp_softc *sc = (struct psp_softc *)self;
struct psp_attach_args *arg = aux;
struct psp_platform_status pst;
- struct psp_init init;
size_t size;
int nsegs;
@@ -155,61 +158,16 @@ psp_attach(struct device *parent, struct device *self, void *aux)
printf(" uninitialized state");
goto fail_3;
}
- printf(" api %u.%u, build %u,",
+ printf(" api %u.%u, build %u, SEV, SEV-ES",
pst.api_major, pst.api_minor, pst.cfges_build >> 24);
- /*
- * 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(sc, &init)) {
- printf(" init");
- goto fail_7;
- }
-
- printf(" SEV");
-
- psp_get_pstatus(sc, &pst);
- 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);
+ /* enable interrupts */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_inten, -1);
printf("\n");
return;
-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:
@@ -300,10 +258,70 @@ psp_init(struct psp_softc *sc, struct psp_init *uinit)
wbinvd_on_all_cpus();
+ sc->sc_flags |= PSPF_INITIALIZED;
+
return (0);
}
int
+psp_reinit(struct psp_softc *sc)
+{
+ struct psp_init init;
+ size_t size;
+ int nsegs;
+
+ if (sc->sc_flags & PSPF_INITIALIZED) {
+ printf("%s: invalid flags 0x%x\n", __func__, sc->sc_flags);
+ return (EINVAL);
+ }
+
+ if (sc->sc_tmr_map != NULL)
+ return (EINVAL);
+
+ /*
+ * 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)
+ return (ENOMEM);
+
+ 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_0;
+
+ if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size,
+ &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0)
+ goto fail_1;
+
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva,
+ size, NULL, BUS_DMA_WAITOK) != 0)
+ goto fail_2;
+
+ 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(sc, &init))
+ goto fail_3;
+
+ return (0);
+
+fail_3:
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map);
+fail_2:
+ bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size);
+fail_1:
+ bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1);
+fail_0:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map);
+
+ return (ENOMEM);
+}
+
+int
psp_get_pstatus(struct psp_softc *sc, struct psp_platform_status *ustatus)
{
struct psp_platform_status *status;
@@ -638,6 +656,9 @@ pspopen(dev_t dev, int flag, int mode, struct proc *p)
if (sc == NULL)
return (ENXIO);
+ if (!(sc->sc_flags & PSPF_INITIALIZED))
+ return (psp_reinit(sc));
+
return (0);
}
@@ -666,6 +687,9 @@ pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
rw_enter_write(&sc->sc_lock);
switch (cmd) {
+ case PSP_IOC_INIT:
+ ret = psp_reinit(sc);
+ break;
case PSP_IOC_GET_PSTATUS:
ret = psp_get_pstatus(sc, (struct psp_platform_status *)data);
break;
diff --git a/sys/dev/ic/pspvar.h b/sys/dev/ic/pspvar.h
index c3bad155aca..48016134002 100644
--- a/sys/dev/ic/pspvar.h
+++ b/sys/dev/ic/pspvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pspvar.h,v 1.3 2024/10/24 18:52:59 bluhm Exp $ */
+/* $OpenBSD: pspvar.h,v 1.4 2024/10/29 21:16:36 bluhm Exp $ */
/*
* Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
@@ -249,6 +249,7 @@ struct psp_snp_platform_status {
#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_INIT _IO('P', 12)
#define PSP_IOC_GUEST_SHUTDOWN _IOW('P', 255, struct psp_guest_shutdown)
#ifdef _KERNEL