Skip to content

Commit

Permalink
irqchip/gicv3-its: Add workaround for hip09 ITS erratum 162100801
Browse files Browse the repository at this point in the history
When enabling GICv4.1 in hip09, VMAPP fails to clear some caches during
the unmap operation, which can causes vSGIs to be lost.

To fix the issue, invalidate the related vPE cache through GICR_INVALLR
after VMOVP.

Suggested-by: Marc Zyngier <maz@kernel.org>
Co-developed-by: Nianyao Tang <tangnianyao@huawei.com>
Signed-off-by: Nianyao Tang <tangnianyao@huawei.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Marc Zyngier <maz@kernel.org>
  • Loading branch information
Zhou Wang authored and Thomas Gleixner committed Nov 26, 2024
1 parent 12aaf67 commit f82e62d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
2 changes: 2 additions & 0 deletions Documentation/arch/arm64/silicon-errata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ stable kernels.
| Hisilicon | Hip{08,09,10,10C| #162001900 | N/A |
| | ,11} SMMU PMCG | | |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
+----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
+----------------+-----------------+-----------------+-----------------------------+
Expand Down
11 changes: 11 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,17 @@ config HISILICON_ERRATUM_161600802

If unsure, say Y.

config HISILICON_ERRATUM_162100801
bool "Hip09 162100801 erratum support"
default y
help
When enabling GICv4.1 in hip09, VMAPP will fail to clear some caches
during unmapping operation, which will cause some vSGIs lost.
To fix the issue, invalidate related vPE cache through GICR_INVALLR
after VMOVP.

If unsure, say Y.

config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
Expand Down
50 changes: 39 additions & 11 deletions drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
#define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3)
#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4)

#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
Expand All @@ -64,6 +65,7 @@ static u32 lpi_id_bits;
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)

static u8 __ro_after_init lpi_prop_prio;
static struct its_node *find_4_1_its(void);

/*
* Collection structure - just an ID, and a redistributor address to
Expand Down Expand Up @@ -3883,13 +3885,28 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
}

static void its_vpe_4_1_invall_locked(int cpu, struct its_vpe *vpe)
{
void __iomem *rdbase;
u64 val;

val = GICR_INVALLR_V;
val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);

guard(raw_spinlock)(&gic_data_rdist_cpu(cpu)->rd_lock);
rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
gic_write_lpir(val, rdbase + GICR_INVALLR);
wait_for_syncr(rdbase);
}

static int its_vpe_set_affinity(struct irq_data *d,
const struct cpumask *mask_val,
bool force)
{
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
unsigned int from, cpu = nr_cpu_ids;
struct cpumask *table_mask;
struct its_node *its;
unsigned long flags;

/*
Expand Down Expand Up @@ -3952,6 +3969,11 @@ static int its_vpe_set_affinity(struct irq_data *d,
vpe->col_idx = cpu;

its_send_vmovp(vpe);

its = find_4_1_its();
if (its && its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100801)
its_vpe_4_1_invall_locked(cpu, vpe);

its_vpe_db_proxy_move(vpe, from, cpu);

out:
Expand Down Expand Up @@ -4259,22 +4281,12 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,

static void its_vpe_4_1_invall(struct its_vpe *vpe)
{
void __iomem *rdbase;
unsigned long flags;
u64 val;
int cpu;

val = GICR_INVALLR_V;
val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);

/* Target the redistributor this vPE is currently known on */
cpu = vpe_to_cpuid_lock(vpe, &flags);
raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
gic_write_lpir(val, rdbase + GICR_INVALLR);

wait_for_syncr(rdbase);
raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
its_vpe_4_1_invall_locked(cpu, vpe);
vpe_to_cpuid_unlock(vpe, flags);
}

Expand Down Expand Up @@ -4867,6 +4879,14 @@ static bool its_set_non_coherent(void *data)
return true;
}

static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
{
struct its_node *its = data;

its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801;
return true;
}

static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
Expand Down Expand Up @@ -4913,6 +4933,14 @@ static const struct gic_quirk its_quirks[] = {
.init = its_enable_quirk_hip07_161600802,
},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_162100801
{
.desc = "ITS: Hip09 erratum 162100801",
.iidr = 0x00051736,
.mask = 0xffffffff,
.init = its_enable_quirk_hip09_162100801,
},
#endif
#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
{
.desc = "ITS: Rockchip erratum RK3588001",
Expand Down

0 comments on commit f82e62d

Please sign in to comment.