driver inclusion category: other bugzilla: https://gitee.com/openeuler/kernel/issues/I9KBKD
------------------------------------------------------------------
For gicv4.0 of hip10, it has a soc bug with vPE schedule: when multiple vPEs are sending vpe schedule/deschedule commands concurrently and repeatly, some vPE schedule command may not be scheduled, and it will cause the command timeout. To avoid the issue, limit the number of vLPI to 4096 for virtual machine.
Signed-off-by: Zhou Wang wangzhou1@hisilicon.com Signed-off-by: caijian caijian11@h-partners.com --- Documentation/arch/arm64/silicon-errata.rst | 2 ++ arch/arm64/kvm/vgic/vgic-init.c | 1 + arch/arm64/kvm/vgic/vgic-mmio-v3.c | 4 ++++ arch/arm64/kvm/vgic/vgic-mmio.h | 2 ++ drivers/irqchip/irq-gic-v3.c | 26 +++++++++++++++++++++ include/kvm/arm_vgic.h | 1 + include/linux/irqchip/arm-gic-v3.h | 2 ++ include/linux/irqchip/arm-vgic-info.h | 1 + 8 files changed, 39 insertions(+)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index 5230538cedfe..af8be06f11df 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -213,6 +213,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Hisilicon | SMMUv3 | #162100602 | HISILICON_ERRATUM_162100602 | +----------------+-----------------+-----------------+-----------------------------+ +| Hisilicon | Hip{10,10C} | #162200803 | N/A | ++----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo/Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 60f860a1dcaa..db5db9402c3a 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -615,6 +615,7 @@ int kvm_vgic_hyp_init(void) kvm_vgic_global_state.no_hw_deactivation = true; }
+ kvm_vgic_global_state.flags = gic_kvm_info->flags; switch (gic_kvm_info->type) { case GIC_V2: ret = vgic_v2_probe(gic_kvm_info); diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index d787de1e2c1c..909584cd21c7 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -83,6 +83,10 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu, if (vgic_has_its(vcpu->kvm)) { value |= (INTERRUPT_ID_BITS_ITS - 1) << 19; value |= GICD_TYPER_LPIS; + /* Limit the number of vlpis to 4096 */ + if (kvm_vgic_global_state.flags & FLAGS_WORKAROUND_HIP10_ERRATUM_162200803) + value |= 11 << GICD_TYPER_NUM_LPIS_SHIFT; + } else { value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19; } diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h index 5b490a4dfa5e..47372c2ceb8d 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.h +++ b/arch/arm64/kvm/vgic/vgic-mmio.h @@ -5,6 +5,8 @@ #ifndef __KVM_ARM_VGIC_MMIO_H__ #define __KVM_ARM_VGIC_MMIO_H__
+#define FLAGS_WORKAROUND_HIP10_ERRATUM_162200803 (1ULL << 4) + struct vgic_register_region { unsigned int reg_offset; unsigned int len; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index f8f2dd7264bb..dba80bfc23f0 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -41,6 +41,7 @@ #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) #define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) #define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 3) +#define FLAGS_WORKAROUND_HIP10_ERRATUM_162200803 (1ULL << 4)
#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
@@ -1991,6 +1992,15 @@ static bool rd_set_non_coherent(void *data) return true; }
+static bool gic_enable_quirk_hip10_10C_162200803(void *data) +{ + struct gic_chip_data *d = data; + + d->flags |= FLAGS_WORKAROUND_HIP10_ERRATUM_162200803; + + return true; +} + static const struct gic_quirk gic_quirks[] = { { .desc = "GICv3: Qualcomm MSM8996 broken firmware", @@ -2062,6 +2072,18 @@ static const struct gic_quirk gic_quirks[] = { .property = "dma-noncoherent", .init = rd_set_non_coherent, }, + { + .desc = "GICv3: HIP10 erratum 162200803", + .iidr = 0x01050736, + .mask = 0xffffffff, + .init = gic_enable_quirk_hip10_10C_162200803, + }, + { + .desc = "GICv3: HIP10C erratum 162200803", + .iidr = 0x00061736, + .mask = 0xffffffff, + .init = gic_enable_quirk_hip10_10C_162200803, + }, { } }; @@ -2373,6 +2395,8 @@ static void __init gic_of_setup_kvm_info(struct device_node *node) #ifdef CONFIG_VIRT_VTIMER_IRQ_BYPASS gic_v3_kvm_info.has_vtimer = gic_data.rdists.has_vtimer; #endif + if (gic_v3_kvm_info.has_v4 && !gic_v3_kvm_info.has_v4_1) + gic_v3_kvm_info.flags = gic_data.flags; vgic_set_kvm_info(&gic_v3_kvm_info); }
@@ -2725,6 +2749,8 @@ static void __init gic_acpi_setup_kvm_info(void) #ifdef CONFIG_VIRT_VTIMER_IRQ_BYPASS gic_v3_kvm_info.has_vtimer = gic_data.rdists.has_vtimer; #endif + if (gic_v3_kvm_info.has_v4 && !gic_v3_kvm_info.has_v4_1) + gic_v3_kvm_info.flags = gic_data.flags; vgic_set_kvm_info(&gic_v3_kvm_info); }
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 0cbcf4e06761..0b734d6f3d21 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -126,6 +126,7 @@ struct vgic_global { struct static_key_false gicv3_cpuif;
u32 ich_vtr_el2; + u64 flags; };
extern struct vgic_global kvm_vgic_global_state; diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 7a91ec9e2afd..ccf464326be7 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -81,6 +81,8 @@ #define GICD_CTLR_ENABLE_SS_G1 (1U << 1) #define GICD_CTLR_ENABLE_SS_G0 (1U << 0)
+#define GICD_TYPER_NUM_LPIS_SHIFT 11 + #define GICD_TYPER_RSS (1U << 26) #define GICD_TYPER_LPIS (1U << 17) #define GICD_TYPER_MBIS (1U << 16) diff --git a/include/linux/irqchip/arm-vgic-info.h b/include/linux/irqchip/arm-vgic-info.h index aa2e9eaa9ad9..eb358cea426d 100644 --- a/include/linux/irqchip/arm-vgic-info.h +++ b/include/linux/irqchip/arm-vgic-info.h @@ -38,6 +38,7 @@ struct gic_kvm_info { /* vtimer irqbypass support */ bool has_vtimer; #endif + u64 flags; /* Deactivation impared, subpar stuff */ bool no_hw_deactivation; };