summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2019-10-03 17:46:39 +0200
committerPeter Maydell <peter.maydell@linaro.org>2019-10-15 18:09:02 +0100
commitf6530926e2310147a7844a3e663230d47b3d7333 (patch)
tree72d1cedab2f00fff2f123803499c2b72ede04745 /target
parentf363d039e883ce6eb2a4fd09b04a38cbb6c95d43 (diff)
downloadqemu-f6530926e2310147a7844a3e663230d47b3d7333.zip
intc/arm_gic: Support IRQ injection for more than 256 vpus
Host kernels that expose the KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 capability allow injection of interrupts along with vcpu ids larger than 255. Let's encode the vpcu id on 12 bits according to the upgraded KVM_IRQ_LINE ABI when needed. Given that we have two callsites that need to assemble the value for kvm_set_irq(), a new helper routine, kvm_arm_set_irq is introduced. Without that patch qemu exits with "kvm_set_irq: Invalid argument" message. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reported-by: Zenghui Yu <yuzenghui@huawei.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Andrew Jones <drjones@redhat.com> Acked-by: Marc Zyngier <maz@kernel.org> Message-id: 20191003154640.22451-3-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu.c10
-rw-r--r--target/arm/kvm.c12
-rw-r--r--target/arm/kvm_arm.h1
3 files changed, 17 insertions, 6 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c14471..13813fb213 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -576,16 +576,16 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
ARMCPU *cpu = opaque;
CPUARMState *env = &cpu->env;
CPUState *cs = CPU(cpu);
- int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
uint32_t linestate_bit;
+ int irq_id;
switch (irq) {
case ARM_CPU_IRQ:
- kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+ irq_id = KVM_ARM_IRQ_CPU_IRQ;
linestate_bit = CPU_INTERRUPT_HARD;
break;
case ARM_CPU_FIQ:
- kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+ irq_id = KVM_ARM_IRQ_CPU_FIQ;
linestate_bit = CPU_INTERRUPT_FIQ;
break;
default:
@@ -597,9 +597,7 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
} else {
env->irq_line_state &= ~linestate_bit;
}
-
- kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
- kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+ kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level);
#endif
}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index b2eaa50b8d..b10581fa06 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -744,6 +744,18 @@ int kvm_arm_vgic_probe(void)
}
}
+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level)
+{
+ int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq;
+ int cpu_idx1 = cpu % 256;
+ int cpu_idx2 = cpu / 256;
+
+ kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) |
+ (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT);
+
+ return kvm_set_irq(kvm_state, kvm_irq, !!level);
+}
+
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint64_t address, uint32_t data, PCIDevice *dev)
{
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index b3106c8600..b4e19457a0 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -253,6 +253,7 @@ int kvm_arm_vgic_probe(void);
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
void kvm_arm_pmu_init(CPUState *cs);
+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
#else