irqchip/gic-v3: Workaround Cavium erratum 38539 when reading GICD_TYPER2

Despite the architecture spec requiring that reserved registers in the GIC
distributor memory map are RES0 (and thus are not allowed to generate
an exception), the Cavium ThunderX (aka TX1) SoC explodes as such:

[ 0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[ 0.000000] GICv3: 128 SPIs implemented
[ 0.000000] GICv3: 0 Extended SPIs implemented
[ 0.000000] Internal error: synchronous external abort: 96000210 [#1] SMP
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-rc4-00035-g3cf6a3d5725f #7956
[ 0.000000] Hardware name: cavium,thunder-88xx (DT)
[ 0.000000] pstate: 60000085 (nZCv daIf -PAN -UAO)
[ 0.000000] pc : __raw_readl+0x0/0x8
[ 0.000000] lr : gic_init_bases+0x110/0x560
[ 0.000000] sp : ffff800011243d90
[ 0.000000] x29: ffff800011243d90 x28: 0000000000000000
[ 0.000000] x27: 0000000000000018 x26: 0000000000000002
[ 0.000000] x25: ffff8000116f0000 x24: ffff000fbe6a2c80
[ 0.000000] x23: 0000000000000000 x22: ffff010fdc322b68
[ 0.000000] x21: ffff800010a7a208 x20: 00000000009b0404
[ 0.000000] x19: ffff80001124dad0 x18: 0000000000000010
[ 0.000000] x17: 000000004d8d492b x16: 00000000f67eb9af
[ 0.000000] x15: ffffffffffffffff x14: ffff800011249908
[ 0.000000] x13: ffff800091243ae7 x12: ffff800011243af4
[ 0.000000] x11: ffff80001126e000 x10: ffff800011243a70
[ 0.000000] x9 : 00000000ffffffd0 x8 : ffff80001069c828
[ 0.000000] x7 : 0000000000000059 x6 : ffff8000113fb4d1
[ 0.000000] x5 : 0000000000000001 x4 : 0000000000000000
[ 0.000000] x3 : 0000000000000000 x2 : 0000000000000000
[ 0.000000] x1 : 0000000000000000 x0 : ffff8000116f000c
[ 0.000000] Call trace:
[ 0.000000] __raw_readl+0x0/0x8
[ 0.000000] gic_of_init+0x188/0x224
[ 0.000000] of_irq_init+0x200/0x3cc
[ 0.000000] irqchip_init+0x1c/0x40
[ 0.000000] init_IRQ+0x160/0x1d0
[ 0.000000] start_kernel+0x2ec/0x4b8
[ 0.000000] Code: a8c47bfd d65f03c0 d538d080 d65f03c0 (b9400000)

when reading the GICv4.1 GICD_TYPER2 register, which is unexpected...

Work around it by adding a new quirk for the following variants:

ThunderX: CN88xx
OCTEON TX: CN83xx, CN81xx
OCTEON TX2: CN93xx, CN96xx, CN98xx, CNF95xx*

and use this flag to avoid accessing GICD_TYPER2. Note that all
reserved registers (including redistributors and ITS) are impacted
by this erratum, but that only GICD_TYPER2 has to be worked around
so far.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Tested-by: Robert Richter <rrichter@marvell.com>
Tested-by: Mark Salter <msalter@redhat.com>
Tested-by: Tim Harvey <tharvey@gateworks.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Robert Richter <rrichter@marvell.com>
Link: https://lore.kernel.org/r/20191027144234.8395-11-maz@kernel.org
Link: https://lore.kernel.org/r/20200311115649.26060-1-maz@kernel.org

Changed files
+31 -1
Documentation
drivers
irqchip
+2
Documentation/arm64/silicon-errata.rst
··· 108 108 +----------------+-----------------+-----------------+-----------------------------+ 109 109 | Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 | 110 110 +----------------+-----------------+-----------------+-----------------------------+ 111 + | Cavium | ThunderX GICv3 | #38539 | N/A | 112 + +----------------+-----------------+-----------------+-----------------------------+ 111 113 | Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 | 112 114 +----------------+-----------------+-----------------+-----------------------------+ 113 115 | Cavium | ThunderX Core | #30115 | CAVIUM_ERRATUM_30115 |
+29 -1
drivers/irqchip/irq-gic-v3.c
··· 34 34 #define GICD_INT_NMI_PRI (GICD_INT_DEF_PRI & ~0x80) 35 35 36 36 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) 37 + #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) 37 38 38 39 struct redist_region { 39 40 void __iomem *redist_base; ··· 1465 1464 return true; 1466 1465 } 1467 1466 1467 + static bool gic_enable_quirk_cavium_38539(void *data) 1468 + { 1469 + struct gic_chip_data *d = data; 1470 + 1471 + d->flags |= FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539; 1472 + 1473 + return true; 1474 + } 1475 + 1468 1476 static bool gic_enable_quirk_hip06_07(void *data) 1469 1477 { 1470 1478 struct gic_chip_data *d = data; ··· 1511 1501 .iidr = 0x00000000, 1512 1502 .mask = 0xffffffff, 1513 1503 .init = gic_enable_quirk_hip06_07, 1504 + }, 1505 + { 1506 + /* 1507 + * Reserved register accesses generate a Synchronous 1508 + * External Abort. This erratum applies to: 1509 + * - ThunderX: CN88xx 1510 + * - OCTEON TX: CN83xx, CN81xx 1511 + * - OCTEON TX2: CN93xx, CN96xx, CN98xx, CNF95xx* 1512 + */ 1513 + .desc = "GICv3: Cavium erratum 38539", 1514 + .iidr = 0xa000034c, 1515 + .mask = 0xe8f00fff, 1516 + .init = gic_enable_quirk_cavium_38539, 1514 1517 }, 1515 1518 { 1516 1519 } ··· 1600 1577 pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32); 1601 1578 pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR); 1602 1579 1603 - gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2); 1580 + /* 1581 + * ThunderX1 explodes on reading GICD_TYPER2, in violation of the 1582 + * architecture spec (which says that reserved registers are RES0). 1583 + */ 1584 + if (!(gic_data.flags & FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539)) 1585 + gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2); 1604 1586 1605 1587 gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops, 1606 1588 &gic_data);