Index | Thread | Search

From:
Hans-Jörg Höxer <hshoexer@genua.de>
Subject:
psp(4): Delay PSP initialization 1/3
To:
<tech@openbsd.org>
Date:
Fri, 25 Oct 2024 15:48:51 +0200

Download raw body.

Thread
Hi,

here are some diffs that implement automatic firmware loading for psp(4).
I will sent a diff for the required ports package to ports@.

Take care,
HJ.

--------------------------------------------------------------------
commit 02ff0b26487d9dea0e28a4baf532dac528fc9e5f
Author: Hans-Joerg Hoexer <hshoexer@genua.de>
Date:   Tue Jul 9 15:31:37 2024 +0200

    psp(4): Delay PSP initialization
    
    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.

diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c
index e3eda5c96a8..eebae8bab57 100644
--- a/sys/dev/ic/psp.c
+++ b/sys/dev/ic/psp.c
@@ -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,46 +158,9 @@ 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);
 
@@ -202,14 +168,6 @@ psp_attach(struct device *parent, struct device *self, void *aux)
 
 	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,9 +258,69 @@ 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)
 {
@@ -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..e7c776ea0cf 100644
--- a/sys/dev/ic/pspvar.h
+++ b/sys/dev/ic/pspvar.h
@@ -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