irqchip/gic-v4: Disable redistributors' view of the VPE table at boot time
authorMarc Zyngier <maz@kernel.org>
Thu, 16 Dec 2021 14:32:27 +0000 (14:32 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 16 Dec 2021 15:19:52 +0000 (15:19 +0000)
Jay Chen reported that using a kdump kernel on a GICv4.1 system
results in a RAS error being delivered when the secondary kernel
configures the ITS's view of the new VPE table.

As it turns out, that's because each RD still has a pointer to
the previous instance of the VPE table, and that particular
implementation is very upset by seeing two bits of the HW that
should point to the same table with different values.

To solve this, let's invalidate any reference that any RD has to
the VPE table when discovering the RDs. The ITS can then be
programmed as expected.

Reported-by: Jay Chen <jkchen@linux.alibaba.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Link: https://lore.kernel.org/r/20211214064716.21407-1-jkchen@linux.alibaba.com
Link: https://lore.kernel.org/r/20211216144804.1578566-1-maz@kernel.org
drivers/irqchip/irq-gic-v3.c

index daec3309b014dd09e3cabba983f66b034c5ba543..86397522e7864535a7d3d5320cf301dec7a801a4 100644 (file)
@@ -920,6 +920,22 @@ static int __gic_update_rdist_properties(struct redist_region *region,
 {
        u64 typer = gic_read_typer(ptr + GICR_TYPER);
 
+       /* Boot-time cleanip */
+       if ((typer & GICR_TYPER_VLPIS) && (typer & GICR_TYPER_RVPEID)) {
+               u64 val;
+
+               /* Deactivate any present vPE */
+               val = gicr_read_vpendbaser(ptr + SZ_128K + GICR_VPENDBASER);
+               if (val & GICR_VPENDBASER_Valid)
+                       gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast,
+                                             ptr + SZ_128K + GICR_VPENDBASER);
+
+               /* Mark the VPE table as invalid */
+               val = gicr_read_vpropbaser(ptr + SZ_128K + GICR_VPROPBASER);
+               val &= ~GICR_VPROPBASER_4_1_VALID;
+               gicr_write_vpropbaser(val, ptr + SZ_128K + GICR_VPROPBASER);
+       }
+
        gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
 
        /* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */