virt inclusion category: other bugzilla: https://gitee.com/openeuler/kernel/issues/I9SGLA
-------------------------------------------------------------
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.
Signed-off-by: Kunkun Jiang jiangkunkun@huawei.com Signed-off-by: Xiang Chen chenxiang66@hisilicon.com Signed-off-by: caijian caijian11@h-partners.com --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 24 ++++++++++++++++++++---- arch/arm64/kvm/vgic/vgic-mmio.h | 1 + drivers/irqchip/irq-gic-v3.c | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index bfaa3a452565..b6bdf22abab1 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -313,6 +313,7 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu, return 0; }
+#define VIRTUAL_SGI_PENDING_OFFSET 0x3F0 static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len) { @@ -332,12 +333,27 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu, bool state = irq->pending_latch;
if (vgic_direct_sgi_or_ppi(irq)) { - int err; - - err = irq_get_irqchip_state(irq->host_irq, + if (vgic_irq_is_sgi(irq->intid) && + (kvm_vgic_global_state.flags & + FLAGS_WORKAROUND_HIP09_ERRATUM_162200806)) { + struct its_vpe *vpe; + void *va; + u8 *ptr; + int mask; + + vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe; + mask = BIT(irq->intid % BITS_PER_BYTE); + va = page_address(vpe->vpt_page); + ptr = va + VIRTUAL_SGI_PENDING_OFFSET + + irq->intid / BITS_PER_BYTE; + state = *ptr & mask; + } else { + int err; + err = irq_get_irqchip_state(irq->host_irq, IRQCHIP_STATE_PENDING, &state); - WARN_ON(err); + WARN_ON(err); + } }
if (state) diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h index 7de51e059698..3c6bd9005acb 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.h +++ b/arch/arm64/kvm/vgic/vgic-mmio.h @@ -6,6 +6,7 @@ #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; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5371a8d8e027..8b2a45fbc9f7 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -37,6 +37,7 @@ #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) #define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) #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)
@@ -1710,6 +1711,15 @@ static bool gic_enable_quirk_hip09_162200803(void *data) return true; }
+static bool __maybe_unused 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", @@ -1752,6 +1762,12 @@ static const struct gic_quirk gic_quirks[] = { .mask = 0xffffffff, .init = gic_enable_quirk_hip09_162200803, }, + { + .desc = "GICv3: HIP09 erratum 162200806", + .iidr = 0x01050736, + .mask = 0xffffffff, + .init = gic_enable_quirk_hip09_162200806, + }, { } };