diff --git a/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch b/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch new file mode 100644 index 0000000000000000000000000000000000000000..5727a1d482a732c900701024507156a0f999bf40 --- /dev/null +++ b/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch @@ -0,0 +1,61 @@ +From f3c1fc4dce1582ccc1754899d5149d233e8629ff Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 3 Oct 2019 17:46:40 +0200 +Subject: [PATCH 3/3] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for + smp_cpus > 256 + +Host kernel within [4.18, 5.3] report an erroneous KVM_MAX_VCPUS=512 +for ARM. The actual capability to instantiate more than 256 vcpus +was fixed in 5.4 with the upgrade of the KVM_IRQ_LINE ABI to support +vcpu id encoded on 12 bits instead of 8 and a redistributor consuming +a single KVM IO device instead of 2. + +So let's check this capability when attempting to use more than 256 +vcpus within any ARM kvm accelerated machine. + +Signed-off-by: Eric Auger +Reviewed-by: Richard Henderson +Reviewed-by: Andrew Jones +Acked-by: Marc Zyngier +Message-id: 20191003154640.22451-4-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd) +[yu: Use the legacy smp_cpus instead of ms->smp.cpus, as we don't have + struct CpuTopology in MachineState at that time. See commit + edeeec911702 for details.] +Signed-off-by: Zenghui Yu +--- + target/arm/kvm.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index f60185ad..383423c4 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -174,6 +174,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) + + int kvm_arch_init(MachineState *ms, KVMState *s) + { ++ int ret = 0; + /* For ARM interrupt delivery is always asynchronous, + * whether we are using an in-kernel VGIC or not. + */ +@@ -187,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + + cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); + +- return 0; ++ if (smp_cpus > 256 && ++ !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { ++ error_report("Using more than 256 vcpus requires a host kernel " ++ "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); ++ ret = -EINVAL; ++ } ++ ++ return ret; + } + + unsigned long kvm_arch_vcpu_id(CPUState *cpu) +-- +2.19.1 + diff --git a/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch b/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch new file mode 100644 index 0000000000000000000000000000000000000000..d69dcc71825a8ed70e133ffb7d28af03a08485a1 --- /dev/null +++ b/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch @@ -0,0 +1,132 @@ +From 15849387df5c25e8ebaef19e2a16e8d428675f5d Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 3 Oct 2019 17:46:39 +0200 +Subject: [PATCH 2/3] 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 +Reported-by: Zenghui Yu +Reviewed-by: Richard Henderson +Reviewed-by: Andrew Jones +Acked-by: Marc Zyngier +Message-id: 20191003154640.22451-3-eric.auger@redhat.com +Signed-off-by: Peter Maydell +(cherry-picked from commit f6530926e2310147a7844a3e663230d47b3d7333) +Signed-off-by: Zenghui Yu +--- + hw/intc/arm_gic_kvm.c | 7 ++----- + target/arm/cpu.c | 10 ++++------ + target/arm/kvm.c | 12 ++++++++++++ + target/arm/kvm_arm.h | 1 + + 4 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c +index a611e8ee..7d600a61 100644 +--- a/hw/intc/arm_gic_kvm.c ++++ b/hw/intc/arm_gic_kvm.c +@@ -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, + * CPU number and interrupt number. + */ +- int kvm_irq, irqtype, cpu; ++ int irqtype, cpu; + + if (irq < (num_irq - GIC_INTERNAL)) { + /* 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; + irq %= GIC_INTERNAL; + } +- kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) +- | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq; +- +- kvm_set_irq(kvm_state, kvm_irq, !!level); ++ kvm_arm_set_irq(cpu, irqtype, irq, !!level); + } + + static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 41557821..0b4c8e27 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -561,16 +561,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: +@@ -582,9 +582,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 79a79f01..f60185ad 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -728,6 +728,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 2a07333c..a9f3ccab 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -235,6 +235,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 + +-- +2.19.1 + diff --git a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d4e4ad5bb7e833e97c2d51f9ab2cf5ae555e823 --- /dev/null +++ b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch @@ -0,0 +1,62 @@ +From 896b9892d4df316b85836daa973e442c0c64cec6 Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Fri, 3 Jan 2020 17:16:55 +0800 +Subject: [PATCH 1/3] linux headers: update against "KVM/ARM: Fix >256 vcpus" + +This is part of upstream commit f363d039e883 ("linux headers: update +against v5.4-rc1"), authored by Eric Auger . + +Signed-off-by: Zenghui Yu +--- + linux-headers/asm-arm/kvm.h | 4 +++- + linux-headers/asm-arm64/kvm.h | 4 +++- + linux-headers/linux/kvm.h | 1 + + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h +index e1f8b745..137a2730 100644 +--- a/linux-headers/asm-arm/kvm.h ++++ b/linux-headers/asm-arm/kvm.h +@@ -254,8 +254,10 @@ struct kvm_vcpu_events { + #define KVM_DEV_ARM_ITS_CTRL_RESET 4 + + /* KVM_IRQ_LINE irq field index values */ ++#define KVM_ARM_IRQ_VCPU2_SHIFT 28 ++#define KVM_ARM_IRQ_VCPU2_MASK 0xf + #define KVM_ARM_IRQ_TYPE_SHIFT 24 +-#define KVM_ARM_IRQ_TYPE_MASK 0xff ++#define KVM_ARM_IRQ_TYPE_MASK 0xf + #define KVM_ARM_IRQ_VCPU_SHIFT 16 + #define KVM_ARM_IRQ_VCPU_MASK 0xff + #define KVM_ARM_IRQ_NUM_SHIFT 0 +diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h +index e6a98c14..dfd3a028 100644 +--- a/linux-headers/asm-arm64/kvm.h ++++ b/linux-headers/asm-arm64/kvm.h +@@ -265,8 +265,10 @@ struct kvm_vcpu_events { + #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 + + /* KVM_IRQ_LINE irq field index values */ ++#define KVM_ARM_IRQ_VCPU2_SHIFT 28 ++#define KVM_ARM_IRQ_VCPU2_MASK 0xf + #define KVM_ARM_IRQ_TYPE_SHIFT 24 +-#define KVM_ARM_IRQ_TYPE_MASK 0xff ++#define KVM_ARM_IRQ_TYPE_MASK 0xf + #define KVM_ARM_IRQ_VCPU_SHIFT 16 + #define KVM_ARM_IRQ_VCPU_MASK 0xff + #define KVM_ARM_IRQ_NUM_SHIFT 0 +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index b53ee597..086cea4d 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_ARM_VM_IPA_SIZE 165 + #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 + #define KVM_CAP_HYPERV_CPUID 167 ++#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 + + #ifdef KVM_CAP_IRQ_ROUTING + +-- +2.19.1 + diff --git a/qemu.spec b/qemu.spec index d993374ccfc445b1e93796f55340efb7041317d6..553ff58b3ed155ec135ec32cd40885ee3f975863 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.0.0 -Release: 4 +Release: 5 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY @@ -80,6 +80,9 @@ Patch0067: slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch Patch0068: slirp-ip_reass-Fix-use-after-free.patch Patch0069: hw-core-loader-Fix-possible-crash-in-rom_copy.patch Patch0070: migration-Fix-use-after-free-during-process-exit.patch +Patch0071: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch +Patch0072: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch +Patch0073: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch BuildRequires: flex BuildRequires: bison @@ -410,6 +413,11 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Mon Jan 6 2020 backport from qemu upstream +- linux headers: update against "KVM/ARM: Fix >256 vcp +- intc/arm_gic: Support IRQ injection for more than 256 vpus +- ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > 256 + * Fri Nov 12 2019 backport from qemu upstream v4.0.1 release - usb-tablet: fix serial compat property - blockdev-backup: don't check aio_context too early