diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index 11645181d7f274e6f39cc310af1ee7f4f59a9a9c..17c6360686034a9eb26a164369f0d3b487887deb 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -213,6 +213,10 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Hisilicon | SMMUv3 | #162100602 | HISILICON_ERRATUM_162100602 | +----------------+-----------------+-----------------+-----------------------------+ +| Hisilicon | Hip09 | #162200803 | HISILICON_ERRATUM_162200803 | ++----------------+-----------------+-----------------+-----------------------------+ +| Hisilicon | Hip09 | #162200806 | HISILICON_ERRATUM_162200806 | ++----------------+-----------------+-----------------+-----------------------------+ | 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/Kconfig b/arch/arm64/Kconfig index 890461d3f5e5dddc4cd936fc3afc588563d0d751..d09dc7a9818f2faa3241347356fe79d14da0ab29 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1236,6 +1236,27 @@ config HISILICON_ERRATUM_162102203 If unsure, say N. +config HISILICON_ERRATUM_162200803 + bool "Hisilicon erratum 162200803" + default y + help + When multiple vPEs are sending vPE schedule/de-schedule commands + concurrently and repeatedly, some vPE schedule command may be not + scheduled, which causes the command timeout. + Limit the number of vLPI to 4096 for virtual machine. + + If unsure, say Y. + +config HISILICON_ERRATUM_162200806 + bool "Hisilicon erratum 162200806" + default y + help + For gicv4.1 of hip09, it has a soc bug with the status of + vpe pending is inaccurate, so read the pending status from + memory to fix the issue. + + If unsure, say Y. + config QCOM_FALKOR_ERRATUM_1003 bool "Falkor E1003: Incorrect translation due to ASID change" default y diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index dbbad2e2d0574490c31fc3355d09580dc74e2a6b..c4e235b7eac415bd4a7926fd977f82b04ff63a68 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -434,6 +434,8 @@ CONFIG_HISILICON_ERRATUM_162102203=y # CONFIG_HISILICON_ERRATUM_1980005 is not set CONFIG_HISILICON_ERRATUM_162100801=y CONFIG_HISILICON_ERRATUM_162100602=y +CONFIG_HISILICON_ERRATUM_162200803=y +CONFIG_HISILICON_ERRATUM_162200806=y CONFIG_QCOM_FALKOR_ERRATUM_1003=y CONFIG_QCOM_FALKOR_ERRATUM_1009=y CONFIG_QCOM_QDF2400_ERRATUM_0065=y diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 0d9d71dc338eecc1cb9cfd4b304dc4918a18a67b..a8590ca54ad2cffd4f60d390e8b5797debb95f7e 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 3dd779cae09f430fb3fe283f7cf204b416e25cb8..09db8c8f8d440ba0cc464924193a1054ac7a922f 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_HIP09_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.c b/arch/arm64/kvm/vgic/vgic-mmio.c index 59b81e5ce1d8a3cb5ff11b0261a6db90dda7d6f4..56549ee4313c1d3a3ce3334594bc2fd3e754753d 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.c +++ b/arch/arm64/kvm/vgic/vgic-mmio.c @@ -228,6 +228,7 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, return 0; } +#define VIRTUAL_SGI_PENDING_OFFSET 0x3F0 static unsigned long __read_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len, bool is_user) @@ -235,6 +236,7 @@ static unsigned long __read_pending(struct kvm_vcpu *vcpu, u32 intid = VGIC_ADDR_TO_INTID(addr, 1); u32 value = 0; int i; + struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe; /* Loop over all IRQs affected by this read */ for (i = 0; i < len * 8; i++) { @@ -255,6 +257,21 @@ static unsigned long __read_pending(struct kvm_vcpu *vcpu, if (vgic_direct_sgi_or_ppi(irq)) { int err; + if (irq->hw && vgic_irq_is_sgi(irq->intid) && + (kvm_vgic_global_state.flags & + FLAGS_WORKAROUND_HIP09_ERRATUM_162200806)) { + void *va; + u8 *ptr; + int mask; + bool is_pending; + + mask = BIT(irq->intid % BITS_PER_BYTE); + va = page_address(vpe->vpt_page); + ptr = va + VIRTUAL_SGI_PENDING_OFFSET + + irq->intid / BITS_PER_BYTE; + is_pending = *ptr & mask; + } + val = false; err = irq_get_irqchip_state(irq->host_irq, IRQCHIP_STATE_PENDING, diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h index 5b490a4dfa5e978800193775ab804e04bd0bf306..0477ec95e96cc979659368b6027995f5e2fd4d6a 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.h +++ b/arch/arm64/kvm/vgic/vgic-mmio.h @@ -5,6 +5,9 @@ #ifndef __KVM_ARM_VGIC_MMIO_H__ #define __KVM_ARM_VGIC_MMIO_H__ +#define FLAGS_WORKAROUND_HIP09_ERRATUM_162200803 (1ULL << 4) +#define FLAGS_WORKAROUND_HIP09_ERRATUM_162200806 (1ULL << 5) + 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 8bb42ac8fb2a28c92f2b852d5856d690bf9f0108..c8d2878d73d3ff1e893c97e90c5535e54e7bf403 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -41,6 +41,8 @@ #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_HIP09_ERRATUM_162200803 (1ULL << 4) +#define FLAGS_WORKAROUND_HIP09_ERRATUM_162200806 (1ULL << 5) #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) @@ -1962,6 +1964,24 @@ static bool rd_set_non_coherent(void *data) return true; } +static bool gic_enable_quirk_hip09_162200803(void *data) +{ + struct gic_chip_data *d = data; + + d->flags |= FLAGS_WORKAROUND_HIP09_ERRATUM_162200803; + + return true; +} + +static bool gic_enable_quirk_hip09_162200806(void *data) +{ + struct gic_chip_data *d = data; + + d->flags |= FLAGS_WORKAROUND_HIP09_ERRATUM_162200806; + + return true; +} + static const struct gic_quirk gic_quirks[] = { { .desc = "GICv3: Qualcomm MSM8996 broken firmware", @@ -2033,6 +2053,22 @@ static const struct gic_quirk gic_quirks[] = { .property = "dma-noncoherent", .init = rd_set_non_coherent, }, +#ifdef CONFIG_HISILICON_ERRATUM_162200803 + { + .desc = "GICv3: HIP09 erratum 162200803", + .iidr = 0x01050736, + .mask = 0xffffffff, + .init = gic_enable_quirk_hip09_162200803, + }, +#endif +#ifdef CONFIG_HISILICON_ERRATUM_162200806 + { + .desc = "GICv3: HIP09 erratum 162200806", + .iidr = 0x01050736, + .mask = 0xffffffff, + .init = gic_enable_quirk_hip09_162200806, + }, +#endif { } }; @@ -2344,6 +2380,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.flags = gic_data.flags; vgic_set_kvm_info(&gic_v3_kvm_info); } @@ -2696,6 +2734,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.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 0cbcf4e06761023c0b3394a20c88eb7aa063e7e1..0b734d6f3d214ceddd093bd9923d0700f6157806 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 7a91ec9e2afd1f299ab02ab5cc9d281d7a755f95..ccf464326be717d81eef38cf2a57da5ff7a7844f 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 aa2e9eaa9ad95f252731d2a0b512c1b409ee8192..eb358cea426d45e15b59fccd3ed70c36056e87fc 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; };