Module Name: src Committed By: tnn Date: Sat Nov 11 17:35:45 UTC 2023
Modified Files: src/sys/arch/arm/cortex: gicv3_its.c Log Message: gicv3_its: assorted minor improvements - KASSERT that the command queue is not stalled due to async error before issuing more commands. - implement gits_command_int under #if 0 (useful for troubleshooting) - protect command queue with its_lock consistently - KASSERT for 32-bit MSI that upper bits are 0 - KASSERT return value of gicv3_its_msi_alloc_lpi - KASSERT that safe conditions for writing to CBASER are met - move CWRITER initialization to before CBASER - fix alignment of tables for the 16KB page size case To generate a diff of this commit: cvs rdiff -u -r1.34 -r1.35 src/sys/arch/arm/cortex/gicv3_its.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gicv3_its.c diff -u src/sys/arch/arm/cortex/gicv3_its.c:1.34 src/sys/arch/arm/cortex/gicv3_its.c:1.35 --- src/sys/arch/arm/cortex/gicv3_its.c:1.34 Sun Oct 31 17:24:11 2021 +++ src/sys/arch/arm/cortex/gicv3_its.c Sat Nov 11 17:35:45 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3_its.c,v 1.34 2021/10/31 17:24:11 skrll Exp $ */ +/* $NetBSD: gicv3_its.c,v 1.35 2023/11/11 17:35:45 tnn Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.34 2021/10/31 17:24:11 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.35 2023/11/11 17:35:45 tnn Exp $"); #include <sys/param.h> #include <sys/kmem.h> @@ -117,6 +117,11 @@ gits_command(struct gicv3_its *its, cons cwriter = gits_read_8(its, GITS_CWRITER); woff = cwriter & GITS_CWRITER_Offset; +#ifdef DIAGNOSTIC + uint64_t creadr = gits_read_8(its, GITS_CREADR); + KASSERT(!ISSET(creadr, GITS_CREADR_Stalled)); + KASSERT(((woff + sizeof(cmd->dw)) & (its->its_cmd.len - 1)) != (creadr & GITS_CREADR_Offset)); +#endif uint64_t *dw = (uint64_t *)(its->its_cmd.base + woff); for (int i = 0; i < __arraycount(cmd->dw); i++) @@ -256,6 +261,26 @@ gits_command_sync(struct gicv3_its *its, gits_command(its, &cmd); } +#if 0 +static inline void +gits_command_int(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid) +{ + struct gicv3_its_command cmd; + + /* + * Translate the deviceid and eventid into an icid and pintid through + * the device table and ITT. Mark the pintid as pending + * on the redistributor. + * If the interrupt is not configured the command queue stalls. + */ + memset(&cmd, 0, sizeof(cmd)); + cmd.dw[0] = GITS_CMD_INT | ((uint64_t)deviceid << 32); + cmd.dw[1] = eventid; + + gits_command(its, &cmd); +} +#endif + static inline int gits_wait(struct gicv3_its *its) { @@ -358,8 +383,10 @@ gicv3_its_device_map(struct gicv3_its *i * Map the device to the ITT */ const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; + mutex_enter(its->its_lock); gits_command_mapd(its, devid, dev->dev_itt.segs[0].ds_addr, id_bits - 1, true); gits_wait(its); + mutex_exit(its->its_lock); return 0; } @@ -391,6 +418,7 @@ gicv3_its_msi_enable(struct gicv3_its *i pci_conf_write(pc, tag, off + PCI_MSI_MDATA64, lpi - its->its_pic->pic_irqbase); } else { + KASSERT((addr >> 32) == 0); pci_conf_write(pc, tag, off + PCI_MSI_MADDR, addr & 0xffffffff); pci_conf_write(pc, tag, off + PCI_MSI_MDATA, @@ -485,8 +513,10 @@ gicv3_its_msi_alloc(struct arm_pci_msi * return NULL; vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); + mutex_enter(its->its_lock); for (n = 0; n < *count; n++) { const int lpi = gicv3_its_msi_alloc_lpi(its, pa); + KASSERT(lpi >= 0); vectors[n] = ARM_PCI_INTR_MSI | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | __SHIFTIN(n, ARM_PCI_INTR_MSI_VEC) | @@ -508,6 +538,7 @@ gicv3_its_msi_alloc(struct arm_pci_msi * gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); } gits_wait(its); + mutex_exit(its->its_lock); return vectors; } @@ -555,8 +586,10 @@ gicv3_its_msix_alloc(struct arm_pci_msi } vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); + mutex_enter(its->its_lock); for (n = 0; n < *count; n++) { const int lpi = gicv3_its_msi_alloc_lpi(its, pa); + KASSERT(lpi >= 0); const int msix_vec = table_indexes ? table_indexes[n] : n; vectors[msix_vec] = ARM_PCI_INTR_MSIX | __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | @@ -578,6 +611,7 @@ gicv3_its_msix_alloc(struct arm_pci_msi gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); } gits_wait(its); + mutex_exit(its->its_lock); bus_space_unmap(bst, bsh, bsz); @@ -638,14 +672,17 @@ gicv3_its_command_init(struct gicv3_soft gicv3_dma_alloc(sc, &its->its_cmd, GITS_COMMANDS_SIZE, GITS_COMMANDS_ALIGN); + KASSERT((gits_read_4(its, GITS_CTLR) & GITS_CTLR_Enabled) == 0); + KASSERT((gits_read_4(its, GITS_CTLR) & GITS_CTLR_Quiescent) != 0); + cbaser = its->its_cmd.segs[0].ds_addr; cbaser |= __SHIFTIN(GITS_Cache_NORMAL_NC, GITS_CBASER_InnerCache); cbaser |= __SHIFTIN(GITS_Shareability_NS, GITS_CBASER_Shareability); cbaser |= __SHIFTIN((its->its_cmd.len / 4096) - 1, GITS_CBASER_Size); cbaser |= GITS_CBASER_Valid; - gits_write_8(its, GITS_CBASER, cbaser); gits_write_8(its, GITS_CWRITER, 0); + gits_write_8(its, GITS_CBASER, cbaser); } static void @@ -692,7 +729,7 @@ gicv3_its_table_init(struct gicv3_softc break; case GITS_Page_Size_16KB: page_size = 16384; - table_align = 4096; + table_align = 16384; break; case GITS_Page_Size_64KB: default: @@ -838,8 +875,10 @@ gicv3_its_set_affinity(void *priv, size_ if (its->its_cpuonline[cpu_index(ci)] == true) { const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); + mutex_enter(its->its_lock); gits_command_movi(its, devid, irq, cpu_index(ci)); gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); + mutex_exit(its->its_lock); } return 0;