From 48352e7ba586ecd6635a13b887330dc49cbd8d63 Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 1 Aug 2022 20:48:19 +0000 Subject: [PATCH] Allocate memory for collection translation tables for hardware that needs it. ok patrick@ --- sys/arch/arm64/dev/agintc.c | 86 +++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c index 3eefae7135c..7a8fdf08eda 100644 --- a/sys/arch/arm64/dev/agintc.c +++ b/sys/arch/arm64/dev/agintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agintc.c,v 1.39 2022/07/16 12:02:28 kettenis Exp $ */ +/* $OpenBSD: agintc.c,v 1.40 2022/08/01 20:48:19 kettenis Exp $ */ /* * Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn * Copyright (c) 2018 Mark Kettenis @@ -1248,6 +1248,7 @@ agintc_send_ipi(struct cpu_info *ci, int id) #define GITS_CTLR_ENABLED (1UL << 0) #define GITS_TYPER 0x0008 #define GITS_TYPER_CIL (1ULL << 36) +#define GITS_TYPER_CIDBITS(x) (((x) >> 32) & 0xf) #define GITS_TYPER_HCC(x) (((x) >> 24) & 0xff) #define GITS_TYPER_PTA (1ULL << 19) #define GITS_TYPER_DEVBITS(x) (((x) >> 13) & 0x1f) @@ -1265,7 +1266,8 @@ agintc_send_ipi(struct cpu_info *ci, int id) #define GITS_BASER_IC_NORM_NC (1ULL << 59) #define GITS_BASER_TYPE_MASK (7ULL << 56) #define GITS_BASER_TYPE_DEVICE (1ULL << 56) -#define GITS_BASER_DTE_SZ(x) (((x) >> 48) & 0x1f) +#define GITS_BASER_TYPE_COLL (4ULL << 56) +#define GITS_BASER_TTE_SZ(x) (((x) >> 48) & 0x1f) #define GITS_BASER_PGSZ_MASK (3ULL << 8) #define GITS_BASER_PGSZ_4K (0ULL << 8) #define GITS_BASER_PGSZ_16K (1ULL << 8) @@ -1329,6 +1331,10 @@ struct agintc_msi_softc { struct agintc_dmamem *sc_dtt; size_t sc_dtt_pgsz; uint8_t sc_dte_sz; + int sc_cidbits; + struct agintc_dmamem *sc_ctt; + size_t sc_ctt_pgsz; + uint8_t sc_cte_sz; uint8_t sc_ite_sz; LIST_HEAD(, agintc_msi_device) sc_msi_devices; @@ -1386,13 +1392,16 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux) } typer = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_TYPER); - if ((typer & GITS_TYPER_PHYS) == 0 || typer & GITS_TYPER_PTA || - GITS_TYPER_HCC(typer) < ncpus || typer & GITS_TYPER_CIL) { + if ((typer & GITS_TYPER_PHYS) == 0 || typer & GITS_TYPER_PTA) { printf(": unsupported type 0x%016llx\n", typer); goto unmap; } sc->sc_ite_sz = GITS_TYPER_ITE_SZ(typer) + 1; sc->sc_devbits = GITS_TYPER_DEVBITS(typer) + 1; + if (typer & GITS_TYPER_CIL) + sc->sc_cidbits = GITS_TYPER_CIDBITS(typer) + 1; + else + sc->sc_cidbits = 16; sc->sc_nlpi = agintc_sc->sc_nlpi; sc->sc_lpi = mallocarray(sc->sc_nlpi, sizeof(void *), M_DEVBUF, @@ -1424,19 +1433,19 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux) (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_64K); baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); if ((baser & GITS_BASER_PGSZ_MASK) == GITS_BASER_PGSZ_64K) - goto found; + goto dfound; bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_16K); baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); if ((baser & GITS_BASER_PGSZ_MASK) == GITS_BASER_PGSZ_16K) - goto found; + goto dfound; bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_4K); baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); - found: + dfound: switch (baser & GITS_BASER_PGSZ_MASK) { case GITS_BASER_PGSZ_4K: sc->sc_dtt_pgsz = PAGE_SIZE; @@ -1450,7 +1459,7 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux) } /* Calculate table size. */ - sc->sc_dte_sz = GITS_BASER_DTE_SZ(baser) + 1; + sc->sc_dte_sz = GITS_BASER_TTE_SZ(baser) + 1; size = (1ULL << sc->sc_devbits) * sc->sc_dte_sz; size = roundup(size, sc->sc_dtt_pgsz); @@ -1470,6 +1479,67 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux) dtt_pa | (size / sc->sc_dtt_pgsz) - 1 | GITS_BASER_VALID); } + /* Set up collection translation table. */ + for (i = 0; i < GITS_NUM_BASER; i++) { + uint64_t baser; + paddr_t ctt_pa; + size_t size; + + baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); + if ((baser & GITS_BASER_TYPE_MASK) != GITS_BASER_TYPE_COLL) + continue; + + /* Determine the maximum supported page size. */ + bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), + (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_64K); + baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); + if ((baser & GITS_BASER_PGSZ_MASK) == GITS_BASER_PGSZ_64K) + goto cfound; + + bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), + (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_16K); + baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); + if ((baser & GITS_BASER_PGSZ_MASK) == GITS_BASER_PGSZ_16K) + goto cfound; + + bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), + (baser & ~GITS_BASER_PGSZ_MASK) | GITS_BASER_PGSZ_4K); + baser = bus_space_read_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i)); + + cfound: + switch (baser & GITS_BASER_PGSZ_MASK) { + case GITS_BASER_PGSZ_4K: + sc->sc_ctt_pgsz = PAGE_SIZE; + break; + case GITS_BASER_PGSZ_16K: + sc->sc_ctt_pgsz = 4 * PAGE_SIZE; + break; + case GITS_BASER_PGSZ_64K: + sc->sc_ctt_pgsz = 16 * PAGE_SIZE; + break; + } + + /* Calculate table size. */ + sc->sc_cte_sz = GITS_BASER_TTE_SZ(baser) + 1; + size = (1ULL << sc->sc_cidbits) * sc->sc_cte_sz; + size = roundup(size, sc->sc_ctt_pgsz); + + /* Allocate table. */ + sc->sc_ctt = agintc_dmamem_alloc(sc->sc_dmat, + size, sc->sc_ctt_pgsz); + if (sc->sc_ctt == NULL) { + printf(": can't alloc translation table\n"); + goto unmap; + } + + /* Configure table. */ + ctt_pa = AGINTC_DMA_DVA(sc->sc_ctt); + KASSERT((ctt_pa & GITS_BASER_PA_MASK) == ctt_pa); + bus_space_write_8(sc->sc_iot, sc->sc_ioh, GITS_BASER(i), + GITS_BASER_IC_NORM_NC | baser & GITS_BASER_PGSZ_MASK | + ctt_pa | (size / sc->sc_ctt_pgsz) - 1 | GITS_BASER_VALID); + } + /* Enable ITS. */ bus_space_write_4(sc->sc_iot, sc->sc_ioh, GITS_CTLR, GITS_CTLR_ENABLED); -- 2.20.1