Index | Thread | Search

From:
Mike Larkin <mlarkin@nested.page>
Subject:
Re: psp(4): Delay PSP initialization 1/3
To:
tech@openbsd.org
Date:
Fri, 25 Oct 2024 09:25:04 -0700

Download raw body.

Thread
On Fri, Oct 25, 2024 at 03:48:51PM +0200, Hans-Jörg Höxer wrote:
> 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.
>

ok mlarkin

> --------------------------------------------------------------------
> 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