mirror of https://github.com/xemu-project/xemu.git
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>
This commit is contained in:
parent
f363d039e8
commit
f6530926e2
|
@ -55,7 +55,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
|
||||||
* has separate fields in the irq number for type,
|
* has separate fields in the irq number for type,
|
||||||
* CPU number and interrupt number.
|
* CPU number and interrupt number.
|
||||||
*/
|
*/
|
||||||
int kvm_irq, irqtype, cpu;
|
int irqtype, cpu;
|
||||||
|
|
||||||
if (irq < (num_irq - GIC_INTERNAL)) {
|
if (irq < (num_irq - GIC_INTERNAL)) {
|
||||||
/* External interrupt. The kernel numbers these like the GIC
|
/* External interrupt. The kernel numbers these like the GIC
|
||||||
|
@ -72,10 +72,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
|
||||||
cpu = irq / GIC_INTERNAL;
|
cpu = irq / GIC_INTERNAL;
|
||||||
irq %= GIC_INTERNAL;
|
irq %= GIC_INTERNAL;
|
||||||
}
|
}
|
||||||
kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT)
|
kvm_arm_set_irq(cpu, irqtype, irq, !!level);
|
||||||
| (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq;
|
|
||||||
|
|
||||||
kvm_set_irq(kvm_state, kvm_irq, !!level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
|
static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
|
||||||
|
|
|
@ -576,16 +576,16 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
|
||||||
ARMCPU *cpu = opaque;
|
ARMCPU *cpu = opaque;
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
|
|
||||||
uint32_t linestate_bit;
|
uint32_t linestate_bit;
|
||||||
|
int irq_id;
|
||||||
|
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case ARM_CPU_IRQ:
|
case ARM_CPU_IRQ:
|
||||||
kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
|
irq_id = KVM_ARM_IRQ_CPU_IRQ;
|
||||||
linestate_bit = CPU_INTERRUPT_HARD;
|
linestate_bit = CPU_INTERRUPT_HARD;
|
||||||
break;
|
break;
|
||||||
case ARM_CPU_FIQ:
|
case ARM_CPU_FIQ:
|
||||||
kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
|
irq_id = KVM_ARM_IRQ_CPU_FIQ;
|
||||||
linestate_bit = CPU_INTERRUPT_FIQ;
|
linestate_bit = CPU_INTERRUPT_FIQ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -597,9 +597,7 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
|
||||||
} else {
|
} else {
|
||||||
env->irq_line_state &= ~linestate_bit;
|
env->irq_line_state &= ~linestate_bit;
|
||||||
}
|
}
|
||||||
|
kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level);
|
||||||
kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
|
|
||||||
kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
||||||
uint64_t address, uint32_t data, PCIDevice *dev)
|
uint64_t address, uint32_t data, PCIDevice *dev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -253,6 +253,7 @@ int kvm_arm_vgic_probe(void);
|
||||||
|
|
||||||
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
|
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
|
||||||
void kvm_arm_pmu_init(CPUState *cs);
|
void kvm_arm_pmu_init(CPUState *cs);
|
||||||
|
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue