Commit cb0003ae authored by Kunkun Jiang's avatar Kunkun Jiang Committed by Hao Chen
Browse files

irqchip: gicv3: Add workaround for hip09 erratum 162200806

driver inclusion
category: other
bugzilla: https://gitee.com/openeuler/kernel/issues/I9KBKD



-------------------------------------------------------------

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 12e11032
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -215,6 +215,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon      | Hip09           | #162200803      | N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon      | Hip09           | #162200806      | N/A                         |
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1  | E1003           | QCOM_FALKOR_ERRATUM_1003    |
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1  | E1009           | QCOM_FALKOR_ERRATUM_1009    |
+17 −0
Original line number Diff line number Diff line
@@ -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,
+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
@@ -42,6 +42,7 @@
#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)

@@ -1972,6 +1973,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",
@@ -2049,6 +2059,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,
	},
	{
	}
};