From 928b70e2d14219cadcbe35a1a5f3e12e9e551ad0 Mon Sep 17 00:00:00 2001 From: zhanghailiang Date: Mon, 6 Jan 2020 14:35:42 +0800 Subject: [PATCH] Arm: Backport patches from upstream to support more than 256 vcpus Without this serial, we can't start VM with more than 256 vcpus, this is limited by kvm API, backport this serial to fix the bug. With this patches, it can supports up to 512 vcpus. Signed-off-by: zhanghailiang --- ...M_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch | 61 ++++++++ ...port-IRQ-injection-for-more-than-256.patch | 132 ++++++++++++++++++ ...update-against-KVM-ARM-Fix-256-vcpus.patch | 62 ++++++++ qemu.spec | 10 +- 4 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch create mode 100644 intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch create mode 100644 linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch 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 0000000..5727a1d --- /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 0000000..d69dcc7 --- /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 0000000..3d4e4ad --- /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 d993374..553ff58 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 -- Gitee