Commit 716da49e authored by Kunkun Jiang's avatar Kunkun Jiang Committed by Dongxu Sun
Browse files

irqchip: gicv3: Add workaround for hip09 erratum 162200806

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: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarcaijian <caijian11@h-partners.com>
parent 8f27ed00
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -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,13 +333,28 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
		bool state = irq->pending_latch;

		if (vgic_direct_sgi_or_ppi(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);
			}
		}

		if (state)
			value |= (1U << i);
+1 −0
Original line number Diff line number Diff line
@@ -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;
+16 −0
Original line number Diff line number Diff line
@@ -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,
	},
	{
	}
};