From 5182d6584197c6cdc1a21486553ae5a84e214a88 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Fri, 29 Aug 2025 11:18:28 +0800 Subject: [PATCH 1/2] irqchip/gicv3-its: Add workaround for HIP09/HIP10/HIP10C/HIP12 erratum 162100803/162200807/162400807/165010802 commit 36fc586982d7eb2e7893fef8e00c78db4d2b4c41 openEuler HIP09/HIP10/HIP10C ITS have a problem, an ITS RAS will be reported in some cases when GICv4.1 is enable. A workaround is that set ITT size to max value(0xf) when doing MAPD with V = 1, and avoid to send MAPD with V = 0 to hardware. Just clear V field in ITS device table and clear ITS cache to implement MAPD with V = 0 instead. Signed-off-by: Zhou Wang Reviewed-by: Nianyao Tang Reviewed-by: Kunkun Jiang Signed-off-by: Jian Cai Reviewed-by: Xie Xiaodong --- arch/arm64/Kconfig | 13 ++++ drivers/irqchip/irq-gic-v3-its.c | 120 +++++++++++++++++++++++++++---- 2 files changed, 119 insertions(+), 14 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 93e47a234ba9..a1d53a1c5c44 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -791,6 +791,19 @@ config HISILICON_ERRATUM_162100602 If unsure, say Y. +config HISILICON_ERRATUM_162100803 + bool "Hip09/10/10c/12 162100803/162200807/162400807/165010802 erratum support" + default y + help + There is a hardware conflict between vSGI and vLPI, fix it by + configure a max ITS ITT size 0xf when doing MAPD with V = 1, clear V + field in ITS device table and clear ITS cache to implement MAPD with + V = 0 instead. Hip09/10/10c/12 have this same problem, just use + HISILICON_ERRATUM_162100803 as the compile macro and + ITS_FLAGS_WORKAROUND_HISILICON_162100803 as ITS flag for convenience + + If unsure, say Y. + config QCOM_FALKOR_ERRATUM_1003 bool "Falkor E1003: Incorrect translation due to ASID change" default y diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 9e421c7f1c07..e08ca4d4839d 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -192,6 +192,7 @@ static int probe_devid_pool_one(void) #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) #define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 3) +#define ITS_FLAGS_WORKAROUND_HISILICON_162100803 (1ULL << 5) #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) @@ -878,7 +879,12 @@ static struct its_collection *its_build_mapd_cmd(struct its_node *its, its_encode_cmd(cmd, GITS_CMD_MAPD); its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id); - its_encode_size(cmd, size - 1); + + if (its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100803) + its_encode_size(cmd, 0xf); + else + its_encode_size(cmd, size - 1); + its_encode_itt(cmd, itt_addr); its_encode_valid(cmd, desc->its_mapd_cmd.valid); @@ -887,6 +893,61 @@ static struct its_collection *its_build_mapd_cmd(struct its_node *its, return NULL; } +static struct its_baser *its_get_baser(struct its_node *its, u32 type) +{ + int i; + + for (i = 0; i < GITS_BASER_NR_REGS; i++) { + if (GITS_BASER_TYPE(its->tables[i].val) == type) + return &its->tables[i]; + } + + return NULL; +} + +static struct its_collection +*its_build_mapd_cmd_hisi_quirk(struct its_node *its, struct its_cmd_block *cmd, + struct its_cmd_desc *desc) +{ + struct its_baser *baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE); + u32 devid = desc->its_mapd_cmd.dev->device_id; + void *base = baser->base; + u32 *dt_entry; + void __iomem *its_func_en = its->sgir_base + 0x80; + u32 tmp, tmp1, mask = 1 << 19; + int i = 100; + + /* + * The device table is flat. Modify v to 0 in the dt entry of devid, + * dt entry format as below: word0: [0-31] ITT address; word1: [0-7] + * ITT address, [8-12]: ITT size, [13]: V + */ + dt_entry = (u32 *)(base + devid * 8 + 4); + *dt_entry &= ~(1 << 13); + + dsb(ishst); + + /* + * Invalidate cache by a private register GITS_FUNC_EN, whose offset + * is 0x20080 of ITS base address. GICv4.1 already maps sgir_base + * (offset is 0x20000), so address of GITS_FUNC_EN can be got by + * sgir_base + 0x80. Bit 16 is used to clear DT cache, the flip of + * bit 19 indicates that DT cache has been cleared. + */ + while (--i) { + tmp = readl_relaxed(its_func_en) & mask; + writel_relaxed(tmp | (1 << 16), its_func_en); + tmp1 = readl_relaxed(its_func_en) & mask; + if (tmp != tmp1) + break; + } + + if (i == 0) + WARN_ON(1); + + return NULL; +} + static struct its_collection *its_build_mapc_cmd(struct its_node *its, struct its_cmd_block *cmd, struct its_cmd_desc *desc) @@ -1471,11 +1532,18 @@ static void its_send_inv(struct its_device *dev, u32 event_id) static void its_send_mapd(struct its_device *dev, int valid) { struct its_cmd_desc desc; + its_cmd_builder_t fn; + + if (dev->its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100803 && + valid == 0) + fn = its_build_mapd_cmd_hisi_quirk; + else + fn = its_build_mapd_cmd; desc.its_mapd_cmd.dev = dev; desc.its_mapd_cmd.valid = !!valid; - its_send_single_command(dev->its, its_build_mapd_cmd, &desc); + its_send_single_command(dev->its, fn, &desc); } static void its_send_mapc(struct its_node *its, struct its_collection *col, @@ -3546,18 +3614,6 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id) return its_dev; } -static struct its_baser *its_get_baser(struct its_node *its, u32 type) -{ - int i; - - for (i = 0; i < GITS_BASER_NR_REGS; i++) { - if (GITS_BASER_TYPE(its->tables[i].val) == type) - return &its->tables[i]; - } - - return NULL; -} - static bool its_alloc_table_entry(struct its_node *its, struct its_baser *baser, u32 id) { @@ -5085,6 +5141,16 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data) return true; } +static bool __maybe_unused its_enable_quirk_162100803(void *data) +{ + struct its_node *its = data; + + if (is_v4_1(its)) + its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100803; + + return true; +} + static const struct gic_quirk its_quirks[] = { #ifdef CONFIG_CAVIUM_ERRATUM_22375 { @@ -5138,6 +5204,32 @@ static const struct gic_quirk its_quirks[] = { .mask = 0xffffffff, .init = its_enable_quirk_hip09_162100801, }, +#endif +#ifdef CONFIG_HISILICON_ERRATUM_162100803 + { + .desc = "ITS: Hip09 erratum 162100803", + .iidr = 0x00051736, + .mask = 0xffffffff, + .init = its_enable_quirk_162100803, + }, + { + .desc = "ITS: Hip10 erratum 162200807", + .iidr = 0x01051736, + .mask = 0xffffffff, + .init = its_enable_quirk_162100803, + }, + { + .desc = "ITS: Hip10c erratum 162400807", + .iidr = 0x00061736, + .mask = 0xffffffff, + .init = its_enable_quirk_162100803, + }, + { + .desc = "ITS: Hip12 erratum 165010802", + .iidr = 0x00070736, + .mask = 0xffffffff, + .init = its_enable_quirk_162100803, + }, #endif { } -- Gitee From 3909f65b31dfd9a3808bf584667b5b1bcb15559a Mon Sep 17 00:00:00 2001 From: Jian Cai Date: Fri, 29 Aug 2025 11:21:23 +0800 Subject: [PATCH 2/2] tencentconfig: Add CONFIG_HISILICON_ERRATUM_162100803 commit d2d1851235f2031f692eec5639bfb362d996bf1e openEuler Add CONFIG_HISILICON_ERRATUM_162100803 into tencent.config. Signed-off-by: Jian Cai Signed-off-by: Xie Xiaodong --- arch/arm64/configs/tencent.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/tencent.config b/arch/arm64/configs/tencent.config index ef4fb41bfb01..d919b2cd9b5f 100644 --- a/arch/arm64/configs/tencent.config +++ b/arch/arm64/configs/tencent.config @@ -1510,3 +1510,4 @@ CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y CONFIG_HISI_L3T_PMU=m CONFIG_HISI_LPDDRC_PMU=m CONFIG_HISILICON_HW_METRIC=y +CONFIG_HISILICON_ERRATUM_162100803=y -- Gitee