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..3012512988402756527c95341aa921a362c9e43e --- /dev/null +++ b/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch @@ -0,0 +1,64 @@ +From e3a7ec839fa4f823666d726989c375dcf73348a4 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 15 Apr 2020 16:14:50 +0800 +Subject: [PATCH] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > + 256 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +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 | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 50e86f8b..cc7a46df 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -173,6 +173,8 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) + + int kvm_arch_init(MachineState *ms, KVMState *s) + { ++ int ret = 0; ++ unsigned int smp_cpus = ms->smp.cpus; + /* For ARM interrupt delivery is always asynchronous, + * whether we are using an in-kernel VGIC or not. + */ +@@ -186,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.23.0 diff --git a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch b/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch deleted file mode 100644 index b2ad176f8d56fdc71b6663f36bad7cc93ed4429a..0000000000000000000000000000000000000000 --- a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch +++ /dev/null @@ -1,134 +0,0 @@ -From d2fd6d1a5200b9a58863839d21d291cd4f76ac31 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 15:47:27 +0800 -Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped - -The vtimer kick still increases even if the vcpu is stopped when VM has -save/restore or suspend/resume operation. This will cause guest watchdog -soft-lockup if the VM has lots of memory in use. - -Signed-off-by: Hao Hong -Signed-off-by: Haibin Wang -Signed-off-by: Ying Fang ---- - cpus.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ - target/arm/cpu.h | 2 ++ - target/arm/machine.c | 1 + - 3 files changed, 61 insertions(+) - -diff --git a/cpus.c b/cpus.c -index e83f72b4..f6ec48a2 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1063,6 +1063,28 @@ void cpu_synchronize_all_pre_loadvm(void) - } - } - -+#ifdef __aarch64__ -+static void get_vcpu_timer_tick(CPUState *cs) -+{ -+ CPUARMState *env = &ARM_CPU(cs)->env; -+ int err; -+ struct kvm_one_reg reg; -+ uint64_t timer_tick; -+ -+ reg.id = KVM_REG_ARM_TIMER_CNT; -+ reg.addr = (uintptr_t) &timer_tick; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); -+ if (err < 0) { -+ error_report("get vcpu tick failed, ret = %d", err); -+ env->vtimer = 0; -+ return; -+ } -+ env->vtimer = timer_tick; -+ return; -+} -+#endif -+ - static int do_vm_stop(RunState state, bool send_stop) - { - int ret = 0; -@@ -1070,6 +1092,11 @@ static int do_vm_stop(RunState state, bool send_stop) - if (runstate_is_running()) { - cpu_disable_ticks(); - pause_all_vcpus(); -+#ifdef __aarch64__ -+ if (first_cpu) { -+ get_vcpu_timer_tick(first_cpu); -+ } -+#endif - runstate_set(state); - vm_state_notify(0, state); - if (send_stop) { -@@ -1909,11 +1936,42 @@ void cpu_resume(CPUState *cpu) - qemu_cpu_kick(cpu); - } - -+#ifdef __aarch64__ -+static void set_vcpu_timer_tick(CPUState *cs) -+{ -+ CPUARMState *env = &ARM_CPU(cs)->env; -+ -+ if (env->vtimer == 0) { -+ return; -+ } -+ -+ int err; -+ struct kvm_one_reg reg; -+ uint64_t timer_tick = env->vtimer; -+ env->vtimer = 0; -+ -+ reg.id = KVM_REG_ARM_TIMER_CNT; -+ reg.addr = (uintptr_t) &timer_tick; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); -+ if (err < 0) { -+ error_report("Set vcpu tick failed, ret = %d", err); -+ return; -+ } -+ return; -+} -+#endif -+ - void resume_all_vcpus(void) - { - CPUState *cpu; - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); -+#ifdef __aarch64__ -+ if (first_cpu) { -+ set_vcpu_timer_tick(first_cpu); -+ } -+#endif - CPU_FOREACH(cpu) { - cpu_resume(cpu); - } -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index d4d28369..e107e395 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -270,6 +270,8 @@ typedef struct CPUARMState { - uint64_t elr_el[4]; /* AArch64 exception link regs */ - uint64_t sp_el[4]; /* AArch64 banked stack pointers */ - -+ uint64_t vtimer; /* Timer tick when vcpu stop */ -+ - /* System control coprocessor (cp15) */ - struct { - uint32_t c0_cpuid; -diff --git a/target/arm/machine.c b/target/arm/machine.c -index b2925496..d64a0057 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -792,6 +792,7 @@ const VMStateDescription vmstate_arm_cpu = { - VMSTATE_UINT32(env.exception.syndrome, ARMCPU), - VMSTATE_UINT32(env.exception.fsr, ARMCPU), - VMSTATE_UINT64(env.exception.vaddress, ARMCPU), -+ VMSTATE_UINT64(env.vtimer, ARMCPU), - VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU), - VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU), - { --- -2.23.0 - diff --git a/Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch b/Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch deleted file mode 100644 index 66f2706d5c36e3e02b2e73cb1c83703f3b2bb499..0000000000000000000000000000000000000000 --- a/Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 477c7aea5f2f9090c016c0a9813dc5901bd1b66a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 24 Apr 2020 11:36:41 +0800 -Subject: [PATCH] Fix use-afte-free in ip_reass() (CVE-2020-1983) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The q pointer is updated when the mbuf data is moved from m_dat to -m_ext. - -m_ext buffer may also be realloc()'ed and moved during m_cat(): -q should also be updated in this case. - -Reported-by: Aviv Sasson -Signed-off-by: Marc-André Lureau -Reviewed-by: Samuel Thibault - -diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c -index 89ae04e0..7fdde631 100644 ---- a/slirp/src/ip_input.c -+++ b/slirp/src/ip_input.c -@@ -333,7 +333,7 @@ insert: - q = fp->frag_link.next; - m = dtom(slirp, q); - -- int was_ext = m->m_flags & M_EXT; -+ int delta = (char *)q - (m->m_flags & M_EXT ? m->m_ext : m->m_dat); - - q = (struct ipasfrag *) q->ipf_next; - while (q != (struct ipasfrag*)&fp->frag_link) { -@@ -356,8 +356,7 @@ insert: - * then an m_ext buffer was alloced. But fp->ipq_next points to the old - * buffer (in the mbuf), so we must point ip into the new buffer. - */ -- if (!was_ext && m->m_flags & M_EXT) { -- int delta = (char *)q - m->m_dat; -+ if (m->m_flags & M_EXT) { - q = (struct ipasfrag *)(m->m_ext + delta); - } - --- -2.23.0 - diff --git a/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch b/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch new file mode 100644 index 0000000000000000000000000000000000000000..200e0b2df02607b11e3117863afd00a346419e27 --- /dev/null +++ b/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch @@ -0,0 +1,88 @@ +From 73a5bf472921068e6db10e7e325b7ac46f111834 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Mon, 29 Jul 2019 18:36:05 -0400 +Subject: [PATCH] Revert "ide/ahci: Check for -ECANCELED in aio callbacks" + +This reverts commit 0d910cfeaf2076b116b4517166d5deb0fea76394. + +It's not correct to just ignore an error code in a callback; we need to +handle that error and possible report failure to the guest so that they +don't wait indefinitely for an operation that will now never finish. + +This ought to help cases reported by Nutanix where iSCSI returns a +legitimate -ECANCELED for certain operations which should be propagated +normally. + +Reported-by: Shaju Abraham +Signed-off-by: John Snow +Message-id: 20190729223605.7163-1-jsnow@redhat.com +Signed-off-by: John Snow +(cherry picked from commit 8ec41c4265714255d5a138f8b538faf3583dcff6) +Signed-off-by: Michael Roth +--- + hw/ide/ahci.c | 3 --- + hw/ide/core.c | 14 -------------- + 2 files changed, 17 deletions(-) + +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index 00ba422a48..6aaf66534a 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -1023,9 +1023,6 @@ static void ncq_cb(void *opaque, int ret) + IDEState *ide_state = &ncq_tfs->drive->port.ifs[0]; + + ncq_tfs->aiocb = NULL; +- if (ret == -ECANCELED) { +- return; +- } + + if (ret < 0) { + bool is_read = ncq_tfs->cmd == READ_FPDMA_QUEUED; +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 6afadf894f..8e1624f7ce 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -722,9 +722,6 @@ static void ide_sector_read_cb(void *opaque, int ret) + s->pio_aiocb = NULL; + s->status &= ~BUSY_STAT; + +- if (ret == -ECANCELED) { +- return; +- } + if (ret != 0) { + if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO | + IDE_RETRY_READ)) { +@@ -840,10 +837,6 @@ static void ide_dma_cb(void *opaque, int ret) + uint64_t offset; + bool stay_active = false; + +- if (ret == -ECANCELED) { +- return; +- } +- + if (ret == -EINVAL) { + ide_dma_error(s); + return; +@@ -975,10 +968,6 @@ static void ide_sector_write_cb(void *opaque, int ret) + IDEState *s = opaque; + int n; + +- if (ret == -ECANCELED) { +- return; +- } +- + s->pio_aiocb = NULL; + s->status &= ~BUSY_STAT; + +@@ -1058,9 +1047,6 @@ static void ide_flush_cb(void *opaque, int ret) + + s->pio_aiocb = NULL; + +- if (ret == -ECANCELED) { +- return; +- } + if (ret < 0) { + /* XXX: What sector number to set here? */ + if (ide_handle_rw_error(s, -ret, IDE_RETRY_FLUSH)) { +-- +2.23.0 diff --git a/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch b/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc1fd44d163beb57f08c3b58918d305772b0c362 --- /dev/null +++ b/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch @@ -0,0 +1,27 @@ +From 843f593280b93e03bb7b0d0001da7488d61f13f6 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 08:55:17 +0800 +Subject: [PATCH] Typo: Correct the name of CPU hotplug memory region + +Replace "acpi-mem-hotplug" with "acpi-cpu-hotplug" + +Signed-off-by: Keqian Zhu +--- + hw/acpi/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index 7a90c8f82d..0c0bfe479a 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -203,7 +203,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, + state->devs[i].arch_id = id_list->cpus[i].arch_id; + } + memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state, +- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); ++ "acpi-cpu-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); + memory_region_add_subregion(as, base_addr, &state->ctrl_reg); + } + +-- +2.19.1 diff --git a/accel-kvm-Add-pre-park-vCPU-support.patch b/accel-kvm-Add-pre-park-vCPU-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..9bc81178581c30504ca1b32d1f47ba8cbc1a5b85 --- /dev/null +++ b/accel-kvm-Add-pre-park-vCPU-support.patch @@ -0,0 +1,63 @@ +From 135119d2e82e99adc67346572c761fbe54d73e4a Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:04:40 +0800 +Subject: [PATCH] accel/kvm: Add pre-park vCPU support + +For that KVM do not support dynamic adjustment of vCPU count, +we must pre-park all possible vCPU at start. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + accel/kvm/kvm-all.c | 23 +++++++++++++++++++++++ + include/sysemu/kvm.h | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index f450f25295..84edbe8bb1 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -339,6 +339,29 @@ err: + return ret; + } + ++int kvm_create_parked_vcpu(unsigned long vcpu_id) ++{ ++ KVMState *s = kvm_state; ++ struct KVMParkedVcpu *vcpu = NULL; ++ int ret; ++ ++ DPRINTF("kvm_create_parked_vcpu\n"); ++ ++ ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); ++ if (ret < 0) { ++ DPRINTF("kvm_create_vcpu failed\n"); ++ goto err; ++ } ++ ++ vcpu = g_malloc0(sizeof(*vcpu)); ++ vcpu->vcpu_id = vcpu_id; ++ vcpu->kvm_fd = ret; ++ QLIST_INSERT_HEAD(&s->kvm_parked_vcpus, vcpu, node); ++ ++err: ++ return ret; ++} ++ + static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) + { + struct KVMParkedVcpu *cpu; +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index acd90aebb6..565adb4e2c 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -216,6 +216,7 @@ int kvm_has_many_ioeventfds(void); + int kvm_has_gsi_routing(void); + int kvm_has_intx_set_mask(void); + ++int kvm_create_parked_vcpu(unsigned long vcpu_id); + int kvm_init_vcpu(CPUState *cpu); + int kvm_cpu_exec(CPUState *cpu); + int kvm_destroy_vcpu(CPUState *cpu); +-- +2.19.1 diff --git a/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch new file mode 100644 index 0000000000000000000000000000000000000000..0506d1b73c1586699dd0fe92254baa5d0af26a7b --- /dev/null +++ b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch @@ -0,0 +1,128 @@ +From 107c267ebe5b8c461268a4ff8384ad2f2b9e8ce0 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 16:11:13 +0800 +Subject: [PATCH] acpi/cpu: Prepare build_cpus_aml for arm virt + +We will reuse build_cpus_aml to build DSDT cpus aml in arm/virt +ACPI to realize cpu hotplug. Three points are added. + +1. Make ACPI IO address space configurable, because ARM64 platforms + don't use port IO for ACPI IO space. +2. Add GICC struct building support in _MAT of cpu aml. +3. Let the hotplug method parameter can be NULL, because ACPI GED + will realize it. + +Besides, CPU CPPC building is injected. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/acpi/cpu.c | 32 +++++++++++++++++++++++++------- + hw/i386/acpi-build.c | 2 +- + include/hw/acpi/cpu.h | 3 ++- + 3 files changed, 28 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index 0c0bfe479a..72ad1fcff2 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -314,7 +314,8 @@ const VMStateDescription vmstate_cpu_hotplug = { + void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + hwaddr io_base, + const char *res_root, +- const char *event_handler_method) ++ const char *event_handler_method, ++ AmlRegionSpace rs) + { + Aml *ifctx; + Aml *field; +@@ -342,13 +343,18 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); + + crs = aml_resource_template(); +- aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, +- ACPI_CPU_HOTPLUG_REG_LEN)); ++ if (rs == AML_SYSTEM_IO) { ++ aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, ++ ACPI_CPU_HOTPLUG_REG_LEN)); ++ } else { ++ aml_append(crs, aml_memory32_fixed(io_base, ++ ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); ++ } + aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); + + /* declare CPU hotplug MMIO region with related access fields */ + aml_append(cpu_ctrl_dev, +- aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), ++ aml_operation_region("PRST", rs, aml_int(io_base), + ACPI_CPU_HOTPLUG_REG_LEN)); + + field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, +@@ -517,6 +523,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(dev, aml_name_decl("_UID", uid)); + } + ++ assert(adevc); ++ if (adevc->cpu_cppc) { ++ adevc->cpu_cppc(adev, i, arch_ids->len, dev); ++ } ++ + method = aml_method("_STA", 0, AML_SERIALIZED); + aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid))); + aml_append(dev, method); +@@ -535,6 +546,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + apic->flags = cpu_to_le32(1); + break; + } ++ case ACPI_APIC_GENERIC_CPU_INTERFACE: { ++ AcpiMadtGenericCpuInterface *gicc = (void *)madt_buf->data; ++ gicc->flags = cpu_to_le32(1); ++ break; ++ } + default: + assert(0); + } +@@ -570,9 +586,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(sb_scope, cpus_dev); + aml_append(table, sb_scope); + +- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); +- aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); +- aml_append(table, method); ++ if (event_handler_method) { ++ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); ++ aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); ++ aml_append(table, method); ++ } + + g_free(cphp_res_path); + } +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 749218561a..c97731ecb3 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1869,7 +1869,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + .acpi_1_compatible = true, .has_legacy_cphp = true + }; + build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, +- "\\_SB.PCI0", "\\_GPE._E02"); ++ "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO); + } + + if (pcms->memhp_io_base && nr_mem) { +diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h +index 62f0278ba2..a30ec84a4f 100644 +--- a/include/hw/acpi/cpu.h ++++ b/include/hw/acpi/cpu.h +@@ -55,7 +55,8 @@ typedef struct CPUHotplugFeatures { + void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + hwaddr io_base, + const char *res_root, +- const char *event_handler_method); ++ const char *event_handler_method, ++ AmlRegionSpace rs); + + void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list); + +-- +2.19.1 diff --git a/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch b/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4e0a25c050e7948c1c7e1e2e0721c0b43d27fcc --- /dev/null +++ b/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch @@ -0,0 +1,41 @@ +From 3cd6df0b9e7d7b544673ce9a63b405e236d8265b Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:05:54 +0800 +Subject: [PATCH] acpi/ged: Add virt_madt_cpu_entry to madt_cpu hook + +In build_cpus_aml, we will invoke this hook to build _MAT +aml mehtod for cpus. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/acpi/generic_event_device.c | 1 + + include/hw/acpi/generic_event_device.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index 9cee90cc70..b834ae3ff6 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -288,6 +288,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) + hc->plug = acpi_ged_device_plug_cb; + + adevc->send_event = acpi_ged_send_event; ++ adevc->madt_cpu = virt_madt_cpu_entry; + } + + static const TypeInfo acpi_ged_info = { +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index d157eac088..f99efad7a3 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -61,6 +61,7 @@ + + #include "hw/sysbus.h" + #include "hw/acpi/memory_hotplug.h" ++#include "hw/arm/virt.h" + + #define ACPI_POWER_BUTTON_DEVICE "PWRB" + +-- +2.19.1 diff --git a/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch new file mode 100644 index 0000000000000000000000000000000000000000..57247e6797da5a977685f737e9454427ab2c41df --- /dev/null +++ b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch @@ -0,0 +1,204 @@ +From 05d22b55133db1a2526cfe305102e075e883b5e2 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 3 Apr 2020 15:41:01 +0800 +Subject: [PATCH] acpi/ged: Extend ACPI GED to support CPU hotplug + +This adds a new GED event called ACPI_GED_CPU_HOTPLUG_EVT. +The basic workflow is that: GED sends this event to guest, +then ACPI driver in guest will call _EVT method of GED aml, +then _EVT will call CSCN method in cpus aml to get status of +all cpus. + +The status of cpus is maintained by CPUHotplugState in GED and +is made accessable to guest through memory region. + +This also adds migration support to CPUHotplugState. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + docs/specs/acpi_hw_reduced_hotplug.rst | 3 ++- + hw/acpi/cpu.c | 1 - + hw/acpi/generic_event_device.c | 35 ++++++++++++++++++++++++++ + hw/arm/Kconfig | 1 + + include/hw/acpi/cpu.h | 2 ++ + include/hw/acpi/generic_event_device.h | 4 +++ + 6 files changed, 44 insertions(+), 2 deletions(-) + +diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst +index 911a98255b..deb481555d 100644 +--- a/docs/specs/acpi_hw_reduced_hotplug.rst ++++ b/docs/specs/acpi_hw_reduced_hotplug.rst +@@ -63,7 +63,8 @@ GED IO interface (4 byte access) + bits: + 0: Memory hotplug event + 1: System power down event +- 2-31: Reserved ++ 2: CPU hotplug event ++ 3-31: Reserved + + **write_access:** + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index 72ad1fcff2..cb6bb67f3c 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -6,7 +6,6 @@ + #include "trace.h" + #include "sysemu/numa.h" + +-#define ACPI_CPU_HOTPLUG_REG_LEN 12 + #define ACPI_CPU_SELECTOR_OFFSET_WR 0 + #define ACPI_CPU_FLAGS_OFFSET_RW 4 + #define ACPI_CPU_CMD_OFFSET_WR 5 +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index 82139b4314..478a4ee87c 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -23,6 +23,7 @@ + static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, + ACPI_GED_PWR_DOWN_EVT, ++ ACPI_GED_CPU_HOTPLUG_EVT, + }; + + /* +@@ -110,6 +111,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), + aml_int(0x80))); + break; ++ case ACPI_GED_CPU_HOTPLUG_EVT: ++ aml_append(if_ctx, aml_call0("\\_SB.CPUS.CSCN")); ++ break; + default: + /* + * Please make sure all the events in ged_supported_events[] +@@ -176,6 +180,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, + + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp); + } else { + error_setg(errp, "virt: device plug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); +@@ -192,6 +198,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) + sel = ACPI_GED_MEM_HOTPLUG_EVT; + } else if (ev & ACPI_POWER_DOWN_STATUS) { + sel = ACPI_GED_PWR_DOWN_EVT; ++ } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { ++ sel = ACPI_GED_CPU_HOTPLUG_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); +@@ -224,6 +232,16 @@ static const VMStateDescription vmstate_memhp_state = { + } + }; + ++static const VMStateDescription vmstate_cpuhp_state = { ++ .name = "acpi-ged/cpuhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_CPU_HOTPLUG(cpuhp_state, AcpiGedState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_ged_state = { + .name = "acpi-ged-state", + .version_id = 1, +@@ -244,6 +262,7 @@ static const VMStateDescription vmstate_acpi_ged = { + }, + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, ++ &vmstate_cpuhp_state, + NULL + } + }; +@@ -254,6 +273,7 @@ static void acpi_ged_initfn(Object *obj) + AcpiGedState *s = ACPI_GED(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + GEDState *ged_st = &s->ged_state; ++ MachineClass *mc; + + memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, + TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); +@@ -273,6 +293,21 @@ static void acpi_ged_initfn(Object *obj) + sysbus_init_mmio(sbd, &s->container_memhp); + acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), + &s->memhp_state, 0); ++ ++ mc = MACHINE_GET_CLASS(qdev_get_machine()); ++ if (!mc->possible_cpu_arch_ids) { ++ /* ++ * MachineClass should support possible_cpu_arch_ids in ++ * cpu_hotplug_hw_init below. ++ */ ++ return; ++ } ++ ++ memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container", ++ ACPI_CPU_HOTPLUG_REG_LEN); ++ sysbus_init_mmio(sbd, &s->container_cpuhp); ++ cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev), ++ &s->cpuhp_state, 0); + } + + static void acpi_ged_class_init(ObjectClass *class, void *data) +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index ad7f7c089b..15e18b0a48 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -24,6 +24,7 @@ config ARM_VIRT + select DIMM + select ACPI_MEMORY_HOTPLUG + select ACPI_HW_REDUCED ++ select ACPI_CPU_HOTPLUG + + config CHEETAH + bool +diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h +index a30ec84a4f..e726414459 100644 +--- a/include/hw/acpi/cpu.h ++++ b/include/hw/acpi/cpu.h +@@ -17,6 +17,8 @@ + #include "hw/acpi/aml-build.h" + #include "hw/hotplug.h" + ++#define ACPI_CPU_HOTPLUG_REG_LEN 12 ++ + typedef struct AcpiCpuStatus { + struct CPUState *cpu; + uint64_t arch_id; +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index f99efad7a3..e702ff1e18 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -62,6 +62,7 @@ + #include "hw/sysbus.h" + #include "hw/acpi/memory_hotplug.h" + #include "hw/arm/virt.h" ++#include "hw/acpi/cpu.h" + + #define ACPI_POWER_BUTTON_DEVICE "PWRB" + +@@ -83,6 +84,7 @@ + */ + #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 + #define ACPI_GED_PWR_DOWN_EVT 0x2 ++#define ACPI_GED_CPU_HOTPLUG_EVT 0x4 + + typedef struct GEDState { + MemoryRegion io; +@@ -93,6 +95,8 @@ typedef struct AcpiGedState { + SysBusDevice parent_obj; + MemHotplugState memhp_state; + MemoryRegion container_memhp; ++ CPUHotplugState cpuhp_state; ++ MemoryRegion container_cpuhp; + GEDState ged_state; + uint32_t ged_event_bitmap; + qemu_irq irq; +-- +2.19.1 diff --git a/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch new file mode 100644 index 0000000000000000000000000000000000000000..30f210b33b66332cc0c16b5d2ddb706a177a2130 --- /dev/null +++ b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch @@ -0,0 +1,95 @@ +From 0288d98f0ef4d17a73cf2bad1b928cd7c044e318 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:40:44 +0800 +Subject: [PATCH] acpi/madt: Add pre-sizing capability to MADT GICC struct + +The count of possible CPUs is exposed to guest through the count +of MADT GICC struct, so we should pre-sizing MADT GICC too. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 26 +++++++++++++++++++++----- + include/hw/acpi/acpi-defs.h | 1 + + 2 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index dbe9acb148..efac788ba1 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -678,6 +678,13 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const MemMapEntry *memmap = vms->memmap; + AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc)); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid)); ++ static bool pmu; ++ ++ if (uid == 0) { ++ pmu = arm_feature(&armcpu->env, ARM_FEATURE_PMU); ++ } ++ /* FEATURE_PMU should be all enabled or disabled for CPUs */ ++ assert(!armcpu || arm_feature(&armcpu->env, ARM_FEATURE_PMU) == pmu); + + gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; + gicc->length = sizeof(*gicc); +@@ -687,11 +694,15 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); + } + gicc->cpu_interface_number = cpu_to_le32(uid); +- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); ++ gicc->arm_mpidr = possible_cpus->cpus[uid].arch_id; + gicc->uid = cpu_to_le32(uid); +- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); ++ if (armcpu) { ++ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); ++ } else { ++ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_DISABLED); ++ } + +- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { ++ if (pmu) { + gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); + } + if (vms->virt) { +@@ -704,12 +715,17 @@ static void + build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); ++ MachineClass *mc = MACHINE_GET_CLASS(vms); ++ MachineState *ms = MACHINE(vms); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + int madt_start = table_data->len; + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; + AcpiMultipleApicTable *madt; + AcpiMadtGenericDistributor *gicd; + AcpiMadtGenericMsiFrame *gic_msi; ++ /* The MADT GICC numbers */ ++ int num_cpu = vms->smp_cpus; + int i; + + madt = acpi_data_push(table_data, sizeof *madt); +@@ -720,8 +736,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); + gicd->version = vms->gic_version; + +- for (i = 0; i < vms->smp_cpus; i++) { +- virt_madt_cpu_entry(NULL, i, NULL, table_data); ++ for (i = 0; i < num_cpu; i++) { ++ virt_madt_cpu_entry(NULL, i, possible_cpus, table_data); + } + + if (vms->gic_version == 3) { +diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h +index 39ae91d3b8..6bfa7f9152 100644 +--- a/include/hw/acpi/acpi-defs.h ++++ b/include/hw/acpi/acpi-defs.h +@@ -306,6 +306,7 @@ typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface; + + /* GICC CPU Interface Flags */ + #define ACPI_MADT_GICC_ENABLED 1 ++#define ACPI_MADT_GICC_DISABLED 0 + + struct AcpiMadtGenericDistributor { + ACPI_SUB_HEADER_DEF +-- +2.19.1 diff --git a/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch new file mode 100644 index 0000000000000000000000000000000000000000..6bda35c51a3952121a155081bf0a37ce3534da25 --- /dev/null +++ b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch @@ -0,0 +1,108 @@ +From a3097eed8b642dc6fe891112340821e869b90cc2 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 13 Jan 2020 19:02:20 +0800 +Subject: [PATCH] acpi/madt: Factor out the building of MADT GICC struct + +To realize CPU hotplug, the cpus aml within ACPI DSDT should contain +_MAT mathod, which is equal to the GICC struct in ACPI MADT. Factor +out the GICC building code from ACPI MADT and reuse it in build_cpus_aml. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 51 +++++++++++++++++++++++----------------- + include/hw/arm/virt.h | 3 +++ + 2 files changed, 32 insertions(+), 22 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index f48733d9f2..4b6aace433 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -664,6 +664,34 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + table_data->len - gtdt_start, 2, NULL, NULL); + } + ++void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, ++ const CPUArchIdList *possible_cpus, GArray *entry) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); ++ const MemMapEntry *memmap = vms->memmap; ++ AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc)); ++ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid)); ++ ++ gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; ++ gicc->length = sizeof(*gicc); ++ if (vms->gic_version == 2) { ++ gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); ++ gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base); ++ gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); ++ } ++ gicc->cpu_interface_number = cpu_to_le32(uid); ++ gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); ++ gicc->uid = cpu_to_le32(uid); ++ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); ++ ++ if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { ++ gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); ++ } ++ if (vms->virt) { ++ gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ)); ++ } ++} ++ + /* MADT */ + static void + build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +@@ -686,28 +714,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + gicd->version = vms->gic_version; + + for (i = 0; i < vms->smp_cpus; i++) { +- AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data, +- sizeof(*gicc)); +- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); +- +- gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; +- gicc->length = sizeof(*gicc); +- if (vms->gic_version == 2) { +- gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); +- gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base); +- gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); +- } +- gicc->cpu_interface_number = cpu_to_le32(i); +- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); +- gicc->uid = cpu_to_le32(i); +- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); +- +- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { +- gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); +- } +- if (vms->virt) { +- gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ)); +- } ++ virt_madt_cpu_entry(NULL, i, NULL, table_data); + } + + if (vms->gic_version == 3) { +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 3dfefca93b..6b1f10b231 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -37,6 +37,7 @@ + #include "hw/block/flash.h" + #include "sysemu/kvm.h" + #include "hw/intc/arm_gicv3_common.h" ++#include "hw/acpi/acpi_dev_interface.h" + + #define NUM_GICV2M_SPIS 64 + #define NUM_VIRTIO_TRANSPORTS 32 +@@ -154,6 +155,8 @@ typedef struct { + OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) + + void virt_acpi_setup(VirtMachineState *vms); ++void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, ++ const CPUArchIdList *cpu_list, GArray *entry); + + /* Return the number of used redistributor regions */ + static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) +-- +2.19.1 diff --git a/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch b/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch index d27d763bb19d0b6b3323eb8f7647e5d89cb1df22..7926e7fa0db4ef16737a89782ea661273ef8c4d3 100644 --- a/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch +++ b/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch @@ -1,8 +1,7 @@ -From a2bae876b7f694b12073bac8ad6668e4d975ad88 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Fri, 10 Apr 2020 16:08:19 +0000 -Subject: [PATCH 1/2] aio-wait: delegate polling of main AioContext if BQL not - held +From 929d29ec7bf9dd6ec3802bea2148a041ff30d59b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 14 Apr 2020 21:17:09 +0800 +Subject: [PATCH] aio-wait: delegate polling of main AioContext if BQL not held Any thread that is not a iothread returns NULL for qemu_get_current_aio_context(). As a result, it would also return true for @@ -20,8 +19,6 @@ The function is moved to aio-wait.h because it is mostly used there and to avoid a circular reference between main-loop.h and block/aio.h. -upstream_url: https://patchwork.kernel.org/patch/11482099/ - Signed-off-by: Paolo Bonzini Message-Id: <20200407140746.8041-5-pbonzini@redhat.com> Signed-off-by: Stefan Hajnoczi @@ -31,21 +28,21 @@ Signed-off-by: Stefan Hajnoczi 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h -index afd0ff7e..d349e7e3 100644 +index afeeb18f..716d2639 100644 --- a/include/block/aio-wait.h +++ b/include/block/aio-wait.h @@ -26,6 +26,7 @@ #define QEMU_AIO_WAIT_H - + #include "block/aio.h" +#include "qemu/main-loop.h" - + /** * AioWait: @@ -124,4 +125,25 @@ void aio_wait_kick(void); */ void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); - + +/** + * in_aio_context_home_thread: + * @ctx: the aio context @@ -67,14 +64,14 @@ index afd0ff7e..d349e7e3 100644 + } +} + - #endif /* QEMU_AIO_WAIT */ + #endif /* QEMU_AIO_WAIT_H */ diff --git a/include/block/aio.h b/include/block/aio.h -index 0ca25dfe..c527893b 100644 +index 6b0d52f7..9d28e247 100644 --- a/include/block/aio.h +++ b/include/block/aio.h -@@ -61,12 +61,16 @@ struct AioContext { +@@ -60,12 +60,16 @@ struct AioContext { QLIST_HEAD(, AioHandler) aio_handlers; - + /* Used to avoid unnecessary event_notifier_set calls in aio_notify; - * accessed with atomic primitives. If this field is 0, everything - * (file descriptors, bottom halves, timers) will be re-evaluated @@ -95,10 +92,10 @@ index 0ca25dfe..c527893b 100644 * * Bit 0 is reserved for GSource usage of the AioContext, and is 1 * between a call to aio_ctx_prepare and the next call to aio_ctx_check. -@@ -581,19 +585,6 @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co); +@@ -580,19 +584,6 @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co); */ AioContext *qemu_get_current_aio_context(void); - + -/** - * in_aio_context_home_thread: - * @ctx: the aio context @@ -115,6 +112,5 @@ index 0ca25dfe..c527893b 100644 /** * aio_context_setup: * @ctx: the aio context --- -2.25.2 - +-- +2.23.0 diff --git a/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch new file mode 100644 index 0000000000000000000000000000000000000000..84903c34d5a86cac12aadf7d35271295b49f143d --- /dev/null +++ b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch @@ -0,0 +1,42 @@ +From d8e0b51447d8c64788cd7f9b0fa75c4ccb06f8eb Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:17:27 +0800 +Subject: [PATCH] arm/cpu: assign arm_get_arch_id handler to get_arch_id hook + +This hook will be called in get_cpu_status, which is called +during cpu hotplug. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + target/arm/cpu.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 39bbe7e2d7..1ccb30e5eb 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2575,6 +2575,13 @@ static gchar *arm_gdb_arch_name(CPUState *cs) + return g_strdup("arm"); + } + ++static int64_t arm_cpu_get_arch_id(CPUState *cs) ++{ ++ ARMCPU *cpu = ARM_CPU(cs); ++ ++ return cpu->mp_affinity; ++} ++ + static void arm_cpu_class_init(ObjectClass *oc, void *data) + { + ARMCPUClass *acc = ARM_CPU_CLASS(oc); +@@ -2596,6 +2603,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; + cc->gdb_read_register = arm_cpu_gdb_read_register; + cc->gdb_write_register = arm_cpu_gdb_write_register; ++ cc->get_arch_id = arm_cpu_get_arch_id; + #ifndef CONFIG_USER_ONLY + cc->do_interrupt = arm_cpu_do_interrupt; + cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug; +-- +2.19.1 diff --git a/arm-virt-Add-CPU-hotplug-framework.patch b/arm-virt-Add-CPU-hotplug-framework.patch new file mode 100644 index 0000000000000000000000000000000000000000..5de672afeab55fe5af5da3d2ce58aa2e9ae1435d --- /dev/null +++ b/arm-virt-Add-CPU-hotplug-framework.patch @@ -0,0 +1,66 @@ +From 6d287b3f1d961cc4adda1c6a452f41db84466f5a Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 3 Apr 2020 16:16:18 +0800 +Subject: [PATCH] arm/virt: Add CPU hotplug framework + +Establish the CPU hotplug framework for arm/virt, we will add +necessary code legs to this framework gradually to realize CPU +hotplug finally. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index d09a5773df..0bd37af26c 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2077,11 +2077,25 @@ out: + error_propagate(errp, local_err); + } + ++static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ /* Currently nothing to do */ ++} ++ ++static void virt_cpu_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ /* Currently nothing to do */ ++} ++ + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_memory_pre_plug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ virt_cpu_pre_plug(hotplug_dev, dev, errp); + } + } + +@@ -2098,6 +2112,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_memory_plug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ virt_cpu_plug(hotplug_dev, dev, errp); + } + } + +@@ -2112,7 +2128,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) + { + if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || +- (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || ++ object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + return HOTPLUG_HANDLER(machine); + } + +-- +2.19.1 diff --git a/arm-virt-Add-CPU-topology-support.patch b/arm-virt-Add-CPU-topology-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..c7813c637449328c5fecf7575d27a06fa1fa0700 --- /dev/null +++ b/arm-virt-Add-CPU-topology-support.patch @@ -0,0 +1,219 @@ +From cde57fcae2ed16a10e1ef7f2da0ec368883988ba Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 10:54:35 +0800 +Subject: [PATCH] arm/virt: Add CPU topology support + +The CPU topology specified by user (through -smp options) is used in +ACPI PPTT. Now we will use this information to locate which CPU to +plug or unplug. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 68 +++++++++++++++++++++++++++++++++++++-- + include/hw/arm/topology.h | 61 +++++++++++++++++++++++++++++++++++ + target/arm/cpu.c | 3 ++ + target/arm/cpu.h | 3 ++ + 4 files changed, 133 insertions(+), 2 deletions(-) + create mode 100644 include/hw/arm/topology.h + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 0bd37af26c..64532b61b2 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -36,6 +36,7 @@ + #include "hw/sysbus.h" + #include "hw/arm/boot.h" + #include "hw/arm/primecell.h" ++#include "hw/arm/topology.h" + #include "hw/arm/virt.h" + #include "hw/block/flash.h" + #include "hw/vfio/vfio-calxeda-xgmac.h" +@@ -2020,6 +2021,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + int n; + unsigned int max_cpus = ms->smp.max_cpus; + VirtMachineState *vms = VIRT_MACHINE(ms); ++ ARMCPUTopoInfo topo; + + if (ms->possible_cpus) { + assert(ms->possible_cpus->len == max_cpus); +@@ -2031,10 +2033,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + ms->possible_cpus->len = max_cpus; + for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].type = ms->cpu_type; ++ ms->possible_cpus->cpus[n].vcpus_count = 1; + ms->possible_cpus->cpus[n].arch_id = + virt_cpu_mp_affinity(vms, n); ++ ++ topo_ids_from_idx(n, ms->smp.cores, ms->smp.threads, &topo); ++ ms->possible_cpus->cpus[n].props.has_socket_id = true; ++ ms->possible_cpus->cpus[n].props.socket_id = topo.pkg_id; ++ ms->possible_cpus->cpus[n].props.has_core_id = true; ++ ms->possible_cpus->cpus[n].props.core_id = topo.core_id; + ms->possible_cpus->cpus[n].props.has_thread_id = true; +- ms->possible_cpus->cpus[n].props.thread_id = n; ++ ms->possible_cpus->cpus[n].props.thread_id = topo.smt_id; + } + return ms->possible_cpus; + } +@@ -2080,7 +2089,62 @@ out: + static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- /* Currently nothing to do */ ++ CPUState *cs = CPU(dev); ++ ARMCPUTopoInfo topo; ++ ARMCPU *cpu = ARM_CPU(dev); ++ MachineState *ms = MACHINE(hotplug_dev); ++ int smp_cores = ms->smp.cores; ++ int smp_threads = ms->smp.threads; ++ ++ /* if cpu idx is not set, set it based on socket/core/thread properties */ ++ if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { ++ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores; ++ if (cpu->socket_id < 0 || cpu->socket_id >= max_socket) { ++ error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", ++ cpu->socket_id, max_socket - 1); ++ return; ++ } ++ if (cpu->core_id < 0 || cpu->core_id >= smp_cores) { ++ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", ++ cpu->core_id, smp_cores - 1); ++ return; ++ } ++ if (cpu->thread_id < 0 || cpu->thread_id >= smp_threads) { ++ error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", ++ cpu->thread_id, smp_threads - 1); ++ return; ++ } ++ ++ topo.pkg_id = cpu->socket_id; ++ topo.core_id = cpu->core_id; ++ topo.smt_id = cpu->thread_id; ++ cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo); ++ } ++ ++ /* if 'address' properties socket-id/core-id/thread-id are not set, set them ++ * so that machine_query_hotpluggable_cpus would show correct values ++ */ ++ topo_ids_from_idx(cs->cpu_index, smp_cores, smp_threads, &topo); ++ if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) { ++ error_setg(errp, "property socket-id: %u doesn't match set idx:" ++ " 0x%x (socket-id: %u)", cpu->socket_id, cs->cpu_index, topo.pkg_id); ++ return; ++ } ++ cpu->socket_id = topo.pkg_id; ++ ++ if (cpu->core_id != -1 && cpu->core_id != topo.core_id) { ++ error_setg(errp, "property core-id: %u doesn't match set idx:" ++ " 0x%x (core-id: %u)", cpu->core_id, cs->cpu_index, topo.core_id); ++ return; ++ } ++ cpu->core_id = topo.core_id; ++ ++ if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) { ++ error_setg(errp, "property thread-id: %u doesn't match set idx:" ++ " 0x%x (thread-id: %u)", cpu->thread_id, cs->cpu_index, topo.smt_id); ++ return; ++ } ++ cpu->thread_id = topo.smt_id; + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, +diff --git a/include/hw/arm/topology.h b/include/hw/arm/topology.h +new file mode 100644 +index 0000000000..a3e5f436c5 +--- /dev/null ++++ b/include/hw/arm/topology.h +@@ -0,0 +1,61 @@ ++/* ++ * ARM CPU topology data structures and functions ++ * ++ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef HW_ARM_TOPOLOGY_H ++#define HW_ARM_TOPOLOGY_H ++ ++typedef struct ARMCPUTopoInfo { ++ unsigned pkg_id; ++ unsigned core_id; ++ unsigned smt_id; ++} ARMCPUTopoInfo; ++ ++/* Calculate (contiguous) CPU index based on topology */ ++static inline unsigned idx_from_topo_ids(unsigned nr_cores, ++ unsigned nr_threads, ++ const ARMCPUTopoInfo *topo) ++{ ++ assert(nr_cores > 0); ++ assert(nr_threads > 0); ++ assert(topo != NULL); ++ ++ return topo->pkg_id * nr_cores * nr_threads + ++ topo->core_id * nr_threads + ++ topo->smt_id; ++} ++ ++/* Calculate thread/core/package topology ++ * based on (contiguous) CPU index ++ */ ++static inline void topo_ids_from_idx(unsigned cpu_index, ++ unsigned nr_cores, ++ unsigned nr_threads, ++ ARMCPUTopoInfo *topo) ++{ ++ assert(nr_cores > 0); ++ assert(nr_threads > 0); ++ assert(topo != NULL); ++ ++ topo->smt_id = cpu_index % nr_threads; ++ topo->core_id = cpu_index / nr_threads % nr_cores; ++ topo->pkg_id = cpu_index / nr_threads / nr_cores; ++} ++ ++#endif /* HW_ARM_TOPOLOGY_H */ ++ +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 1ccb30e5eb..91f1e36cd8 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2560,6 +2560,9 @@ static Property arm_cpu_properties[] = { + DEFINE_PROP_UINT64("mp-affinity", ARMCPU, + mp_affinity, ARM64_AFFINITY_INVALID), + DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), ++ DEFINE_PROP_INT32("socket-id", ARMCPU, socket_id, -1), ++ DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1), ++ DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, -1), + DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), + DEFINE_PROP_END_OF_LIST() + }; +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index e19531a77b..219c222b89 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -916,6 +916,9 @@ struct ARMCPU { + QLIST_HEAD(, ARMELChangeHook) el_change_hooks; + + int32_t node_id; /* NUMA node this CPU belongs to */ ++ int32_t socket_id; ++ int32_t core_id; ++ int32_t thread_id; + + /* Used to synchronize KVM and QEMU in-kernel device levels */ + uint8_t device_irq_level; +-- +2.19.1 diff --git a/arm-virt-Add-cpu_hotplug_enabled-field.patch b/arm-virt-Add-cpu_hotplug_enabled-field.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b8bc47f6d31dba63e1148c22cc803204ce82e70 --- /dev/null +++ b/arm-virt-Add-cpu_hotplug_enabled-field.patch @@ -0,0 +1,61 @@ +From 31873c4c0454fb17654f57adece2bc396415f8bf Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:50:40 +0800 +Subject: [PATCH] arm/virt: Add cpu_hotplug_enabled field + +Some conditions must be satisfied to support CPU hotplug, including +ACPI, GED, 64bit CPU, GICv3. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 7 +++++++ + include/hw/arm/virt.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index dda22194b5..304a4c2d31 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1645,6 +1645,7 @@ static void machvirt_init(MachineState *machine) + { + VirtMachineState *vms = VIRT_MACHINE(machine); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); ++ MachineState *ms = MACHINE(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; + MemoryRegion *sysmem = get_system_memory(); +@@ -1655,6 +1656,7 @@ static void machvirt_init(MachineState *machine) + bool has_ged = !vmc->no_ged; + unsigned int smp_cpus = machine->smp.cpus; + unsigned int max_cpus = machine->smp.max_cpus; ++ ObjectClass *cpu_class; + + /* + * In accelerated mode, the memory map is computed earlier in kvm_type() +@@ -1760,6 +1762,11 @@ static void machvirt_init(MachineState *machine) + + create_fdt(vms); + ++ cpu_class = object_class_by_name(ms->cpu_type); ++ vms->cpu_hotplug_enabled = has_ged && firmware_loaded && ++ acpi_enabled && vms->gic_version == 3 && ++ !!object_class_dynamic_cast(cpu_class, TYPE_AARCH64_CPU); ++ + possible_cpus = mc->possible_cpu_arch_ids(machine); + for (n = 0; n < possible_cpus->len; n++) { + Object *cpuobj; +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index beef4c8002..b4c53d920e 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -126,6 +126,7 @@ typedef struct { + bool highmem_ecam; + bool its; + bool virt; ++ bool cpu_hotplug_enabled; + int32_t gic_version; + VirtIOMMUType iommu; + struct arm_boot_info bootinfo; +-- +2.19.1 diff --git a/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch b/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch new file mode 100644 index 0000000000000000000000000000000000000000..c81227d8a3ef4ff3ffc74f7b848b42e8cc79c762 --- /dev/null +++ b/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch @@ -0,0 +1,66 @@ +From 7cfb37c50209208f853c6fbd0df6673a95e03ef9 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 14:16:40 +0800 +Subject: [PATCH] arm/virt: Add some sanity checks in cpu_pre_plug hook + +For that user will try to hotplug a CPU when preconditions +are not satisfied, check these CPU hotplug preconditions in +pre_plug hook. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 983084c459..c6a99e683a 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2086,10 +2086,30 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ const CPUArchId *cpu_slot = NULL; + MemoryRegion *sysmem = get_system_memory(); + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; + ++ /* Some hotplug capability checks */ ++ ++ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { ++ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", ++ ms->cpu_type); ++ return; ++ } ++ ++ if (dev->hotplugged && !vms->acpi_dev) { ++ error_setg(errp, "CPU hotplug is disabled: missing acpi device."); ++ return; ++ } ++ ++ if (dev->hotplugged && !vms->cpu_hotplug_enabled) { ++ error_setg(errp, "CPU hotplug is disabled: " ++ "should use AArch64 CPU and GICv3."); ++ return; ++ } ++ + /* if cpu idx is not set, set it based on socket/core/thread properties */ + if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { + int max_socket = ms->smp.max_cpus / smp_threads / smp_cores; +@@ -2145,6 +2165,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id, + "mp-affinity", NULL); + ++ cpu_slot = &possible_cpus->cpus[cs->cpu_index]; ++ if (cpu_slot->cpu) { ++ error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists", ++ cs->cpu_index, cpu->mp_affinity); ++ return; ++ } ++ + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); + +-- +2.19.1 diff --git a/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch new file mode 100644 index 0000000000000000000000000000000000000000..ade3ccfd9fe50a78c8ef33ded3463e52b5f6d6c3 --- /dev/null +++ b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch @@ -0,0 +1,100 @@ +From d38d1d4e859450535ddc6bf0c7a59f6217b1403c Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Sun, 5 Apr 2020 16:03:15 +0800 +Subject: [PATCH] arm/virt: Attach ACPI CPU hotplug support to virt + +Attach cpus aml building and GED support for CPU hotplug to +arm/virt, but currently we make it diabled by not add CPU +hotplug event to GED. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 15 ++++++++++++++- + hw/arm/virt.c | 6 ++++++ + include/hw/arm/virt.h | 1 + + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 8b68a15d76..dbe9acb148 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -806,6 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + MachineState *ms = MACHINE(vms); + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; ++ bool cpu_aml_built = false; + + dsdt = init_aml_allocator(); + /* Reserve space for header */ +@@ -817,7 +818,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + * the RTC ACPI device at all when using UEFI. + */ + scope = aml_scope("\\_SB"); +- acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], + (irqmap[VIRT_UART] + ARM_SPI_BASE)); + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); +@@ -845,6 +845,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + AML_SYSTEM_MEMORY, + memmap[VIRT_PCDIMM_ACPI].base); + } ++ ++ if (event & ACPI_GED_CPU_HOTPLUG_EVT) { ++ CPUHotplugFeatures opts = { ++ .acpi_1_compatible = false, .has_legacy_cphp = false ++ }; ++ build_cpus_aml(dsdt, ms, opts, memmap[VIRT_CPU_ACPI].base, ++ "\\_SB", NULL, AML_SYSTEM_MEMORY); ++ cpu_aml_built = true; ++ } ++ } ++ ++ if (!cpu_aml_built) { ++ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms); + } + + acpi_dsdt_add_power_button(scope); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 8638aeedb7..d09a5773df 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -140,6 +140,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_SMMU] = { 0x09050000, 0x00020000 }, + [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, + [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, ++ [VIRT_CPU_ACPI] = { 0x09090000, ACPI_CPU_HOTPLUG_REG_LEN }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, + [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ +@@ -645,11 +646,16 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_MEM_HOTPLUG_EVT; + } + ++ /* event |= ACPI_GED_CPU_HOTPLUG_EVT; ++ * Currently CPU hotplug is not enabled. ++ */ ++ + dev = qdev_create(NULL, TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, vms->memmap[VIRT_CPU_ACPI].base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); + + qdev_init_nofail(dev); +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index cbdea7ff32..6880ebe07c 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -81,6 +81,7 @@ enum { + VIRT_SECURE_MEM, + VIRT_PCDIMM_ACPI, + VIRT_ACPI_GED, ++ VIRT_CPU_ACPI, + VIRT_LOWMEMMAP_LAST, + }; + +-- +2.19.1 diff --git a/arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch b/arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2d9a3cb0a48436433a30670e8517d7dafb9bca4 --- /dev/null +++ b/arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch @@ -0,0 +1,124 @@ +From bf47ef282bfe8b0a98e1f87d8708051ffa7192a1 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:55:11 +0800 +Subject: [PATCH] arm/virt: Pre-sizing MADT-GICC PPTT GICv3 and Pre-park KVM + vCPU + +Establish all pre-sizing facilities based on cpu_hotplug_enabled +field. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 12 +++++++++++- + hw/arm/virt.c | 14 ++++++++++++-- + target/arm/kvm.c | 6 +++--- + 3 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index efac788ba1..2cfac7b84f 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -736,6 +736,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); + gicd->version = vms->gic_version; + ++ if (vms->cpu_hotplug_enabled) { ++ num_cpu = ms->smp.max_cpus; ++ } + for (i = 0; i < num_cpu; i++) { + virt_madt_cpu_entry(NULL, i, possible_cpus, table_data); + } +@@ -902,9 +905,11 @@ static + void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) + { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); ++ MachineState *ms = MACHINE(vms); + GArray *table_offsets; + unsigned dsdt, xsdt; + GArray *tables_blob = tables->table_data; ++ int num_cpus; + + table_offsets = g_array_new(false, true /* clear */, + sizeof(uint32_t)); +@@ -923,7 +928,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) + + acpi_add_table(table_offsets, tables_blob); + +- build_pptt(tables_blob, tables->linker, vms->smp_cpus); ++ if (vms->cpu_hotplug_enabled) { ++ num_cpus = ms->smp.max_cpus; ++ } else { ++ num_cpus = ms->smp.cpus; ++ } ++ build_pptt(tables_blob, tables->linker, num_cpus); + + acpi_add_table(table_offsets, tables_blob); + build_madt(tables_blob, tables->linker, vms); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 304a4c2d31..983084c459 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -767,6 +767,9 @@ static void create_gic(VirtMachineState *vms) + unsigned int smp_cpus = ms->smp.cpus; + uint32_t nb_redist_regions = 0; + ++ if (vms->cpu_hotplug_enabled) { ++ num_cpus = ms->smp.max_cpus; ++ } + assert(num_cpus >= smp_cpus); + + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); +@@ -1772,8 +1775,15 @@ static void machvirt_init(MachineState *machine) + Object *cpuobj; + CPUState *cs; + ++ if (kvm_enabled() && vms->cpu_hotplug_enabled) { ++ if (kvm_create_parked_vcpu(n) < 0) { ++ error_report("mach-virt: Create KVM parked vCPU failed"); ++ exit(1); ++ } ++ } ++ + if (n >= smp_cpus) { +- break; ++ continue; + } + + cpuobj = object_new(possible_cpus->cpus[n].type); +@@ -1857,7 +1867,7 @@ static void machvirt_init(MachineState *machine) + vms->bootinfo.kernel_filename = machine->kernel_filename; + vms->bootinfo.kernel_cmdline = machine->kernel_cmdline; + vms->bootinfo.initrd_filename = machine->initrd_filename; +- vms->bootinfo.nb_cpus = smp_cpus; ++ vms->bootinfo.nb_cpus = vms->cpu_hotplug_enabled ? max_cpus : smp_cpus; + vms->bootinfo.board_id = -1; + vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base; + vms->bootinfo.get_dtb = machvirt_dtb; +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 327b3bc338..4f131f687d 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -202,7 +202,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) + int kvm_arch_init(MachineState *ms, KVMState *s) + { + int ret = 0; +- unsigned int smp_cpus = ms->smp.cpus; ++ unsigned int max_cpus = ms->smp.max_cpus; + /* For ARM interrupt delivery is always asynchronous, + * whether we are using an in-kernel VGIC or not. + */ +@@ -216,9 +216,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + + cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); + +- if (smp_cpus > 256 && ++ if (max_cpus > 256 && + !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { +- error_report("Using more than 256 vcpus requires a host kernel " ++ error_report("Using more than max 256 vcpus requires a host kernel " + "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); + ret = -EINVAL; + } +-- +2.19.1 diff --git a/arm-virt-Start-up-CPU-hot-plug.patch b/arm-virt-Start-up-CPU-hot-plug.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ba620a2215710682afa4ccdfd0d5cad53556680 --- /dev/null +++ b/arm-virt-Start-up-CPU-hot-plug.patch @@ -0,0 +1,159 @@ +From 11f9628ceff019259ff12ce469deafbf50eb3075 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 14:20:59 +0800 +Subject: [PATCH] arm/virt: Start up CPU hot-plug + +All the CPU hotplug facilities are ready. Assemble them +to start up CPU hot-plug capability for arm/virt. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 61 ++++++++++++++++++++++++++++++++++++++++--- + include/hw/arm/virt.h | 1 + + qom/cpu.c | 5 ++++ + target/arm/cpu.c | 2 ++ + 4 files changed, 65 insertions(+), 4 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index c6a99e683a..112a6ae7cb 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -48,6 +48,8 @@ + #include "sysemu/cpus.h" + #include "sysemu/sysemu.h" + #include "sysemu/kvm.h" ++#include "sysemu/cpus.h" ++#include "sysemu/hw_accel.h" + #include "hw/loader.h" + #include "exec/address-spaces.h" + #include "qemu/bitops.h" +@@ -649,9 +651,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_MEM_HOTPLUG_EVT; + } + +- /* event |= ACPI_GED_CPU_HOTPLUG_EVT; +- * Currently CPU hotplug is not enabled. +- */ ++ if (vms->cpu_hotplug_enabled) { ++ event |= ACPI_GED_CPU_HOTPLUG_EVT; ++ } + + dev = qdev_create(NULL, TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); +@@ -2214,12 +2216,62 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + object_property_set_link(cpuobj, OBJECT(secure_sysmem), + "secure-memory", &error_abort); + } ++ ++ /* If we use KVM accel, we should pause all vcpus to ++ * allow hot access of vcpu registers. ++ */ ++ if (dev->hotplugged && kvm_enabled()) { ++ pause_all_vcpus(); ++ } + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- /* Currently nothing to do */ ++ CPUArchId *cpu_slot; ++ CPUState *cs = CPU(dev); ++ int ncpu = cs->cpu_index; ++ MachineState *ms = MACHINE(hotplug_dev); ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ GICv3State *gicv3; ++ ARMGICv3CommonClass *agcc; ++ Error *local_err = NULL; ++ ++ if (dev->hotplugged) { ++ /* Realize GIC related parts of CPU */ ++ assert(vms->gic_version == 3); ++ gicv3 = ARM_GICV3_COMMON(vms->gic); ++ agcc = ARM_GICV3_COMMON_GET_CLASS(gicv3); ++ agcc->cpu_hotplug_realize(gicv3, ncpu); ++ connect_gic_cpu_irqs(vms, ncpu); ++ ++ /* Register CPU reset and trigger it manually */ ++ cpu_synchronize_state(cs); ++ cpu_hotplug_register_reset(ncpu); ++ cpu_hotplug_reset_manually(ncpu); ++ cpu_synchronize_post_reset(cs); ++ ++ if (kvm_enabled()) { ++ resume_all_vcpus(); ++ } ++ } ++ ++ if (vms->acpi_dev) { ++ hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ ++ vms->boot_cpus++; ++ if (vms->fw_cfg) { ++ fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus); ++ } ++ ++ cpu_slot = &ms->possible_cpus->cpus[ncpu]; ++ cpu_slot->cpu = OBJECT(dev); ++out: ++ error_propagate(errp, local_err); + } + + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, +@@ -2324,6 +2376,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"); + mc->get_default_cpu_node_id = virt_get_default_cpu_node_id; + mc->kvm_type = virt_kvm_type; ++ mc->has_hotpluggable_cpus = true; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + hc->pre_plug = virt_machine_device_pre_plug_cb; +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index b4c53d920e..a9429bed25 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -140,6 +140,7 @@ typedef struct { + uint32_t msi_phandle; + uint32_t iommu_phandle; + int psci_conduit; ++ uint32_t boot_cpus; + hwaddr highest_gpa; + DeviceState *gic; + DeviceState *acpi_dev; +diff --git a/qom/cpu.c b/qom/cpu.c +index f376f782d8..58cd9d5bbc 100644 +--- a/qom/cpu.c ++++ b/qom/cpu.c +@@ -342,7 +342,12 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) + + if (dev->hotplugged) { + cpu_synchronize_post_init(cpu); ++ ++#ifdef __aarch64__ ++ if (!kvm_enabled()) ++#endif + cpu_resume(cpu); ++ + } + + /* NOTE: latest generic point where the cpu is fully realized */ +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 91f1e36cd8..811e5c6365 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2598,6 +2598,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + acc->parent_reset = cc->reset; + cc->reset = arm_cpu_reset; + ++ dc->user_creatable = true; ++ + cc->class_by_name = arm_cpu_class_by_name; + cc->has_work = arm_cpu_has_work; + cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; +-- +2.19.1 diff --git a/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch new file mode 100644 index 0000000000000000000000000000000000000000..297ccf633fe69840b863f10109ee4271f16c11a1 --- /dev/null +++ b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch @@ -0,0 +1,65 @@ +From 91fed8840b004ec7bc91969afa10f03e13f311c4 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 19:52:58 +0800 +Subject: [PATCH] arm/virt/acpi: Extend cpufreq to support max_cpus + +We will support CPU hotplug soon, so extend memory region size to +allow hotplugged CPU access cpufreq space. + +Signed-off-by: Keqian Zhu +--- + hw/acpi/cpufreq.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c +index d02a25a6de..38dcab5683 100644 +--- a/hw/acpi/cpufreq.c ++++ b/hw/acpi/cpufreq.c +@@ -84,6 +84,7 @@ typedef struct CpuhzState { + uint32_t PerformanceLimited; + uint32_t LowestFreq; + uint32_t NominalFreq; ++ uint32_t num_cpu; + uint32_t reg_size; + } CpuhzState; + +@@ -95,10 +96,7 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, + uint64_t r; + uint64_t n; + +- MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; +- +- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) { + warn_report("cpufreq_read: offset 0x%lx out of range", offset); + return 0; + } +@@ -166,11 +164,10 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, + static void cpufreq_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) + { ++ CpuhzState *s = CPUFREQ(opaque); + uint64_t n; +- MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; + +- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) { + error_printf("cpufreq_write: offset 0x%lx out of range", offset); + return; + } +@@ -251,9 +248,9 @@ static void cpufreq_init(Object *obj) + CpuhzState *s = CPUFREQ(obj); + + MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; ++ s->num_cpu = ms->smp.max_cpus; + +- s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; ++ s->reg_size = s->num_cpu * CPPC_REG_PER_CPU_STRIDE; + if (s->reg_size > MAX_SUPPORT_SPACE) { + error_report("Required space 0x%x excesses the max support 0x%x", + s->reg_size, MAX_SUPPORT_SPACE); +-- +2.19.1 diff --git a/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch new file mode 100644 index 0000000000000000000000000000000000000000..f08f83de6505d7810cb7b6753bd00034e3921862 --- /dev/null +++ b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch @@ -0,0 +1,121 @@ +From 2fdece10dac6161cb6c1f0f05247391aa3269eed Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 15:58:27 +0800 +Subject: [PATCH] arm/virt/acpi: Factor out CPPC building from DSDT CPU aml + +When CPU hotplug is enabled, we will use build_cpus_aml instead of +acpi_dsdt_add_cpus, so factor out CPPC building and we can reuse it +in build_cpus_aml. + +Signed-off-by: Keqian Zhu +--- + hw/acpi/generic_event_device.c | 1 + + hw/arm/virt-acpi-build.c | 33 +++++++++++++++++----------- + include/hw/acpi/acpi_dev_interface.h | 2 ++ + include/hw/arm/virt.h | 2 ++ + 4 files changed, 25 insertions(+), 13 deletions(-) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index b834ae3ff6..82139b4314 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -289,6 +289,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) + + adevc->send_event = acpi_ged_send_event; + adevc->madt_cpu = virt_madt_cpu_entry; ++ adevc->cpu_cppc = virt_acpi_dsdt_cpu_cppc; + } + + static const TypeInfo acpi_ged_info = { +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 4b6aace433..8b68a15d76 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -111,8 +111,24 @@ static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) + aml_append(dev, aml_name_decl("_CPC", cpc)); + } + +-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, +- const MemMapEntry *cppc_memmap) ++void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int ncpu, int num_cpu, Aml *dev) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); ++ const MemMapEntry *cppc_memmap = &vms->memmap[VIRT_CPUFREQ]; ++ ++ /* ++ * Append _CPC and _PSD to support CPU frequence show ++ * Check CPPC available by DESIRED_PERF register ++ */ ++ if (cppc_regs_offset[DESIRED_PERF] != -1) { ++ acpi_dsdt_add_cppc(dev, ++ cppc_memmap->base + ncpu * CPPC_REG_PER_CPU_STRIDE, ++ cppc_regs_offset); ++ acpi_dsdt_add_psd(dev, num_cpu); ++ } ++} ++ ++static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, VirtMachineState *vms) + { + uint16_t i; + +@@ -121,16 +137,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); + +- /* +- * Append _CPC and _PSD to support CPU frequence show +- * Check CPPC available by DESIRED_PERF register +- */ +- if (cppc_regs_offset[DESIRED_PERF] != -1) { +- acpi_dsdt_add_cppc(dev, +- cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, +- cppc_regs_offset); +- acpi_dsdt_add_psd(dev, smp_cpus); +- } ++ virt_acpi_dsdt_cpu_cppc(NULL, i, smp_cpus, dev); + + aml_append(scope, dev); + } +@@ -810,7 +817,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + * the RTC ACPI device at all when using UEFI. + */ + scope = aml_scope("\\_SB"); +- acpi_dsdt_add_cpus(scope, vms->smp_cpus, &memmap[VIRT_CPUFREQ]); ++ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], + (irqmap[VIRT_UART] + ARM_SPI_BASE)); + acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); +diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h +index adcb3a816c..2952914569 100644 +--- a/include/hw/acpi/acpi_dev_interface.h ++++ b/include/hw/acpi/acpi_dev_interface.h +@@ -3,6 +3,7 @@ + + #include "qom/object.h" + #include "hw/boards.h" ++#include "hw/acpi/aml-build.h" + + /* These values are part of guest ABI, and can not be changed */ + typedef enum { +@@ -55,5 +56,6 @@ typedef struct AcpiDeviceIfClass { + void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev); + void (*madt_cpu)(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry); ++ void (*cpu_cppc)(AcpiDeviceIf *adev, int uid, int num_cpu, Aml *dev); + } AcpiDeviceIfClass; + #endif +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 6b1f10b231..cbdea7ff32 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -157,6 +157,8 @@ typedef struct { + void virt_acpi_setup(VirtMachineState *vms); + void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *cpu_list, GArray *entry); ++void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int uid, ++ int num_cpu, Aml *dev); + + /* Return the number of used redistributor regions */ + static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) +-- +2.19.1 diff --git a/arm-virt-gic-Construct-irqs-connection-from-create_g.patch b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e9506425f1de938d2ba70a3fb31a83561a4154e --- /dev/null +++ b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch @@ -0,0 +1,123 @@ +From 92124743f4560c490780a229f53ea5881f706383 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Sun, 5 Apr 2020 15:29:16 +0800 +Subject: [PATCH] arm/virt/gic: Construct irqs connection from create_gic + +Make the irqs can be connected to for individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 90 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 49 insertions(+), 41 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 83f4887e57..55d403bad6 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -706,6 +706,54 @@ static void create_v2m(VirtMachineState *vms) + fdt_add_v2m_gic_node(vms); + } + ++static void connect_gic_cpu_irqs(VirtMachineState *vms, int i) ++{ ++ DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); ++ SysBusDevice *gicbusdev = SYS_BUS_DEVICE(vms->gic); ++ int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; ++ int num_cpus = object_property_get_uint(OBJECT(vms->gic), "num-cpu", NULL); ++ int gic_type = vms->gic_version; ++ int irq; ++ /* Mapping from the output timer irq lines from the CPU to the ++ * GIC PPI inputs we use for the virt board. ++ */ ++ const int timer_irq[] = { ++ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, ++ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, ++ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, ++ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, ++ }; ++ ++ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { ++ qdev_connect_gpio_out(cpudev, irq, ++ qdev_get_gpio_in(vms->gic, ++ ppibase + timer_irq[irq])); ++ } ++ ++ if (gic_type == 3) { ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, ++ ppibase + ARCH_GIC_MAINT_IRQ); ++ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", ++ 0, irq); ++ } else if (vms->virt) { ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, ++ ppibase + ARCH_GIC_MAINT_IRQ); ++ sysbus_connect_irq(gicbusdev, i + 4 * num_cpus, irq); ++ } ++ ++ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, ++ qdev_get_gpio_in(vms->gic, ppibase ++ + VIRTUAL_PMU_IRQ)); ++ ++ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); ++ sysbus_connect_irq(gicbusdev, i + num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); ++ sysbus_connect_irq(gicbusdev, i + 2 * num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); ++ sysbus_connect_irq(gicbusdev, i + 3 * num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); ++} ++ + static void create_gic(VirtMachineState *vms) + { + MachineState *ms = MACHINE(vms); +@@ -775,47 +823,7 @@ static void create_gic(VirtMachineState *vms) + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. + */ + for (i = 0; i < smp_cpus; i++) { +- DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); +- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; +- int irq; +- /* Mapping from the output timer irq lines from the CPU to the +- * GIC PPI inputs we use for the virt board. +- */ +- const int timer_irq[] = { +- [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, +- [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, +- [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, +- [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, +- }; +- +- for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { +- qdev_connect_gpio_out(cpudev, irq, +- qdev_get_gpio_in(vms->gic, +- ppibase + timer_irq[irq])); +- } +- +- if (type == 3) { +- qemu_irq irq = qdev_get_gpio_in(vms->gic, +- ppibase + ARCH_GIC_MAINT_IRQ); +- qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", +- 0, irq); +- } else if (vms->virt) { +- qemu_irq irq = qdev_get_gpio_in(vms->gic, +- ppibase + ARCH_GIC_MAINT_IRQ); +- sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); +- } +- +- qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, +- qdev_get_gpio_in(vms->gic, ppibase +- + VIRTUAL_PMU_IRQ)); +- +- sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); +- sysbus_connect_irq(gicbusdev, i + smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); +- sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); +- sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); ++ connect_gic_cpu_irqs(vms, i); + } + + fdt_add_gic_node(vms); +-- +2.19.1 diff --git a/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch b/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch new file mode 100644 index 0000000000000000000000000000000000000000..1dc656892b5f124d3ad732aed9c31b0f71a3363b --- /dev/null +++ b/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch @@ -0,0 +1,24 @@ +From 2892a4b1f7dfc75e06d0ce770d44a062b6334eb0 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 15 Apr 2020 17:03:54 +0800 +Subject: [PATCH] bios-tables-test: prepare to change ARM virt ACPI DSDT + +We will change ARM virt ACPI DSDT table in order to add the cpufreq device, +which use ACPI CPPC to show CPU frequency info to guest. + +Signed-off-by: Ying Fang +--- + tests/bios-tables-test-allowed-diff.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h +index dfb8523c..32a401ae 100644 +--- a/tests/bios-tables-test-allowed-diff.h ++++ b/tests/bios-tables-test-allowed-diff.h +@@ -1 +1,4 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/virt/DSDT", ++"tests/data/acpi/virt/DSDT.memhp", ++"tests/data/acpi/virt/DSDT.numamem", +-- +2.23.0 diff --git a/block-Add-bdrv_co_get_self_request.patch b/block-Add-bdrv_co_get_self_request.patch new file mode 100644 index 0000000000000000000000000000000000000000..4972f084649f70253978ad8fb1d3842bbf741d81 --- /dev/null +++ b/block-Add-bdrv_co_get_self_request.patch @@ -0,0 +1,59 @@ +From d9b88f7e0d56feb4d7daa2506e2756fc48e975a1 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2019 16:25:09 +0100 +Subject: [PATCH] block: Add bdrv_co_get_self_request() + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20191101152510.11719-3-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit c28107e9e55b11cd35cf3dc2505e3e69d10dcf13) +Signed-off-by: Michael Roth +--- + block/io.c | 18 ++++++++++++++++++ + include/block/block_int.h | 1 + + 2 files changed, 19 insertions(+) + +diff --git a/block/io.c b/block/io.c +index d4ceaaa2ce..65b5102714 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -721,6 +721,24 @@ static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req) + (req->bytes == req->overlap_bytes); + } + ++/** ++ * Return the tracked request on @bs for the current coroutine, or ++ * NULL if there is none. ++ */ ++BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs) ++{ ++ BdrvTrackedRequest *req; ++ Coroutine *self = qemu_coroutine_self(); ++ ++ QLIST_FOREACH(req, &bs->tracked_requests, list) { ++ if (req->co == self) { ++ return req; ++ } ++ } ++ ++ return NULL; ++} ++ + /** + * Round a region to cluster boundaries + */ +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 4465b02242..05ee6b4866 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -964,6 +964,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent); + + bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self); + void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align); ++BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs); + + int get_tmp_filename(char *filename, int size); + BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, +-- +2.23.0 diff --git a/block-Make-wait-mark-serialising-requests-public.patch b/block-Make-wait-mark-serialising-requests-public.patch new file mode 100644 index 0000000000000000000000000000000000000000..162463c7769093014562846d9d7c0da4e131b5e3 --- /dev/null +++ b/block-Make-wait-mark-serialising-requests-public.patch @@ -0,0 +1,131 @@ +From 590cff8230749794ba09b38f3ea4eb6b0f2f73b5 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2019 16:25:08 +0100 +Subject: [PATCH] block: Make wait/mark serialising requests public + +Make both bdrv_mark_request_serialising() and +bdrv_wait_serialising_requests() public so they can be used from block +drivers. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20191101152510.11719-2-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit 304d9d7f034ff7f5e1e66a65b7f720f63a72c57e) + Conflicts: + block/io.c +*drop context dependency on 1acc3466a2 +Signed-off-by: Michael Roth +--- + block/io.c | 24 ++++++++++++------------ + include/block/block_int.h | 3 +++ + 2 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/block/io.c b/block/io.c +index 07d2d825c3..d4ceaaa2ce 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -694,7 +694,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req, + qemu_co_mutex_unlock(&bs->reqs_lock); + } + +-static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) ++void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) + { + int64_t overlap_offset = req->offset & ~(align - 1); + uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align) +@@ -784,7 +784,7 @@ void bdrv_dec_in_flight(BlockDriverState *bs) + bdrv_wakeup(bs); + } + +-static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self) ++bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self) + { + BlockDriverState *bs = self->bs; + BdrvTrackedRequest *req; +@@ -1340,14 +1340,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, + * with each other for the same cluster. For example, in copy-on-read + * it ensures that the CoR read and write operations are atomic and + * guest writes cannot interleave between them. */ +- mark_request_serialising(req, bdrv_get_cluster_size(bs)); ++ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs)); + } + + /* BDRV_REQ_SERIALISING is only for write operation */ + assert(!(flags & BDRV_REQ_SERIALISING)); + + if (!(flags & BDRV_REQ_NO_SERIALISING)) { +- wait_serialising_requests(req); ++ bdrv_wait_serialising_requests(req); + } + + if (flags & BDRV_REQ_COPY_ON_READ) { +@@ -1736,10 +1736,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes, + assert(!(flags & ~BDRV_REQ_MASK)); + + if (flags & BDRV_REQ_SERIALISING) { +- mark_request_serialising(req, bdrv_get_cluster_size(bs)); ++ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs)); + } + +- waited = wait_serialising_requests(req); ++ waited = bdrv_wait_serialising_requests(req); + + assert(!waited || !req->serialising || + is_request_serialising_and_aligned(req)); +@@ -1905,8 +1905,8 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, + + padding = bdrv_init_padding(bs, offset, bytes, &pad); + if (padding) { +- mark_request_serialising(req, align); +- wait_serialising_requests(req); ++ bdrv_mark_request_serialising(req, align); ++ bdrv_wait_serialising_requests(req); + + bdrv_padding_rmw_read(child, req, &pad, true); + +@@ -1993,8 +1993,8 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, + } + + if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { +- mark_request_serialising(&req, align); +- wait_serialising_requests(&req); ++ bdrv_mark_request_serialising(&req, align); ++ bdrv_wait_serialising_requests(&req); + bdrv_padding_rmw_read(child, &req, &pad, false); + } + +@@ -3078,7 +3078,7 @@ static int coroutine_fn bdrv_co_copy_range_internal( + /* BDRV_REQ_SERIALISING is only for write operation */ + assert(!(read_flags & BDRV_REQ_SERIALISING)); + if (!(read_flags & BDRV_REQ_NO_SERIALISING)) { +- wait_serialising_requests(&req); ++ bdrv_wait_serialising_requests(&req); + } + + ret = src->bs->drv->bdrv_co_copy_range_from(src->bs, +@@ -3205,7 +3205,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, + * new area, we need to make sure that no write requests are made to it + * concurrently or they might be overwritten by preallocation. */ + if (new_bytes) { +- mark_request_serialising(&req, 1); ++ bdrv_mark_request_serialising(&req, 1); + } + if (bs->read_only) { + error_setg(errp, "Image is read-only"); +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 3aa1e832a8..4465b02242 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -962,6 +962,9 @@ extern unsigned int bdrv_drain_all_count; + void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent); + void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent); + ++bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self); ++void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align); ++ + int get_tmp_filename(char *filename, int size); + BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, + const char *filename); +-- +2.23.0 diff --git a/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch b/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch new file mode 100644 index 0000000000000000000000000000000000000000..73d2b9d0e5e490c3f855304e692ed68fd4029468 --- /dev/null +++ b/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch @@ -0,0 +1,95 @@ +From 088f1e8fd9e790bc5766bd43af134230abcff6dd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 12 Sep 2019 00:08:49 +0200 +Subject: [PATCH] block/create: Do not abort if a block driver is not available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 'blockdev-create' QMP command was introduced as experimental +feature in commit b0292b851b8, using the assert() debug call. +It got promoted to 'stable' command in 3fb588a0f2c, but the +assert call was not removed. + +Some block drivers are optional, and bdrv_find_format() might +return a NULL value, triggering the assertion. + +Stable code is not expected to abort, so return an error instead. + +This is easily reproducible when libnfs is not installed: + + ./configure + [...] + module support no + Block whitelist (rw) + Block whitelist (ro) + libiscsi support yes + libnfs support no + [...] + +Start QEMU: + + $ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait + +Send the 'blockdev-create' with the 'nfs' driver: + + $ ( cat << 'EOF' + {'execute': 'qmp_capabilities'} + {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} + EOF + ) | socat STDIO UNIX:/tmp/qemu.qmp + {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}} + {"return": {}} + +QEMU crashes: + + $ gdb qemu-system-x86_64 core + Program received signal SIGSEGV, Segmentation fault. + (gdb) bt + #0 0x00007ffff510957f in raise () at /lib64/libc.so.6 + #1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6 + #2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6 + #3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6 + #4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69 + #5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314 + #6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131 + #7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174 + +With this patch applied, QEMU returns a QMP error: + + {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} + {"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}} + +Cc: qemu-stable@nongnu.org +Reported-by: Xu Tian +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Eric Blake +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba) +Signed-off-by: Michael Roth +--- + block/create.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/create.c b/block/create.c +index 95341219ef..de5e97bb18 100644 +--- a/block/create.c ++++ b/block/create.c +@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, + const char *fmt = BlockdevDriver_str(options->driver); + BlockDriver *drv = bdrv_find_format(fmt); + ++ if (!drv) { ++ error_setg(errp, "Block driver '%s' not found or not supported", fmt); ++ return; ++ } ++ + /* If the driver is in the schema, we know that it exists. But it may not + * be whitelisted. */ +- assert(drv); + if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) { + error_setg(errp, "Driver is not whitelisted"); + return; +-- +2.23.0 diff --git a/block-file-posix-Let-post-EOF-fallocate-serialize.patch b/block-file-posix-Let-post-EOF-fallocate-serialize.patch new file mode 100644 index 0000000000000000000000000000000000000000..bf7d34a3e54ffe24356a16185d1dfcaef603c455 --- /dev/null +++ b/block-file-posix-Let-post-EOF-fallocate-serialize.patch @@ -0,0 +1,69 @@ +From 7db05c8a732fbdc986a40aadf0de6dd23057d044 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2019 16:25:10 +0100 +Subject: [PATCH] block/file-posix: Let post-EOF fallocate serialize + +The XFS kernel driver has a bug that may cause data corruption for qcow2 +images as of qemu commit c8bb23cbdbe32f. We can work around it by +treating post-EOF fallocates as serializing up until infinity (INT64_MAX +in practice). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20191101152510.11719-4-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit 292d06b925b2787ee6f2430996b95651cae42fce) +Signed-off-by: Michael Roth +--- + block/file-posix.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 992eb4a798..c5df61b477 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2623,6 +2623,42 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, + RawPosixAIOData acb; + ThreadPoolFunc *handler; + ++#ifdef CONFIG_FALLOCATE ++ if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) { ++ BdrvTrackedRequest *req; ++ uint64_t end; ++ ++ /* ++ * This is a workaround for a bug in the Linux XFS driver, ++ * where writes submitted through the AIO interface will be ++ * discarded if they happen beyond a concurrently running ++ * fallocate() that increases the file length (i.e., both the ++ * write and the fallocate() happen beyond the EOF). ++ * ++ * To work around it, we extend the tracked request for this ++ * zero write until INT64_MAX (effectively infinity), and mark ++ * it as serializing. ++ * ++ * We have to enable this workaround for all filesystems and ++ * AIO modes (not just XFS with aio=native), because for ++ * remote filesystems we do not know the host configuration. ++ */ ++ ++ req = bdrv_co_get_self_request(bs); ++ assert(req); ++ assert(req->type == BDRV_TRACKED_WRITE); ++ assert(req->offset <= offset); ++ assert(req->offset + req->bytes >= offset + bytes); ++ ++ end = INT64_MAX & -(uint64_t)bs->bl.request_alignment; ++ req->bytes = end - req->offset; ++ req->overlap_bytes = req->bytes; ++ ++ bdrv_mark_request_serialising(req, bs->bl.request_alignment); ++ bdrv_wait_serialising_requests(req); ++ } ++#endif ++ + acb = (RawPosixAIOData) { + .bs = bs, + .aio_fildes = s->fd, +-- +2.23.0 diff --git a/block-file-posix-Reduce-xfsctl-use.patch b/block-file-posix-Reduce-xfsctl-use.patch new file mode 100644 index 0000000000000000000000000000000000000000..69ceb453efac39a1fcfcc26488e04a7bb8eee0df --- /dev/null +++ b/block-file-posix-Reduce-xfsctl-use.patch @@ -0,0 +1,165 @@ +From 6f1a94035b02d3676a897ea5fa4cda4c62128228 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 23 Aug 2019 15:03:40 +0200 +Subject: [PATCH] block/file-posix: Reduce xfsctl() use +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch removes xfs_write_zeroes() and xfs_discard(). Both functions +have been added just before the same feature was present through +fallocate(): + +- fallocate() has supported PUNCH_HOLE for XFS since Linux 2.6.38 (March + 2011); xfs_discard() was added in December 2010. + +- fallocate() has supported ZERO_RANGE for XFS since Linux 3.15 (June + 2014); xfs_write_zeroes() was added in November 2013. + +Nowadays, all systems that qemu runs on should support both fallocate() +features (RHEL 7's kernel does). + +xfsctl() is still useful for getting the request alignment for O_DIRECT, +so this patch does not remove our dependency on it completely. + +Note that xfs_write_zeroes() had a bug: It calls ftruncate() when the +file is shorter than the specified range (because ZERO_RANGE does not +increase the file length). ftruncate() may yield and then discard data +that parallel write requests have written past the EOF in the meantime. +Dropping the function altogether fixes the bug. + +Suggested-by: Paolo Bonzini +Fixes: 50ba5b2d994853b38fed10e0841b119da0f8b8e5 +Reported-by: Lukáš Doktor +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: Stefano Garzarella +Reviewed-by: John Snow +Tested-by: Stefano Garzarella +Tested-by: John Snow +Signed-off-by: Kevin Wolf +(cherry picked from commit b2c6f23f4a9f6d8f1b648705cd46d3713b78d6a2) +Signed-off-by: Michael Roth +--- + block/file-posix.c | 77 +--------------------------------------------- + 1 file changed, 1 insertion(+), 76 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 4479cc7ab4..992eb4a798 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1445,59 +1445,6 @@ out: + } + } + +-#ifdef CONFIG_XFS +-static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes) +-{ +- int64_t len; +- struct xfs_flock64 fl; +- int err; +- +- len = lseek(s->fd, 0, SEEK_END); +- if (len < 0) { +- return -errno; +- } +- +- if (offset + bytes > len) { +- /* XFS_IOC_ZERO_RANGE does not increase the file length */ +- if (ftruncate(s->fd, offset + bytes) < 0) { +- return -errno; +- } +- } +- +- memset(&fl, 0, sizeof(fl)); +- fl.l_whence = SEEK_SET; +- fl.l_start = offset; +- fl.l_len = bytes; +- +- if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) { +- err = errno; +- trace_file_xfs_write_zeroes(strerror(errno)); +- return -err; +- } +- +- return 0; +-} +- +-static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes) +-{ +- struct xfs_flock64 fl; +- int err; +- +- memset(&fl, 0, sizeof(fl)); +- fl.l_whence = SEEK_SET; +- fl.l_start = offset; +- fl.l_len = bytes; +- +- if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) { +- err = errno; +- trace_file_xfs_discard(strerror(errno)); +- return -err; +- } +- +- return 0; +-} +-#endif +- + static int translate_err(int err) + { + if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP || +@@ -1553,10 +1500,8 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) + static int handle_aiocb_write_zeroes(void *opaque) + { + RawPosixAIOData *aiocb = opaque; +-#if defined(CONFIG_FALLOCATE) || defined(CONFIG_XFS) +- BDRVRawState *s = aiocb->bs->opaque; +-#endif + #ifdef CONFIG_FALLOCATE ++ BDRVRawState *s = aiocb->bs->opaque; + int64_t len; + #endif + +@@ -1564,12 +1509,6 @@ static int handle_aiocb_write_zeroes(void *opaque) + return handle_aiocb_write_zeroes_block(aiocb); + } + +-#ifdef CONFIG_XFS +- if (s->is_xfs) { +- return xfs_write_zeroes(s, aiocb->aio_offset, aiocb->aio_nbytes); +- } +-#endif +- + #ifdef CONFIG_FALLOCATE_ZERO_RANGE + if (s->has_write_zeroes) { + int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE, +@@ -1632,14 +1571,6 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + } + #endif + +-#ifdef CONFIG_XFS +- if (s->is_xfs) { +- /* xfs_discard() guarantees that the discarded area reads as all-zero +- * afterwards, so we can use it here. */ +- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes); +- } +-#endif +- + /* If we couldn't manage to unmap while guaranteed that the area reads as + * all-zero afterwards, just write zeroes without unmapping */ + ret = handle_aiocb_write_zeroes(aiocb); +@@ -1716,12 +1647,6 @@ static int handle_aiocb_discard(void *opaque) + ret = -errno; + #endif + } else { +-#ifdef CONFIG_XFS +- if (s->is_xfs) { +- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes); +- } +-#endif +- + #ifdef CONFIG_FALLOCATE_PUNCH_HOLE + ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + aiocb->aio_offset, aiocb->aio_nbytes); +-- +2.23.0 diff --git a/block-io-refactor-padding.patch b/block-io-refactor-padding.patch new file mode 100644 index 0000000000000000000000000000000000000000..7a267147f5b5fbfa908edf342c02bd17481b3d70 --- /dev/null +++ b/block-io-refactor-padding.patch @@ -0,0 +1,481 @@ +From 2e2ad02f2cecf419eaad0df982ceb5b41170cc7e Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Tue, 4 Jun 2019 19:15:05 +0300 +Subject: [PATCH] block/io: refactor padding + +We have similar padding code in bdrv_co_pwritev, +bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify +it. + +[Squashed in Vladimir's qemu-iotests 077 fix +--Stefan] + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Acked-by: Stefan Hajnoczi +Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com +Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4) +*prereq for 292d06b9 +Signed-off-by: Michael Roth +--- + block/io.c | 365 +++++++++++++++++++++++++++++------------------------ + 1 file changed, 200 insertions(+), 165 deletions(-) + +diff --git a/block/io.c b/block/io.c +index dccf687acc..07d2d825c3 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -1408,28 +1408,177 @@ out: + } + + /* +- * Handle a read request in coroutine context ++ * Request padding ++ * ++ * |<---- align ----->| |<----- align ---->| ++ * |<- head ->|<------------- bytes ------------->|<-- tail -->| ++ * | | | | | | ++ * -*----------$-------*-------- ... --------*-----$------------*--- ++ * | | | | | | ++ * | offset | | end | ++ * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end) ++ * [buf ... ) [tail_buf ) ++ * ++ * @buf is an aligned allocation needed to store @head and @tail paddings. @head ++ * is placed at the beginning of @buf and @tail at the @end. ++ * ++ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk ++ * around tail, if tail exists. ++ * ++ * @merge_reads is true for small requests, ++ * if @buf_len == @head + bytes + @tail. In this case it is possible that both ++ * head and tail exist but @buf_len == align and @tail_buf == @buf. ++ */ ++typedef struct BdrvRequestPadding { ++ uint8_t *buf; ++ size_t buf_len; ++ uint8_t *tail_buf; ++ size_t head; ++ size_t tail; ++ bool merge_reads; ++ QEMUIOVector local_qiov; ++} BdrvRequestPadding; ++ ++static bool bdrv_init_padding(BlockDriverState *bs, ++ int64_t offset, int64_t bytes, ++ BdrvRequestPadding *pad) ++{ ++ uint64_t align = bs->bl.request_alignment; ++ size_t sum; ++ ++ memset(pad, 0, sizeof(*pad)); ++ ++ pad->head = offset & (align - 1); ++ pad->tail = ((offset + bytes) & (align - 1)); ++ if (pad->tail) { ++ pad->tail = align - pad->tail; ++ } ++ ++ if ((!pad->head && !pad->tail) || !bytes) { ++ return false; ++ } ++ ++ sum = pad->head + bytes + pad->tail; ++ pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align; ++ pad->buf = qemu_blockalign(bs, pad->buf_len); ++ pad->merge_reads = sum == pad->buf_len; ++ if (pad->tail) { ++ pad->tail_buf = pad->buf + pad->buf_len - align; ++ } ++ ++ return true; ++} ++ ++static int bdrv_padding_rmw_read(BdrvChild *child, ++ BdrvTrackedRequest *req, ++ BdrvRequestPadding *pad, ++ bool zero_middle) ++{ ++ QEMUIOVector local_qiov; ++ BlockDriverState *bs = child->bs; ++ uint64_t align = bs->bl.request_alignment; ++ int ret; ++ ++ assert(req->serialising && pad->buf); ++ ++ if (pad->head || pad->merge_reads) { ++ uint64_t bytes = pad->merge_reads ? pad->buf_len : align; ++ ++ qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); ++ ++ if (pad->head) { ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); ++ } ++ if (pad->merge_reads && pad->tail) { ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); ++ } ++ ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, ++ align, &local_qiov, 0); ++ if (ret < 0) { ++ return ret; ++ } ++ if (pad->head) { ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); ++ } ++ if (pad->merge_reads && pad->tail) { ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); ++ } ++ ++ if (pad->merge_reads) { ++ goto zero_mem; ++ } ++ } ++ ++ if (pad->tail) { ++ qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align); ++ ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); ++ ret = bdrv_aligned_preadv( ++ child, req, ++ req->overlap_offset + req->overlap_bytes - align, ++ align, align, &local_qiov, 0); ++ if (ret < 0) { ++ return ret; ++ } ++ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); ++ } ++ ++zero_mem: ++ if (zero_middle) { ++ memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail); ++ } ++ ++ return 0; ++} ++ ++static void bdrv_padding_destroy(BdrvRequestPadding *pad) ++{ ++ if (pad->buf) { ++ qemu_vfree(pad->buf); ++ qemu_iovec_destroy(&pad->local_qiov); ++ } ++} ++ ++/* ++ * bdrv_pad_request ++ * ++ * Exchange request parameters with padded request if needed. Don't include RMW ++ * read of padding, bdrv_padding_rmw_read() should be called separately if ++ * needed. ++ * ++ * All parameters except @bs are in-out: they represent original request at ++ * function call and padded (if padding needed) at function finish. ++ * ++ * Function always succeeds. + */ ++static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, ++ int64_t *offset, unsigned int *bytes, ++ BdrvRequestPadding *pad) ++{ ++ if (!bdrv_init_padding(bs, *offset, *bytes, pad)) { ++ return false; ++ } ++ ++ qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head, ++ *qiov, 0, *bytes, ++ pad->buf + pad->buf_len - pad->tail, pad->tail); ++ *bytes += pad->head + pad->tail; ++ *offset -= pad->head; ++ *qiov = &pad->local_qiov; ++ ++ return true; ++} ++ + int coroutine_fn bdrv_co_preadv(BdrvChild *child, + int64_t offset, unsigned int bytes, QEMUIOVector *qiov, + BdrvRequestFlags flags) + { + BlockDriverState *bs = child->bs; +- BlockDriver *drv = bs->drv; + BdrvTrackedRequest req; +- +- uint64_t align = bs->bl.request_alignment; +- uint8_t *head_buf = NULL; +- uint8_t *tail_buf = NULL; +- QEMUIOVector local_qiov; +- bool use_local_qiov = false; ++ BdrvRequestPadding pad; + int ret; + +- trace_bdrv_co_preadv(child->bs, offset, bytes, flags); +- +- if (!drv) { +- return -ENOMEDIUM; +- } ++ trace_bdrv_co_preadv(bs, offset, bytes, flags); + + ret = bdrv_check_byte_request(bs, offset, bytes); + if (ret < 0) { +@@ -1443,43 +1592,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, + flags |= BDRV_REQ_COPY_ON_READ; + } + +- /* Align read if necessary by padding qiov */ +- if (offset & (align - 1)) { +- head_buf = qemu_blockalign(bs, align); +- qemu_iovec_init(&local_qiov, qiov->niov + 2); +- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); +- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); +- use_local_qiov = true; +- +- bytes += offset & (align - 1); +- offset = offset & ~(align - 1); +- } +- +- if ((offset + bytes) & (align - 1)) { +- if (!use_local_qiov) { +- qemu_iovec_init(&local_qiov, qiov->niov + 1); +- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); +- use_local_qiov = true; +- } +- tail_buf = qemu_blockalign(bs, align); +- qemu_iovec_add(&local_qiov, tail_buf, +- align - ((offset + bytes) & (align - 1))); +- +- bytes = ROUND_UP(bytes, align); +- } ++ bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad); + + tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); +- ret = bdrv_aligned_preadv(child, &req, offset, bytes, align, +- use_local_qiov ? &local_qiov : qiov, +- flags); ++ ret = bdrv_aligned_preadv(child, &req, offset, bytes, ++ bs->bl.request_alignment, ++ qiov, flags); + tracked_request_end(&req); + bdrv_dec_in_flight(bs); + +- if (use_local_qiov) { +- qemu_iovec_destroy(&local_qiov); +- qemu_vfree(head_buf); +- qemu_vfree(tail_buf); +- } ++ bdrv_padding_destroy(&pad); + + return ret; + } +@@ -1775,44 +1897,34 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, + BdrvTrackedRequest *req) + { + BlockDriverState *bs = child->bs; +- uint8_t *buf = NULL; + QEMUIOVector local_qiov; + uint64_t align = bs->bl.request_alignment; +- unsigned int head_padding_bytes, tail_padding_bytes; + int ret = 0; ++ bool padding; ++ BdrvRequestPadding pad; + +- head_padding_bytes = offset & (align - 1); +- tail_padding_bytes = (align - (offset + bytes)) & (align - 1); +- +- +- assert(flags & BDRV_REQ_ZERO_WRITE); +- if (head_padding_bytes || tail_padding_bytes) { +- buf = qemu_blockalign(bs, align); +- qemu_iovec_init_buf(&local_qiov, buf, align); +- } +- if (head_padding_bytes) { +- uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes); +- +- /* RMW the unaligned part before head. */ ++ padding = bdrv_init_padding(bs, offset, bytes, &pad); ++ if (padding) { + mark_request_serialising(req, align); + wait_serialising_requests(req); +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); +- ret = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align, +- align, &local_qiov, 0); +- if (ret < 0) { +- goto fail; +- } +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); + +- memset(buf + head_padding_bytes, 0, zero_bytes); +- ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align, +- align, &local_qiov, +- flags & ~BDRV_REQ_ZERO_WRITE); +- if (ret < 0) { +- goto fail; ++ bdrv_padding_rmw_read(child, req, &pad, true); ++ ++ if (pad.head || pad.merge_reads) { ++ int64_t aligned_offset = offset & ~(align - 1); ++ int64_t write_bytes = pad.merge_reads ? pad.buf_len : align; ++ ++ qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); ++ ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes, ++ align, &local_qiov, ++ flags & ~BDRV_REQ_ZERO_WRITE); ++ if (ret < 0 || pad.merge_reads) { ++ /* Error or all work is done */ ++ goto out; ++ } ++ offset += write_bytes - pad.head; ++ bytes -= write_bytes - pad.head; + } +- offset += zero_bytes; +- bytes -= zero_bytes; + } + + assert(!bytes || (offset & (align - 1)) == 0); +@@ -1822,7 +1934,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, + ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align, + NULL, flags); + if (ret < 0) { +- goto fail; ++ goto out; + } + bytes -= aligned_bytes; + offset += aligned_bytes; +@@ -1830,26 +1942,17 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, + + assert(!bytes || (offset & (align - 1)) == 0); + if (bytes) { +- assert(align == tail_padding_bytes + bytes); +- /* RMW the unaligned part after tail. */ +- mark_request_serialising(req, align); +- wait_serialising_requests(req); +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); +- ret = bdrv_aligned_preadv(child, req, offset, align, +- align, &local_qiov, 0); +- if (ret < 0) { +- goto fail; +- } +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); ++ assert(align == pad.tail + bytes); + +- memset(buf, 0, bytes); ++ qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); + ret = bdrv_aligned_pwritev(child, req, offset, align, align, + &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE); + } +-fail: +- qemu_vfree(buf); +- return ret; + ++out: ++ bdrv_padding_destroy(&pad); ++ ++ return ret; + } + + /* +@@ -1862,10 +1965,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, + BlockDriverState *bs = child->bs; + BdrvTrackedRequest req; + uint64_t align = bs->bl.request_alignment; +- uint8_t *head_buf = NULL; +- uint8_t *tail_buf = NULL; +- QEMUIOVector local_qiov; +- bool use_local_qiov = false; ++ BdrvRequestPadding pad; + int ret; + + trace_bdrv_co_pwritev(child->bs, offset, bytes, flags); +@@ -1892,86 +1992,21 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, + goto out; + } + +- if (offset & (align - 1)) { +- QEMUIOVector head_qiov; +- ++ if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { + mark_request_serialising(&req, align); + wait_serialising_requests(&req); +- +- head_buf = qemu_blockalign(bs, align); +- qemu_iovec_init_buf(&head_qiov, head_buf, align); +- +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); +- ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align, +- align, &head_qiov, 0); +- if (ret < 0) { +- goto fail; +- } +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); +- +- qemu_iovec_init(&local_qiov, qiov->niov + 2); +- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); +- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); +- use_local_qiov = true; +- +- bytes += offset & (align - 1); +- offset = offset & ~(align - 1); +- +- /* We have read the tail already if the request is smaller +- * than one aligned block. +- */ +- if (bytes < align) { +- qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes); +- bytes = align; +- } +- } +- +- if ((offset + bytes) & (align - 1)) { +- QEMUIOVector tail_qiov; +- size_t tail_bytes; +- bool waited; +- +- mark_request_serialising(&req, align); +- waited = wait_serialising_requests(&req); +- assert(!waited || !use_local_qiov); +- +- tail_buf = qemu_blockalign(bs, align); +- qemu_iovec_init_buf(&tail_qiov, tail_buf, align); +- +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); +- ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1), +- align, align, &tail_qiov, 0); +- if (ret < 0) { +- goto fail; +- } +- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); +- +- if (!use_local_qiov) { +- qemu_iovec_init(&local_qiov, qiov->niov + 1); +- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); +- use_local_qiov = true; +- } +- +- tail_bytes = (offset + bytes) & (align - 1); +- qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes); +- +- bytes = ROUND_UP(bytes, align); ++ bdrv_padding_rmw_read(child, &req, &pad, false); + } + + ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, +- use_local_qiov ? &local_qiov : qiov, +- flags); ++ qiov, flags); + +-fail: ++ bdrv_padding_destroy(&pad); + +- if (use_local_qiov) { +- qemu_iovec_destroy(&local_qiov); +- } +- qemu_vfree(head_buf); +- qemu_vfree(tail_buf); + out: + tracked_request_end(&req); + bdrv_dec_in_flight(bs); ++ + return ret; + } + +-- +2.23.0 diff --git a/block-nfs-tear-down-aio-before-nfs_close.patch b/block-nfs-tear-down-aio-before-nfs_close.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea116d0a381c18521da88b94d3ea914f0357939d --- /dev/null +++ b/block-nfs-tear-down-aio-before-nfs_close.patch @@ -0,0 +1,41 @@ +From 0694c489cd240620fee5675e8d24c7ce02d1d67d Mon Sep 17 00:00:00 2001 +From: Peter Lieven +Date: Tue, 10 Sep 2019 17:41:09 +0200 +Subject: [PATCH] block/nfs: tear down aio before nfs_close + +nfs_close is a sync call from libnfs and has its own event +handler polling on the nfs FD. Avoid that both QEMU and libnfs +are intefering here. + +CC: qemu-stable@nongnu.org +Signed-off-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914) +Signed-off-by: Michael Roth +--- + block/nfs.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/block/nfs.c b/block/nfs.c +index d93241b3bb..2b7a078241 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -390,12 +390,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs, + static void nfs_client_close(NFSClient *client) + { + if (client->context) { ++ qemu_mutex_lock(&client->mutex); ++ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), ++ false, NULL, NULL, NULL, NULL); ++ qemu_mutex_unlock(&client->mutex); + if (client->fh) { + nfs_close(client->context, client->fh); + client->fh = NULL; + } +- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), +- false, NULL, NULL, NULL, NULL); + nfs_destroy_context(client->context); + client->context = NULL; + } +-- +2.23.0 diff --git a/block-posix-Always-allocate-the-first-block.patch b/block-posix-Always-allocate-the-first-block.patch new file mode 100644 index 0000000000000000000000000000000000000000..166d73957ce0569929276d446a1934be17cad612 --- /dev/null +++ b/block-posix-Always-allocate-the-first-block.patch @@ -0,0 +1,343 @@ +From 3d018ff3bdd8aec260254036b600cfa8d694ced4 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Tue, 27 Aug 2019 04:05:27 +0300 +Subject: [PATCH] block: posix: Always allocate the first block + +When creating an image with preallocation "off" or "falloc", the first +block of the image is typically not allocated. When using Gluster +storage backed by XFS filesystem, reading this block using direct I/O +succeeds regardless of request length, fooling alignment detection. + +In this case we fallback to a safe value (4096) instead of the optimal +value (512), which may lead to unneeded data copying when aligning +requests. Allocating the first block avoids the fallback. + +Since we allocate the first block even with preallocation=off, we no +longer create images with zero disk size: + + $ ./qemu-img create -f raw test.raw 1g + Formatting 'test.raw', fmt=raw size=1073741824 + + $ ls -lhs test.raw + 4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw + +And converting the image requires additional cluster: + + $ ./qemu-img measure -f raw -O qcow2 test.raw + required size: 458752 + fully allocated size: 1074135040 + +When using format like vmdk with multiple files per image, we allocate +one block per file: + + $ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g + Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat + + $ ls -lhs test*.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk + +I did quick performance test for copying disks with qemu-img convert to +new raw target image to Gluster storage with sector size of 512 bytes: + + for i in $(seq 10); do + rm -f dst.raw + sleep 10 + time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw + done + +Here is a table comparing the total time spent: + +Type Before(s) After(s) Diff(%) +--------------------------------------- +real 530.028 469.123 -11.4 +user 17.204 10.768 -37.4 +sys 17.881 7.011 -60.7 + +We can see very clear improvement in CPU usage. + +Signed-off-by: Nir Soffer +Message-id: 20190827010528.8818-2-nsoffer@redhat.com +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz + +(cherry picked from commit 3a20013fbb26d2a1bd11ef148eefdb1508783787) + +Signed-off-by: Michael Roth +--- + block/file-posix.c | 51 +++++++++++++++++++ + tests/qemu-iotests/059.out | 2 +- + tests/qemu-iotests/{150.out => 150.out.qcow2} | 0 + tests/qemu-iotests/150.out.raw | 12 +++++ + tests/qemu-iotests/175 | 19 ++++--- + tests/qemu-iotests/175.out | 8 +-- + tests/qemu-iotests/178.out.qcow2 | 4 +- + tests/qemu-iotests/221.out | 12 +++-- + tests/qemu-iotests/253.out | 12 +++-- + 9 files changed, 99 insertions(+), 21 deletions(-) + rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%) + create mode 100644 tests/qemu-iotests/150.out.raw + +diff --git a/block/file-posix.c b/block/file-posix.c +index be32dd8c51..2184aa980c 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1674,6 +1674,43 @@ static int handle_aiocb_discard(void *opaque) + return ret; + } + ++/* ++ * Help alignment probing by allocating the first block. ++ * ++ * When reading with direct I/O from unallocated area on Gluster backed by XFS, ++ * reading succeeds regardless of request length. In this case we fallback to ++ * safe alignment which is not optimal. Allocating the first block avoids this ++ * fallback. ++ * ++ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or ++ * request alignment, so we use safe values. ++ * ++ * Returns: 0 on success, -errno on failure. Since this is an optimization, ++ * caller may ignore failures. ++ */ ++static int allocate_first_block(int fd, size_t max_size) ++{ ++ size_t write_size = (max_size < MAX_BLOCKSIZE) ++ ? BDRV_SECTOR_SIZE ++ : MAX_BLOCKSIZE; ++ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); ++ void *buf; ++ ssize_t n; ++ int ret; ++ ++ buf = qemu_memalign(max_align, write_size); ++ memset(buf, 0, write_size); ++ ++ do { ++ n = pwrite(fd, buf, write_size, 0); ++ } while (n == -1 && errno == EINTR); ++ ++ ret = (n == -1) ? -errno : 0; ++ ++ qemu_vfree(buf); ++ return ret; ++} ++ + static int handle_aiocb_truncate(void *opaque) + { + RawPosixAIOData *aiocb = opaque; +@@ -1713,6 +1750,17 @@ static int handle_aiocb_truncate(void *opaque) + /* posix_fallocate() doesn't set errno. */ + error_setg_errno(errp, -result, + "Could not preallocate new data"); ++ } else if (current_length == 0) { ++ /* ++ * posix_fallocate() uses fallocate() if the filesystem ++ * supports it, or fallback to manually writing zeroes. If ++ * fallocate() was used, unaligned reads from the fallocated ++ * area in raw_probe_alignment() will succeed, hence we need to ++ * allocate the first block. ++ * ++ * Optimize future alignment probing; ignore failures. ++ */ ++ allocate_first_block(fd, offset); + } + } else { + result = 0; +@@ -1774,6 +1822,9 @@ static int handle_aiocb_truncate(void *opaque) + if (ftruncate(fd, offset) != 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not resize file"); ++ } else if (current_length == 0 && offset > current_length) { ++ /* Optimize future alignment probing; ignore failures. */ ++ allocate_first_block(fd, offset); + } + return result; + default: +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 4fab42a28c..fe3f861f3c 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -27,7 +27,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax + image: TEST_DIR/t.vmdk + file format: vmdk + virtual size: 0.977 TiB (1073741824000 bytes) +-disk size: 16 KiB ++disk size: 1.97 MiB + Format specific information: + cid: XXXXXXXX + parent cid: XXXXXXXX +diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out.qcow2 +similarity index 100% +rename from tests/qemu-iotests/150.out +rename to tests/qemu-iotests/150.out.qcow2 +diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw +new file mode 100644 +index 0000000000..3cdc7727a5 +--- /dev/null ++++ b/tests/qemu-iotests/150.out.raw +@@ -0,0 +1,12 @@ ++QA output created by 150 ++ ++=== Mapping sparse conversion === ++ ++Offset Length File ++0 0x1000 TEST_DIR/t.IMGFMT ++ ++=== Mapping non-sparse conversion === ++ ++Offset Length File ++0 0x100000 TEST_DIR/t.IMGFMT ++*** done +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index 51e62c8276..7ba28b3c1b 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -37,14 +37,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + # the file size. This function hides the resulting difference in the + # stat -c '%b' output. + # Parameter 1: Number of blocks an empty file occupies +-# Parameter 2: Image size in bytes ++# Parameter 2: Minimal number of blocks in an image ++# Parameter 3: Image size in bytes + _filter_blocks() + { + extra_blocks=$1 +- img_size=$2 ++ min_blocks=$2 ++ img_size=$3 + +- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ +- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" ++ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \ ++ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" + } + + # get standard environment, filters and checks +@@ -60,16 +62,21 @@ size=$((1 * 1024 * 1024)) + touch "$TEST_DIR/empty" + extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") + ++# We always write the first byte; check how many blocks this filesystem ++# allocates to match empty image alloation. ++printf "\0" > "$TEST_DIR/empty" ++min_blocks=$(stat -c '%b' "$TEST_DIR/empty") ++ + echo + echo "== creating image with default preallocation ==" + _make_test_img $size | _filter_imgfmt +-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" + IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt +- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + done + + # success, all done +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 6d9a5ed84e..263e521262 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -2,17 +2,17 @@ QA output created by 175 + + == creating image with default preallocation == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation off == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation full == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full +-size=1048576, everything allocated ++size=1048576, max allocation + + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc +-size=1048576, everything allocated ++size=1048576, max allocation + *** done +diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 +index 55a8dc926f..9e7d8c44df 100644 +--- a/tests/qemu-iotests/178.out.qcow2 ++++ b/tests/qemu-iotests/178.out.qcow2 +@@ -101,7 +101,7 @@ converted image file size in bytes: 196608 + == raw input image with data (human) == + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 +-required size: 393216 ++required size: 458752 + fully allocated size: 1074135040 + wrote 512/512 bytes at offset 512 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -257,7 +257,7 @@ converted image file size in bytes: 196608 + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 + { +- "required": 393216, ++ "required": 458752, + "fully-allocated": 1074135040 + } + wrote 512/512 bytes at offset 512 +diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out +index 9f9dd52bb0..dca024a0c3 100644 +--- a/tests/qemu-iotests/221.out ++++ b/tests/qemu-iotests/221.out +@@ -3,14 +3,18 @@ QA output created by 221 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 1/1 bytes at offset 65536 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + *** done +diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out +index 607c0baa0b..3d08b305d7 100644 +--- a/tests/qemu-iotests/253.out ++++ b/tests/qemu-iotests/253.out +@@ -3,12 +3,16 @@ QA output created by 253 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 65535/65535 bytes at offset 983040 + 63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] + *** done +-- +2.23.0 diff --git a/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch b/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch new file mode 100644 index 0000000000000000000000000000000000000000..f77cc06c60dd36ccd84a5ad5c5e9748bb2126c08 --- /dev/null +++ b/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch @@ -0,0 +1,66 @@ +From 84f22c728520792f1010074e0d5ac2ec8e2e372c Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 15 Sep 2019 23:36:53 +0300 +Subject: [PATCH] block/qcow2: Fix corruption introduced by commit 8ac0f15f335 + +This fixes subtle corruption introduced by luks threaded encryption +in commit 8ac0f15f335 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922 + +The corruption happens when we do a write that + * writes to two or more unallocated clusters at once + * doesn't fully cover the first sector + * doesn't fully cover the last sector + * uses luks encryption + +In this case, when allocating the new clusters we COW both areas +prior to the write and after the write, and we encrypt them. + +The above mentioned commit accidentally made it so we encrypt the +second COW area using the physical cluster offset of the first area. + +The problem is that offset_in_cluster in do_perform_cow_encrypt +can be larger that the cluster size, thus cluster_offset +will no longer point to the start of the cluster at which encrypted +area starts. + +Next patch in this series will refactor the code to avoid all these +assumptions. + +In the bugreport that was triggered by rebasing a luks image to new, +zero filled base, which lot of such writes, and causes some files +with zero areas to contain garbage there instead. +But as described above it can happen elsewhere as well + +Signed-off-by: Maxim Levitsky +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-id: 20190915203655.21638-2-mlevitsk@redhat.com +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit 38e7d54bdc518b5a05a922467304bcace2396945) +Signed-off-by: Michael Roth +--- + block/qcow2-cluster.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index cc5609e27a..760564c8fb 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -473,9 +473,10 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, + assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); + assert((bytes & ~BDRV_SECTOR_MASK) == 0); + assert(s->crypto); +- if (qcow2_co_encrypt(bs, cluster_offset, +- src_cluster_offset + offset_in_cluster, +- buffer, bytes) < 0) { ++ if (qcow2_co_encrypt(bs, ++ start_of_cluster(s, cluster_offset + offset_in_cluster), ++ src_cluster_offset + offset_in_cluster, ++ buffer, bytes) < 0) { + return false; + } + } +-- +2.23.0 diff --git a/block-snapshot-Restrict-set-of-snapshot-nodes.patch b/block-snapshot-Restrict-set-of-snapshot-nodes.patch new file mode 100644 index 0000000000000000000000000000000000000000..c29f30adc897f5b60bf8004b7f317b6e6257bf3a --- /dev/null +++ b/block-snapshot-Restrict-set-of-snapshot-nodes.patch @@ -0,0 +1,124 @@ +From 7a8aa6c734bb1c2927ad0cc1d10bcacb53cf4ae3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 17 Sep 2019 12:26:23 +0200 +Subject: [PATCH] block/snapshot: Restrict set of snapshot nodes + +Nodes involved in internal snapshots were those that were returned by +bdrv_next(), inserted and not read-only. bdrv_next() in turn returns all +nodes that are either the root node of a BlockBackend or monitor-owned +nodes. + +With the typical -drive use, this worked well enough. However, in the +typical -blockdev case, the user defines one node per option, making all +nodes monitor-owned nodes. This includes protocol nodes etc. which often +are not snapshottable, so "savevm" only returns an error. + +Change the conditions so that internal snapshot still include all nodes +that have a BlockBackend attached (we definitely want to snapshot +anything attached to a guest device and probably also the built-in NBD +server; snapshotting block job BlockBackends is more of an accident, but +a preexisting one), but other monitor-owned nodes are only included if +they have no parents. + +This makes internal snapshots usable again with typical -blockdev +configurations. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Peter Krempa +Tested-by: Peter Krempa +(cherry picked from commit 05f4aced658a02b02d3e89a6c7a2281008fcf26c) +Signed-off-by: Michael Roth +--- + block/snapshot.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/block/snapshot.c b/block/snapshot.c +index f2f48f926a..8081616ae9 100644 +--- a/block/snapshot.c ++++ b/block/snapshot.c +@@ -31,6 +31,7 @@ + #include "qapi/qmp/qerror.h" + #include "qapi/qmp/qstring.h" + #include "qemu/option.h" ++#include "sysemu/block-backend.h" + + QemuOptsList internal_snapshot_opts = { + .name = "snapshot", +@@ -384,6 +385,16 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, + return ret; + } + ++static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs) ++{ ++ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { ++ return false; ++ } ++ ++ /* Include all nodes that are either in use by a BlockBackend, or that ++ * aren't attached to any node, but owned by the monitor. */ ++ return bdrv_has_blk(bs) || QLIST_EMPTY(&bs->parents); ++} + + /* Group operations. All block drivers are involved. + * These functions will properly handle dataplane (take aio_context_acquire +@@ -399,7 +410,7 @@ bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs) + AioContext *ctx = bdrv_get_aio_context(bs); + + aio_context_acquire(ctx); +- if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) { ++ if (bdrv_all_snapshots_includes_bs(bs)) { + ok = bdrv_can_snapshot(bs); + } + aio_context_release(ctx); +@@ -426,8 +437,9 @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs, + AioContext *ctx = bdrv_get_aio_context(bs); + + aio_context_acquire(ctx); +- if (bdrv_can_snapshot(bs) && +- bdrv_snapshot_find(bs, snapshot, name) >= 0) { ++ if (bdrv_all_snapshots_includes_bs(bs) && ++ bdrv_snapshot_find(bs, snapshot, name) >= 0) ++ { + ret = bdrv_snapshot_delete(bs, snapshot->id_str, + snapshot->name, err); + } +@@ -455,7 +467,7 @@ int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs, + AioContext *ctx = bdrv_get_aio_context(bs); + + aio_context_acquire(ctx); +- if (bdrv_can_snapshot(bs)) { ++ if (bdrv_all_snapshots_includes_bs(bs)) { + ret = bdrv_snapshot_goto(bs, name, errp); + } + aio_context_release(ctx); +@@ -481,7 +493,7 @@ int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs) + AioContext *ctx = bdrv_get_aio_context(bs); + + aio_context_acquire(ctx); +- if (bdrv_can_snapshot(bs)) { ++ if (bdrv_all_snapshots_includes_bs(bs)) { + err = bdrv_snapshot_find(bs, &sn, name); + } + aio_context_release(ctx); +@@ -512,7 +524,7 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn, + if (bs == vm_state_bs) { + sn->vm_state_size = vm_state_size; + err = bdrv_snapshot_create(bs, sn); +- } else if (bdrv_can_snapshot(bs)) { ++ } else if (bdrv_all_snapshots_includes_bs(bs)) { + sn->vm_state_size = 0; + err = bdrv_snapshot_create(bs, sn); + } +@@ -538,7 +550,7 @@ BlockDriverState *bdrv_all_find_vmstate_bs(void) + bool found; + + aio_context_acquire(ctx); +- found = bdrv_can_snapshot(bs); ++ found = bdrv_all_snapshots_includes_bs(bs) && bdrv_can_snapshot(bs); + aio_context_release(ctx); + + if (found) { +-- +2.23.0 diff --git a/blockjob-update-nodes-head-while-removing-all-bdrv.patch b/blockjob-update-nodes-head-while-removing-all-bdrv.patch new file mode 100644 index 0000000000000000000000000000000000000000..36cedc77f7d38b124263a6f5d09e5f1dc97de5b8 --- /dev/null +++ b/blockjob-update-nodes-head-while-removing-all-bdrv.patch @@ -0,0 +1,61 @@ +From 86b0f4022bb43b16979ba5300e8d40a1e6d44b79 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez +Date: Wed, 11 Sep 2019 12:03:16 +0200 +Subject: [PATCH] blockjob: update nodes head while removing all bdrv + +block_job_remove_all_bdrv() iterates through job->nodes, calling +bdrv_root_unref_child() for each entry. The call to the latter may +reach child_job_[can_]set_aio_ctx(), which will also attempt to +traverse job->nodes, potentially finding entries that where freed +on previous iterations. + +To avoid this situation, update job->nodes head on each iteration to +ensure that already freed entries are no longer linked to the list. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631 +Signed-off-by: Sergio Lopez +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190911100316.32282-1-mreitz@redhat.com +Reviewed-by: Sergio Lopez +Signed-off-by: Max Reitz +(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f) +Signed-off-by: Michael Roth +--- + blockjob.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/blockjob.c b/blockjob.c +index 20b7f557da..74abb97bfd 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -186,14 +186,23 @@ static const BdrvChildRole child_job = { + + void block_job_remove_all_bdrv(BlockJob *job) + { +- GSList *l; +- for (l = job->nodes; l; l = l->next) { ++ /* ++ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), ++ * which will also traverse job->nodes, so consume the list one by ++ * one to make sure that such a concurrent access does not attempt ++ * to process an already freed BdrvChild. ++ */ ++ while (job->nodes) { ++ GSList *l = job->nodes; + BdrvChild *c = l->data; ++ ++ job->nodes = l->next; ++ + bdrv_op_unblock_all(c->bs, job->blocker); + bdrv_root_unref_child(c); ++ ++ g_slist_free_1(l); + } +- g_slist_free(job->nodes); +- job->nodes = NULL; + } + + bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) +-- +2.23.0 diff --git a/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch b/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch new file mode 100644 index 0000000000000000000000000000000000000000..e714cb10bef351cd6ed6df71d08f3666df879ed5 --- /dev/null +++ b/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch @@ -0,0 +1,44 @@ +From b9e4a4ff6f3292927adb1463777c86cd4063a6ef Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Sat, 18 Apr 2020 12:10:11 +0800 +Subject: [PATCH] bugfix: Use gicr_typer in arm_gicv3_icc_reset + +The KVM_VGIC_ATTR macro expect the second parameter as gicr_typer, +of which high 32bit is constructed by mp_affinity. For most case, +the high 32bit of mp_affinity is zero, so it will always access the +ICC_CTLR_EL1 of CPU0. + +Signed-off-by: Keqian Zhu +--- + hw/intc/arm_gicv3_kvm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index d9c72f85be..b1e74147ba 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -661,13 +661,11 @@ static void kvm_arm_gicv3_get(GICv3State *s) + + static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) + { +- ARMCPU *cpu; + GICv3State *s; + GICv3CPUState *c; + + c = (GICv3CPUState *)env->gicv3state; + s = c->gic; +- cpu = ARM_CPU(c->cpu); + + c->icc_pmr_el1 = 0; + c->icc_bpr[GICV3_G0] = GIC_MIN_BPR; +@@ -684,7 +682,7 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) + + /* Initialize to actual HW supported configuration */ + kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, +- KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity), ++ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), + &c->icc_ctlr_el1[GICV3_NS], false, &error_abort); + + c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; +-- +2.19.1 diff --git a/coroutine-Add-qemu_co_mutex_assert_locked.patch b/coroutine-Add-qemu_co_mutex_assert_locked.patch new file mode 100644 index 0000000000000000000000000000000000000000..fb1f2589f3edd987f0311288d049951c726ddeb8 --- /dev/null +++ b/coroutine-Add-qemu_co_mutex_assert_locked.patch @@ -0,0 +1,50 @@ +From e9bb3d942e268a19e03fc5d404586d2ed1564282 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 24 Oct 2019 16:26:57 +0200 +Subject: [PATCH] coroutine: Add qemu_co_mutex_assert_locked() + +Some functions require that the caller holds a certain CoMutex for them +to operate correctly. Add a function so that they can assert the lock is +really held. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Tested-by: Michael Weiser +Reviewed-by: Michael Weiser +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Denis V. Lunev +Reviewed-by: Max Reitz +(cherry picked from commit 944f3d5dd216fcd8cb007eddd4f82dced0a15b3d) +Signed-off-by: Michael Roth +--- + include/qemu/coroutine.h | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h +index 9801e7f5a4..f4843b5f59 100644 +--- a/include/qemu/coroutine.h ++++ b/include/qemu/coroutine.h +@@ -167,6 +167,21 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); + */ + void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); + ++/** ++ * Assert that the current coroutine holds @mutex. ++ */ ++static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) ++{ ++ /* ++ * mutex->holder doesn't need any synchronisation if the assertion holds ++ * true because the mutex protects it. If it doesn't hold true, we still ++ * don't mind if another thread takes or releases mutex behind our back, ++ * because the condition will be false no matter whether we read NULL or ++ * the pointer for any other coroutine. ++ */ ++ assert(atomic_read(&mutex->locked) && ++ mutex->holder == qemu_coroutine_self()); ++} + + /** + * CoQueues are a mechanism to queue coroutines in order to continue executing +-- +2.23.0 diff --git a/cpu-add-Kunpeng-920-cpu-support.patch b/cpu-add-Kunpeng-920-cpu-support.patch index 149a1a123e8deae9de1e634aa025618518c7f56f..74e27645ac18a07c00a04283f428bec515cf259e 100644 --- a/cpu-add-Kunpeng-920-cpu-support.patch +++ b/cpu-add-Kunpeng-920-cpu-support.patch @@ -3,6 +3,8 @@ From: Xu Yandong Date: Wed, 28 Aug 2019 01:36:21 -0400 Subject: [PATCH] cpu: add Kunpeng-920 cpu support +Add the Kunpeng-920 CPU model. + Signed-off-by: Xu Yandong --- hw/arm/virt.c | 1 + @@ -28,7 +30,7 @@ index 228906f2..5581d5e1 100644 @@ -258,6 +258,26 @@ static void aarch64_a72_initfn(Object *obj) define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); } - + +static void aarch64_kunpeng_920_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); @@ -60,6 +62,5 @@ index 228906f2..5581d5e1 100644 { .name = "max", .initfn = aarch64_max_initfn }, { .name = NULL } }; --- +-- 2.19.1 - diff --git a/cpu-parse-feature-to-avoid-failure.patch b/cpu-parse-feature-to-avoid-failure.patch index a241a5f140c371f792a75839c53fb5b8779f7060..78178bfa3dd2a9dd1413dd3c12bbc8e6ed6d2869 100644 --- a/cpu-parse-feature-to-avoid-failure.patch +++ b/cpu-parse-feature-to-avoid-failure.patch @@ -1,8 +1,11 @@ From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001 -From: rpm-build +From: Xu Yandong Date: Tue, 3 Sep 2019 16:27:39 +0800 Subject: [PATCH] cpu: parse +/- feature to avoid failure +To avoid cpu feature parse failuer, +/- feature is added. + +Signed-off-by: Xu Yandong --- target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch new file mode 100644 index 0000000000000000000000000000000000000000..c61c9fd848c4e1d68baa778388c8440a8d28ec32 --- /dev/null +++ b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch @@ -0,0 +1,79 @@ +From fbde196c30e4797a51bda046ba514b187963d4ba Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 29 Jul 2019 23:34:16 +0200 +Subject: [PATCH] dma-helpers: ensure AIO callback is invoked after + cancellation + +dma_aio_cancel unschedules the BH if there is one, which corresponds +to the reschedule_dma case of dma_blk_cb. This can stall the DMA +permanently, because dma_complete will never get invoked and therefore +nobody will ever invoke the original AIO callback in dbs->common.cb. + +Fix this by invoking the callback (which is ensured to happen after +a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and +add assertions to check that the DMA state machine is indeed waiting +for dma_complete or reschedule_dma, but never both. + +Reported-by: John Snow +Signed-off-by: Paolo Bonzini +Message-id: 20190729213416.1972-1-pbonzini@redhat.com +Signed-off-by: John Snow +(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f) +Signed-off-by: Michael Roth +--- + dma-helpers.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/dma-helpers.c b/dma-helpers.c +index 2d7e02d35e..d3871dc61e 100644 +--- a/dma-helpers.c ++++ b/dma-helpers.c +@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque) + { + DMAAIOCB *dbs = (DMAAIOCB *)opaque; + ++ assert(!dbs->acb && dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; + dma_blk_cb(dbs, 0); +@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret) + { + trace_dma_complete(dbs, ret, dbs->common.cb); + ++ assert(!dbs->acb && !dbs->bh); + dma_blk_unmap(dbs); + if (dbs->common.cb) { + dbs->common.cb(dbs->common.opaque, ret); + } + qemu_iovec_destroy(&dbs->iov); +- if (dbs->bh) { +- qemu_bh_delete(dbs->bh); +- dbs->bh = NULL; +- } + qemu_aio_unref(dbs); + } + +@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb) + + trace_dma_aio_cancel(dbs); + ++ assert(!(dbs->acb && dbs->bh)); + if (dbs->acb) { ++ /* This will invoke dma_blk_cb. */ + blk_aio_cancel_async(dbs->acb); ++ return; + } ++ + if (dbs->bh) { + cpu_unregister_map_client(dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; + } ++ if (dbs->common.cb) { ++ dbs->common.cb(dbs->common.opaque, -ECANCELED); ++ } + } + + static AioContext *dma_get_aio_context(BlockAIOCB *acb) +-- +2.23.0 diff --git a/docs-specs-Add-ACPI-GED-documentation.patch b/docs-specs-Add-ACPI-GED-documentation.patch new file mode 100644 index 0000000000000000000000000000000000000000..46e8c17483ba33af2b75e954233c3cbdc5c7cddc --- /dev/null +++ b/docs-specs-Add-ACPI-GED-documentation.patch @@ -0,0 +1,107 @@ +From 9c1752703fb8a5b70985cf4c9caabc3388c5953b Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:31 +0100 +Subject: [PATCH] docs/specs: Add ACPI GED documentation + +Documents basic concepts of ACPI Generic Event device(GED) +and interface between QEMU and the ACPI BIOS. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Message-Id: <20190918130633.4872-10-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + docs/specs/acpi_hw_reduced_hotplug.rst | 70 ++++++++++++++++++++++++++ + docs/specs/index.rst | 1 + + 2 files changed, 71 insertions(+) + create mode 100644 docs/specs/acpi_hw_reduced_hotplug.rst + +diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst +new file mode 100644 +index 0000000000..911a98255b +--- /dev/null ++++ b/docs/specs/acpi_hw_reduced_hotplug.rst +@@ -0,0 +1,70 @@ ++================================================== ++QEMU and ACPI BIOS Generic Event Device interface ++================================================== ++ ++The ACPI *Generic Event Device* (GED) is a HW reduced platform ++specific device introduced in ACPI v6.1 that handles all platform ++events, including the hotplug ones. GED is modelled as a device ++in the namespace with a _HID defined to be ACPI0013. This document ++describes the interface between QEMU and the ACPI BIOS. ++ ++GED allows HW reduced platforms to handle interrupts in ACPI ASL ++statements. It follows a very similar approach to the _EVT method ++from GPIO events. All interrupts are listed in _CRS and the handler ++is written in _EVT method. However, the QEMU implementation uses a ++single interrupt for the GED device, relying on an IO memory region ++to communicate the type of device affected by the interrupt. This way, ++we can support up to 32 events with a unique interrupt. ++ ++**Here is an example,** ++ ++:: ++ ++ Device (\_SB.GED) ++ { ++ Name (_HID, "ACPI0013") ++ Name (_UID, Zero) ++ Name (_CRS, ResourceTemplate () ++ { ++ Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) ++ { ++ 0x00000029, ++ } ++ }) ++ OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) ++ Field (EREG, DWordAcc, NoLock, WriteAsZeros) ++ { ++ ESEL, 32 ++ } ++ Method (_EVT, 1, Serialized) ++ { ++ Local0 = ESEL // ESEL = IO memory region which specifies the ++ // device type. ++ If (((Local0 & One) == One)) ++ { ++ MethodEvent1() ++ } ++ If ((Local0 & 0x2) == 0x2) ++ { ++ MethodEvent2() ++ } ++ ... ++ } ++ } ++ ++GED IO interface (4 byte access) ++-------------------------------- ++**read access:** ++ ++:: ++ ++ [0x0-0x3] Event selector bit field (32 bit) set by QEMU. ++ ++ bits: ++ 0: Memory hotplug event ++ 1: System power down event ++ 2-31: Reserved ++ ++**write_access:** ++ ++Nothing is expected to be written into GED IO memory +diff --git a/docs/specs/index.rst b/docs/specs/index.rst +index 40adb97c5e..984ba44029 100644 +--- a/docs/specs/index.rst ++++ b/docs/specs/index.rst +@@ -12,3 +12,4 @@ Contents: + + ppc-xive + ppc-spapr-xive ++ acpi_hw_reduced_hotplug +-- +2.19.1 diff --git a/hbitmap-handle-set-reset-with-zero-length.patch b/hbitmap-handle-set-reset-with-zero-length.patch new file mode 100644 index 0000000000000000000000000000000000000000..b346a970d8594e2fae6a730c8c66370dc66af0da --- /dev/null +++ b/hbitmap-handle-set-reset-with-zero-length.patch @@ -0,0 +1,50 @@ +From c0b35d87de345bd3b59a44c604b247a0497f2fc0 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Fri, 11 Oct 2019 12:07:07 +0300 +Subject: [PATCH] hbitmap: handle set/reset with zero length + +Passing zero length to these functions leads to unpredicted results. +Zero-length set/reset may occur in active-mirror, on zero-length write +(which is unlikely, but not guaranteed to never happen). + +Let's just do nothing on zero-length request. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-id: 20191011090711.19940-2-vsementsov@virtuozzo.com +Reviewed-by: Max Reitz +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +(cherry picked from commit fed33bd175f663cc8c13f8a490a4f35a19756cfe) +Signed-off-by: Michael Roth +--- + util/hbitmap.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/util/hbitmap.c b/util/hbitmap.c +index 71c6ba2c52..c059313b9e 100644 +--- a/util/hbitmap.c ++++ b/util/hbitmap.c +@@ -387,6 +387,10 @@ void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count) + uint64_t first, n; + uint64_t last = start + count - 1; + ++ if (count == 0) { ++ return; ++ } ++ + trace_hbitmap_set(hb, start, count, + start >> hb->granularity, last >> hb->granularity); + +@@ -478,6 +482,10 @@ void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count) + uint64_t last = start + count - 1; + uint64_t gran = 1ULL << hb->granularity; + ++ if (count == 0) { ++ return; ++ } ++ + assert(QEMU_IS_ALIGNED(start, gran)); + assert(QEMU_IS_ALIGNED(count, gran) || (start + count == hb->orig_size)); + +-- +2.23.0 diff --git a/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch b/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc57aa64dd12427afc1e59af0476206317065d1b --- /dev/null +++ b/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch @@ -0,0 +1,478 @@ +From b12d9edd0079d4ee136c25e95333918b0c6d3cd9 Mon Sep 17 00:00:00 2001 +From: Samuel Ortiz +Date: Wed, 18 Sep 2019 14:06:25 +0100 +Subject: [PATCH] hw/acpi: Add ACPI Generic Event Device Support + +The ACPI Generic Event Device (GED) is a hardware-reduced specific +device[ACPI v6.1 Section 5.6.9] that handles all platform events, +including the hotplug ones. This patch generates the AML code that +defines GEDs. + +Platforms need to specify their own GED Event bitmap to describe +what kind of events they want to support through GED. Also this +uses a a single interrupt for the GED device, relying on IO +memory region to communicate the type of device affected by the +interrupt. This way, we can support up to 32 events with a unique +interrupt. + +This supports only memory hotplug for now. + +Signed-off-by: Samuel Ortiz +Signed-off-by: Sebastien Boeuf +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Message-Id: <20190918130633.4872-4-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + hw/acpi/Kconfig | 4 + + hw/acpi/Makefile.objs | 1 + + hw/acpi/generic_event_device.c | 303 +++++++++++++++++++++++++ + include/hw/acpi/generic_event_device.h | 100 ++++++++ + 4 files changed, 408 insertions(+) + create mode 100644 hw/acpi/generic_event_device.c + create mode 100644 include/hw/acpi/generic_event_device.h + +diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig +index 7c59cf900b..12e3f1e86e 100644 +--- a/hw/acpi/Kconfig ++++ b/hw/acpi/Kconfig +@@ -31,3 +31,7 @@ config ACPI_VMGENID + bool + default y + depends on PC ++ ++config ACPI_HW_REDUCED ++ bool ++ depends on ACPI +diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs +index 1a720c381e..e4b5d101a4 100644 +--- a/hw/acpi/Makefile.objs ++++ b/hw/acpi/Makefile.objs +@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o + common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o + common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o + common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o ++common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o + common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o + + common-obj-y += acpi_interface.o +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +new file mode 100644 +index 0000000000..b94500b08d +--- /dev/null ++++ b/hw/acpi/generic_event_device.c +@@ -0,0 +1,303 @@ ++/* ++ * ++ * Copyright (c) 2018 Intel Corporation ++ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd ++ * Written by Samuel Ortiz, Shameer Kolothum ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2 or later, as published by the Free Software Foundation. ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "exec/address-spaces.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/generic_event_device.h" ++#include "hw/irq.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/qdev-properties.h" ++#include "migration/vmstate.h" ++#include "qemu/error-report.h" ++ ++static const uint32_t ged_supported_events[] = { ++ ACPI_GED_MEM_HOTPLUG_EVT, ++}; ++ ++/* ++ * The ACPI Generic Event Device (GED) is a hardware-reduced specific ++ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, ++ * including the hotplug ones. Platforms need to specify their own ++ * GED Event bitmap to describe what kind of events they want to support ++ * through GED. This routine uses a single interrupt for the GED device, ++ * relying on IO memory region to communicate the type of device ++ * affected by the interrupt. This way, we can support up to 32 events ++ * with a unique interrupt. ++ */ ++void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, ++ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base) ++{ ++ AcpiGedState *s = ACPI_GED(hotplug_dev); ++ Aml *crs = aml_resource_template(); ++ Aml *evt, *field; ++ Aml *dev = aml_device("%s", name); ++ Aml *evt_sel = aml_local(0); ++ Aml *esel = aml_name(AML_GED_EVT_SEL); ++ ++ /* _CRS interrupt */ ++ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, ++ AML_EXCLUSIVE, &ged_irq, 1)); ++ ++ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013"))); ++ aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE))); ++ aml_append(dev, aml_name_decl("_CRS", crs)); ++ ++ /* Append IO region */ ++ aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs, ++ aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET), ++ ACPI_GED_EVT_SEL_LEN)); ++ field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK, ++ AML_WRITE_AS_ZEROS); ++ aml_append(field, aml_named_field(AML_GED_EVT_SEL, ++ ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE)); ++ aml_append(dev, field); ++ ++ /* ++ * For each GED event we: ++ * - Add a conditional block for each event, inside a loop. ++ * - Call a method for each supported GED event type. ++ * ++ * The resulting ASL code looks like: ++ * ++ * Local0 = ESEL ++ * If ((Local0 & One) == One) ++ * { ++ * MethodEvent0() ++ * } ++ * ++ * If ((Local0 & 0x2) == 0x2) ++ * { ++ * MethodEvent1() ++ * } ++ * ... ++ */ ++ evt = aml_method("_EVT", 1, AML_SERIALIZED); ++ { ++ Aml *if_ctx; ++ uint32_t i; ++ uint32_t ged_events = ctpop32(s->ged_event_bitmap); ++ ++ /* Local0 = ESEL */ ++ aml_append(evt, aml_store(esel, evt_sel)); ++ ++ for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { ++ uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; ++ ++ if (!event) { ++ continue; ++ } ++ ++ if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL), ++ aml_int(event))); ++ switch (event) { ++ case ACPI_GED_MEM_HOTPLUG_EVT: ++ aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." ++ MEMORY_SLOT_SCAN_METHOD)); ++ break; ++ default: ++ /* ++ * Please make sure all the events in ged_supported_events[] ++ * are handled above. ++ */ ++ g_assert_not_reached(); ++ } ++ ++ aml_append(evt, if_ctx); ++ ged_events--; ++ } ++ ++ if (ged_events) { ++ error_report("Unsupported events specified"); ++ abort(); ++ } ++ } ++ ++ /* Append _EVT method */ ++ aml_append(dev, evt); ++ ++ aml_append(table, dev); ++} ++ ++/* Memory read by the GED _EVT AML dynamic method */ ++static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ uint64_t val = 0; ++ GEDState *ged_st = opaque; ++ ++ switch (addr) { ++ case ACPI_GED_EVT_SEL_OFFSET: ++ /* Read the selector value and reset it */ ++ val = ged_st->sel; ++ ged_st->sel = 0; ++ break; ++ default: ++ break; ++ } ++ ++ return val; ++} ++ ++/* Nothing is expected to be written to the GED memory region */ ++static void ged_write(void *opaque, hwaddr addr, uint64_t data, ++ unsigned int size) ++{ ++} ++ ++static const MemoryRegionOps ged_ops = { ++ .read = ged_read, ++ .write = ged_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 4, ++ }, ++}; ++ ++static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ AcpiGedState *s = ACPI_GED(hotplug_dev); ++ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); ++ } else { ++ error_setg(errp, "virt: device plug request for unsupported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) ++{ ++ AcpiGedState *s = ACPI_GED(adev); ++ GEDState *ged_st = &s->ged_state; ++ uint32_t sel; ++ ++ if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { ++ sel = ACPI_GED_MEM_HOTPLUG_EVT; ++ } else { ++ /* Unknown event. Return without generating interrupt. */ ++ warn_report("GED: Unsupported event %d. No irq injected", ev); ++ return; ++ } ++ ++ /* ++ * Set the GED selector field to communicate the event type. ++ * This will be read by GED aml code to select the appropriate ++ * event method. ++ */ ++ ged_st->sel |= sel; ++ ++ /* Trigger the event by sending an interrupt to the guest. */ ++ qemu_irq_pulse(s->irq); ++} ++ ++static Property acpi_ged_properties[] = { ++ DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), ++ DEFINE_PROP_END_OF_LIST(), ++}; ++ ++static const VMStateDescription vmstate_memhp_state = { ++ .name = "acpi-ged/memhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_ged_state = { ++ .name = "acpi-ged-state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(sel, GEDState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_acpi_ged = { ++ .name = "acpi-ged", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState), ++ VMSTATE_END_OF_LIST(), ++ }, ++ .subsections = (const VMStateDescription * []) { ++ &vmstate_memhp_state, ++ NULL ++ } ++}; ++ ++static void acpi_ged_initfn(Object *obj) ++{ ++ DeviceState *dev = DEVICE(obj); ++ AcpiGedState *s = ACPI_GED(dev); ++ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); ++ GEDState *ged_st = &s->ged_state; ++ ++ memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, ++ TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); ++ sysbus_init_mmio(sbd, &ged_st->io); ++ ++ sysbus_init_irq(sbd, &s->irq); ++ ++ s->memhp_state.is_enabled = true; ++ /* ++ * GED handles memory hotplug event and acpi-mem-hotplug ++ * memory region gets initialized here. Create an exclusive ++ * container for memory hotplug IO and expose it as GED sysbus ++ * MMIO so that boards can map it separately. ++ */ ++ memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container", ++ MEMORY_HOTPLUG_IO_LEN); ++ sysbus_init_mmio(sbd, &s->container_memhp); ++ acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), ++ &s->memhp_state, 0); ++} ++ ++static void acpi_ged_class_init(ObjectClass *class, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(class); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); ++ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); ++ ++ dc->desc = "ACPI Generic Event Device"; ++ dc->props = acpi_ged_properties; ++ dc->vmsd = &vmstate_acpi_ged; ++ ++ hc->plug = acpi_ged_device_plug_cb; ++ ++ adevc->send_event = acpi_ged_send_event; ++} ++ ++static const TypeInfo acpi_ged_info = { ++ .name = TYPE_ACPI_GED, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(AcpiGedState), ++ .instance_init = acpi_ged_initfn, ++ .class_init = acpi_ged_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { TYPE_ACPI_DEVICE_IF }, ++ { } ++ } ++}; ++ ++static void acpi_ged_register_types(void) ++{ ++ type_register_static(&acpi_ged_info); ++} ++ ++type_init(acpi_ged_register_types) +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +new file mode 100644 +index 0000000000..2049e8d873 +--- /dev/null ++++ b/include/hw/acpi/generic_event_device.h +@@ -0,0 +1,100 @@ ++/* ++ * ++ * Copyright (c) 2018 Intel Corporation ++ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd ++ * Written by Samuel Ortiz, Shameer Kolothum ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2 or later, as published by the Free Software Foundation. ++ * ++ * The ACPI Generic Event Device (GED) is a hardware-reduced specific ++ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, ++ * including the hotplug ones. Generic Event Device allows platforms ++ * to handle interrupts in ACPI ASL statements. It follows a very ++ * similar approach like the _EVT method from GPIO events. All ++ * interrupts are listed in _CRS and the handler is written in _EVT ++ * method. Here, we use a single interrupt for the GED device, relying ++ * on IO memory region to communicate the type of device affected by ++ * the interrupt. This way, we can support up to 32 events with a ++ * unique interrupt. ++ * ++ * Here is an example. ++ * ++ * Device (\_SB.GED) ++ * { ++ * Name (_HID, "ACPI0013") ++ * Name (_UID, Zero) ++ * Name (_CRS, ResourceTemplate () ++ * { ++ * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) ++ * { ++ * 0x00000029, ++ * } ++ * }) ++ * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) ++ * Field (EREG, DWordAcc, NoLock, WriteAsZeros) ++ * { ++ * ESEL, 32 ++ * } ++ * ++ * Method (_EVT, 1, Serialized) // _EVT: Event ++ * { ++ * Local0 = ESEL // ESEL = IO memory region which specifies the ++ * // device type. ++ * If (((Local0 & One) == One)) ++ * { ++ * MethodEvent1() ++ * } ++ * If ((Local0 & 0x2) == 0x2) ++ * { ++ * MethodEvent2() ++ * } ++ * ... ++ * } ++ * } ++ * ++ */ ++ ++#ifndef HW_ACPI_GED_H ++#define HW_ACPI_GED_H ++ ++#include "hw/sysbus.h" ++#include "hw/acpi/memory_hotplug.h" ++ ++#define TYPE_ACPI_GED "acpi-ged" ++#define ACPI_GED(obj) \ ++ OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) ++ ++#define ACPI_GED_EVT_SEL_OFFSET 0x0 ++#define ACPI_GED_EVT_SEL_LEN 0x4 ++ ++#define GED_DEVICE "GED" ++#define AML_GED_EVT_REG "EREG" ++#define AML_GED_EVT_SEL "ESEL" ++ ++/* ++ * Platforms need to specify the GED event bitmap ++ * to describe what kind of events they want to support ++ * through GED. ++ */ ++#define ACPI_GED_MEM_HOTPLUG_EVT 0x1 ++ ++typedef struct GEDState { ++ MemoryRegion io; ++ uint32_t sel; ++} GEDState; ++ ++typedef struct AcpiGedState { ++ SysBusDevice parent_obj; ++ MemHotplugState memhp_state; ++ MemoryRegion container_memhp; ++ GEDState ged_state; ++ uint32_t ged_event_bitmap; ++ qemu_irq irq; ++} AcpiGedState; ++ ++void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, ++ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); ++ ++#endif +-- +2.19.1 diff --git a/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch b/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch new file mode 100644 index 0000000000000000000000000000000000000000..292687199fbe797b86b25ac2fb56063f7080a0f0 --- /dev/null +++ b/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch @@ -0,0 +1,46 @@ +From 7a08983315bf4d624966a89112259e2b4949de91 Mon Sep 17 00:00:00 2001 +From: Samuel Ortiz +Date: Wed, 18 Sep 2019 14:06:24 +0100 +Subject: [PATCH] hw/acpi: Do not create memory hotplug method when handler is + not defined + +With Hardware-reduced ACPI, the GED device will manage ACPI +hotplug entirely. As a consequence, make the memory specific +events AML generation optional. The code will only be added +when the method name is not NULL. + +Signed-off-by: Samuel Ortiz +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-3-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/memory_hotplug.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c +index 9a515c0484..8b30356c1a 100644 +--- a/hw/acpi/memory_hotplug.c ++++ b/hw/acpi/memory_hotplug.c +@@ -711,10 +711,12 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + } + aml_append(table, dev_container); + +- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); +- aml_append(method, +- aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD)); +- aml_append(table, method); ++ if (event_handler_method) { ++ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); ++ aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "." ++ MEMORY_SLOT_SCAN_METHOD)); ++ aml_append(table, method); ++ } + + g_free(mhp_res_path); + } +-- +2.19.1 diff --git a/hw-acpi-Make-ACPI-IO-address-space-configurable.patch b/hw-acpi-Make-ACPI-IO-address-space-configurable.patch new file mode 100644 index 0000000000000000000000000000000000000000..cdf597b51566400b17ddac3e27dc93cb65a61bd6 --- /dev/null +++ b/hw-acpi-Make-ACPI-IO-address-space-configurable.patch @@ -0,0 +1,196 @@ +From 6cd7281c73ca462b2f27969f1e28f1afd3ebe82d Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:23 +0100 +Subject: [PATCH] hw/acpi: Make ACPI IO address space configurable + +This is in preparation for adding support for ARM64 platforms +where it doesn't use port mapped IO for ACPI IO space. We are +making changes so that MMIO region can be accommodated +and board can pass the base address into the aml build function. + +Also move few MEMORY_* definitions to header so that other memory +hotplug event signalling mechanisms (eg. Generic Event Device on +HW-reduced acpi platforms) can use the same from their respective +event handler code. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-2-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/memory_hotplug.c | 33 ++++++++++++++------------------ + hw/i386/acpi-build.c | 7 ++++++- + hw/i386/pc.c | 3 +++ + include/hw/acpi/memory_hotplug.h | 9 +++++++-- + include/hw/i386/pc.h | 3 +++ + 5 files changed, 33 insertions(+), 22 deletions(-) + +diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c +index 297812d5f7..9a515c0484 100644 +--- a/hw/acpi/memory_hotplug.c ++++ b/hw/acpi/memory_hotplug.c +@@ -29,12 +29,7 @@ + #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM" + #define MEMORY_SLOT_EJECT_METHOD "MEJ0" + #define MEMORY_SLOT_NOTIFY_METHOD "MTFY" +-#define MEMORY_SLOT_SCAN_METHOD "MSCN" + #define MEMORY_HOTPLUG_DEVICE "MHPD" +-#define MEMORY_HOTPLUG_IO_LEN 24 +-#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" +- +-static uint16_t memhp_io_base; + + static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev) + { +@@ -209,7 +204,7 @@ static const MemoryRegionOps acpi_memory_hotplug_ops = { + }; + + void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, +- MemHotplugState *state, uint16_t io_base) ++ MemHotplugState *state, hwaddr io_base) + { + MachineState *machine = MACHINE(qdev_get_machine()); + +@@ -218,12 +213,10 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, + return; + } + +- assert(!memhp_io_base); +- memhp_io_base = io_base; + state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count); + memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state, + "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN); +- memory_region_add_subregion(as, memhp_io_base, &state->io); ++ memory_region_add_subregion(as, io_base, &state->io); + } + + /** +@@ -342,7 +335,8 @@ const VMStateDescription vmstate_memory_hotplug = { + + void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + const char *res_root, +- const char *event_handler_method) ++ const char *event_handler_method, ++ AmlRegionSpace rs, hwaddr memhp_io_base) + { + int i; + Aml *ifctx; +@@ -351,10 +345,6 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + Aml *mem_ctrl_dev; + char *mhp_res_path; + +- if (!memhp_io_base) { +- return; +- } +- + mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root); + mem_ctrl_dev = aml_device("%s", mhp_res_path); + { +@@ -365,14 +355,19 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + aml_name_decl("_UID", aml_string("Memory hotplug resources"))); + + crs = aml_resource_template(); +- aml_append(crs, +- aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, +- MEMORY_HOTPLUG_IO_LEN) +- ); ++ if (rs == AML_SYSTEM_IO) { ++ aml_append(crs, ++ aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, ++ MEMORY_HOTPLUG_IO_LEN) ++ ); ++ } else { ++ aml_append(crs, aml_memory32_fixed(memhp_io_base, ++ MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE)); ++ } + aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs)); + + aml_append(mem_ctrl_dev, aml_operation_region( +- MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, ++ MEMORY_HOTPLUG_IO_REGION, rs, + aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN) + ); + +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index f3fdfefcd5..749218561a 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1871,7 +1871,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, + "\\_SB.PCI0", "\\_GPE._E02"); + } +- build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", "\\_GPE._E03"); ++ ++ if (pcms->memhp_io_base && nr_mem) { ++ build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", ++ "\\_GPE._E03", AML_SYSTEM_IO, ++ pcms->memhp_io_base); ++ } + + scope = aml_scope("_GPE"); + { +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index d011733ff7..8a914130b0 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1936,6 +1936,9 @@ void pc_memory_init(PCMachineState *pcms, + + /* Init default IOAPIC address space */ + pcms->ioapic_as = &address_space_memory; ++ ++ /* Init ACPI memory hotplug IO base address */ ++ pcms->memhp_io_base = ACPI_MEMORY_HOTPLUG_BASE; + } + + /* +diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h +index 77c65765d6..dfe9cf3fde 100644 +--- a/include/hw/acpi/memory_hotplug.h ++++ b/include/hw/acpi/memory_hotplug.h +@@ -5,6 +5,10 @@ + #include "hw/acpi/acpi.h" + #include "hw/acpi/aml-build.h" + ++#define MEMORY_SLOT_SCAN_METHOD "MSCN" ++#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" ++#define MEMORY_HOTPLUG_IO_LEN 24 ++ + /** + * MemStatus: + * @is_removing: the memory device in slot has been requested to be ejected. +@@ -29,7 +33,7 @@ typedef struct MemHotplugState { + } MemHotplugState; + + void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, +- MemHotplugState *state, uint16_t io_base); ++ MemHotplugState *state, hwaddr io_base); + + void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, + DeviceState *dev, Error **errp); +@@ -48,5 +52,6 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); + + void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + const char *res_root, +- const char *event_handler_method); ++ const char *event_handler_method, ++ AmlRegionSpace rs, hwaddr memhp_io_base); + #endif +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 859b64c51d..49b47535cf 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -69,6 +69,9 @@ struct PCMachineState { + /* Address space used by IOAPIC device. All IOAPIC interrupts + * will be translated to MSI messages in the address space. */ + AddressSpace *ioapic_as; ++ ++ /* ACPI Memory hotplug IO base address */ ++ hwaddr memhp_io_base; + }; + + #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" +-- +2.19.1 diff --git a/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch b/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2c0f3900d05652a977be13df0babb8210c65b1b --- /dev/null +++ b/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch @@ -0,0 +1,72 @@ +From e6b1fd7bfbfe116e9d5df590f7069336c1eb1983 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:29 +0100 +Subject: [PATCH] hw/arm: Factor out powerdown notifier from GPIO + +This is in preparation of using GED device for +system_powerdown event. Make the powerdown notifier +registration independent of create_gpio() fn. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-8-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/virt.c | 12 ++++-------- + include/hw/arm/virt.h | 1 + + 2 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index ab33cce4b3..aaefa5578e 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -910,10 +910,6 @@ static void virt_powerdown_req(Notifier *n, void *opaque) + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); + } + +-static Notifier virt_system_powerdown_notifier = { +- .notify = virt_powerdown_req +-}; +- + static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + { + char *nodename; +@@ -954,10 +950,6 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + KEY_POWER); + qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", + "gpios", phandle, 3, 0); +- +- /* connect powerdown request */ +- qemu_register_powerdown_notifier(&virt_system_powerdown_notifier); +- + g_free(nodename); + } + +@@ -1856,6 +1848,10 @@ static void machvirt_init(MachineState *machine) + vms->acpi_dev = create_acpi_ged(vms, pic); + } + ++ /* connect powerdown request */ ++ vms->powerdown_notifier.notify = virt_powerdown_req; ++ qemu_register_powerdown_notifier(&vms->powerdown_notifier); ++ + /* Create mmio transports, so the user can create virtio backends + * (which will be automatically plugged in to the transports). If + * no backend is created the transport will just sit harmlessly idle. +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 0350285136..dcceb9c615 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -139,6 +139,7 @@ typedef struct { + int psci_conduit; + hwaddr highest_gpa; + DeviceState *acpi_dev; ++ Notifier powerdown_notifier; + } VirtMachineState; + + #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +-- +2.19.1 diff --git a/hw-arm-Use-GED-for-system_powerdown-event.patch b/hw-arm-Use-GED-for-system_powerdown-event.patch new file mode 100644 index 0000000000000000000000000000000000000000..140f59a2c71da40f47a2edd2bd2dd529227c3ddc --- /dev/null +++ b/hw-arm-Use-GED-for-system_powerdown-event.patch @@ -0,0 +1,167 @@ +From 0b77f242b180f1ae40b9752999cef4894113df8e Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:30 +0100 +Subject: [PATCH] hw/arm: Use GED for system_powerdown event + +For machines 4.2 or higher with ACPI boot use GED for system_powerdown +event instead of GPIO. Guest boot with DT still uses GPIO. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/generic_event_device.c | 8 ++++++++ + hw/arm/virt-acpi-build.c | 6 +++--- + hw/arm/virt.c | 18 ++++++++++++------ + include/hw/acpi/acpi_dev_interface.h | 1 + + include/hw/acpi/generic_event_device.h | 3 +++ + 5 files changed, 27 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index b94500b08d..9cee90cc70 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -22,6 +22,7 @@ + + static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, ++ ACPI_GED_PWR_DOWN_EVT, + }; + + /* +@@ -104,6 +105,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." + MEMORY_SLOT_SCAN_METHOD)); + break; ++ case ACPI_GED_PWR_DOWN_EVT: ++ aml_append(if_ctx, ++ aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), ++ aml_int(0x80))); ++ break; + default: + /* + * Please make sure all the events in ged_supported_events[] +@@ -184,6 +190,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) + + if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { + sel = ACPI_GED_MEM_HOTPLUG_EVT; ++ } else if (ev & ACPI_POWER_DOWN_STATUS) { ++ sel = ACPI_GED_PWR_DOWN_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 9622994e50..f48733d9f2 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -50,7 +50,6 @@ + #include "hw/acpi/acpi-defs.h" + + #define ARM_SPI_BASE 32 +-#define ACPI_POWER_BUTTON_DEVICE "PWRB" + + static void acpi_dsdt_add_psd(Aml *dev, int cpus) + { +@@ -813,13 +812,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); + acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), + vms->highmem, vms->highmem_ecam); +- acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], +- (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); + if (vms->acpi_dev) { + build_ged_aml(scope, "\\_SB."GED_DEVICE, + HOTPLUG_HANDLER(vms->acpi_dev), + irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, + memmap[VIRT_ACPI_GED].base); ++ } else { ++ acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], ++ (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); + } + + if (vms->acpi_dev) { +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index aaefa5578e..18321e522b 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -639,10 +639,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) + DeviceState *dev; + MachineState *ms = MACHINE(vms); + int irq = vms->irqmap[VIRT_ACPI_GED]; +- uint32_t event = 0; ++ uint32_t event = ACPI_GED_PWR_DOWN_EVT; + + if (ms->ram_slots) { +- event = ACPI_GED_MEM_HOTPLUG_EVT; ++ event |= ACPI_GED_MEM_HOTPLUG_EVT; + } + + dev = qdev_create(NULL, TYPE_ACPI_GED); +@@ -906,8 +906,14 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) + static DeviceState *gpio_key_dev; + static void virt_powerdown_req(Notifier *n, void *opaque) + { +- /* use gpio Pin 3 for power button event */ +- qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); ++ VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); ++ ++ if (s->acpi_dev) { ++ acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); ++ } else { ++ /* use gpio Pin 3 for power button event */ ++ qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); ++ } + } + + static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) +@@ -1842,10 +1848,10 @@ static void machvirt_init(MachineState *machine) + + create_pcie(vms, pic); + +- create_gpio(vms, pic); +- + if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { + vms->acpi_dev = create_acpi_ged(vms, pic); ++ } else { ++ create_gpio(vms, pic); + } + + /* connect powerdown request */ +diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h +index 43ff119179..adcb3a816c 100644 +--- a/include/hw/acpi/acpi_dev_interface.h ++++ b/include/hw/acpi/acpi_dev_interface.h +@@ -11,6 +11,7 @@ typedef enum { + ACPI_MEMORY_HOTPLUG_STATUS = 8, + ACPI_NVDIMM_HOTPLUG_STATUS = 16, + ACPI_VMGENID_CHANGE_STATUS = 32, ++ ACPI_POWER_DOWN_STATUS = 64, + } AcpiEventStatusBits; + + #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index 2049e8d873..d157eac088 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -62,6 +62,8 @@ + #include "hw/sysbus.h" + #include "hw/acpi/memory_hotplug.h" + ++#define ACPI_POWER_BUTTON_DEVICE "PWRB" ++ + #define TYPE_ACPI_GED "acpi-ged" + #define ACPI_GED(obj) \ + OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) +@@ -79,6 +81,7 @@ + * through GED. + */ + #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 ++#define ACPI_GED_PWR_DOWN_EVT 0x2 + + typedef struct GEDState { + MemoryRegion io; +-- +2.19.1 diff --git a/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch new file mode 100644 index 0000000000000000000000000000000000000000..95abd07e5a2b62acd14c1a45e61ce471707f173e --- /dev/null +++ b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch @@ -0,0 +1,115 @@ +From de86ba0ff72a51b0c1cdbebf790869aea73ae9d3 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Thu, 9 Apr 2020 09:31:22 +0800 +Subject: [PATCH] hw/arm/boot: Add manually register and trigger of CPU reset + +We need to register and trigger CPU reset manually for hotplugged +CPU. Besides, we gather CPU reset handlers of all CPUs because CPU +reset should happen before GIC reset. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/boot.c | 18 ++++++++++++++++++ + hw/core/reset.c | 25 +++++++++++++++++++++++++ + include/hw/arm/boot.h | 3 +++ + include/sysemu/reset.h | 4 ++++ + 4 files changed, 50 insertions(+) + +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index fc4e021a38..3ab9de6456 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -789,6 +789,24 @@ static void do_cpu_reset(void *opaque) + } + } + ++void cpu_hotplug_register_reset(int ncpu) ++{ ++ CPUState *cpu_0 = qemu_get_cpu(0); ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ QEMUResetEntry *entry = qemu_get_reset_entry(do_cpu_reset, cpu_0); ++ ++ assert(entry); ++ /* Gather the reset handlers of all CPUs */ ++ qemu_register_reset_after(entry, do_cpu_reset, cpu); ++} ++ ++void cpu_hotplug_reset_manually(int ncpu) ++{ ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ ++ do_cpu_reset(cpu); ++} ++ + /** + * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified + * by key. +diff --git a/hw/core/reset.c b/hw/core/reset.c +index 9c477f2bf5..0efaf2d76c 100644 +--- a/hw/core/reset.c ++++ b/hw/core/reset.c +@@ -47,6 +47,31 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque) + QTAILQ_INSERT_TAIL(&reset_handlers, re, entry); + } + ++QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, ++ void *opaque) ++{ ++ QEMUResetEntry *re; ++ ++ QTAILQ_FOREACH(re, &reset_handlers, entry) { ++ if (re->func == func && re->opaque == opaque) { ++ return re; ++ } ++ } ++ ++ return NULL; ++} ++ ++void qemu_register_reset_after(QEMUResetEntry *entry, ++ QEMUResetHandler *func, ++ void *opaque) ++{ ++ QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry)); ++ ++ re->func = func; ++ re->opaque = opaque; ++ QTAILQ_INSERT_AFTER(&reset_handlers, entry, re, entry); ++} ++ + void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) + { + QEMUResetEntry *re; +diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h +index c48cc4c2bc..9452ccd1fa 100644 +--- a/include/hw/arm/boot.h ++++ b/include/hw/arm/boot.h +@@ -118,6 +118,9 @@ struct arm_boot_info { + arm_endianness endianness; + }; + ++void cpu_hotplug_register_reset(int ncpu); ++void cpu_hotplug_reset_manually(int ncpu); ++ + /** + * arm_load_kernel - Loads memory with everything needed to boot + * +diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h +index 0b0d6d7598..f3ff26c637 100644 +--- a/include/sysemu/reset.h ++++ b/include/sysemu/reset.h +@@ -2,7 +2,11 @@ + #define QEMU_SYSEMU_RESET_H + + typedef void QEMUResetHandler(void *opaque); ++typedef struct QEMUResetEntry QEMUResetEntry; + ++QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, void *opaque); ++void qemu_register_reset_after(QEMUResetEntry *entry, ++ QEMUResetHandler *func, void *opaque); + void qemu_register_reset(QEMUResetHandler *func, void *opaque); + void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); + void qemu_devices_reset(void); +-- +2.19.1 diff --git a/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch b/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7ca51a5deb7146de6d6b05aa1d8391b0c08adac --- /dev/null +++ b/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch @@ -0,0 +1,47 @@ +From 220816989c1e3d490d293b8d7ac85dbc41a4c321 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 20 Sep 2019 18:40:39 +0100 +Subject: [PATCH] hw/arm/boot.c: Set NSACR.{CP11,CP10} for NS kernel boots + +If we're booting a Linux kernel directly into Non-Secure +state on a CPU which has Secure state, then make sure we +set the NSACR CP11 and CP10 bits, so that Non-Secure is allowed +to access the FPU. Otherwise an AArch32 kernel will UNDEF as +soon as it tries to use the FPU. + +It used to not matter that we didn't do this until commit +fc1120a7f5f2d4b6, where we implemented actually honouring +these NSACR bits. + +The problem only exists for CPUs where EL3 is AArch32; the +equivalent AArch64 trap bits are in CPTR_EL3 and are "0 to +not trap, 1 to trap", so the reset value of the register +permits NS access, unlike NSACR. + +Fixes: fc1120a7f5 +Fixes: https://bugs.launchpad.net/qemu/+bug/1844597 +Cc: qemu-stable@nongnu.org +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20190920174039.3916-1-peter.maydell@linaro.org +(cherry picked from commit ece628fcf69cbbd4b3efb6fbd203af07609467a2) +Signed-off-by: Michael Roth +--- + hw/arm/boot.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index c2b89b3bb9..fc4e021a38 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -754,6 +754,8 @@ static void do_cpu_reset(void *opaque) + (cs != first_cpu || !info->secure_board_setup)) { + /* Linux expects non-secure state */ + env->cp15.scr_el3 |= SCR_NS; ++ /* Set NSACR.{CP11,CP10} so NS can access the FPU */ ++ env->cp15.nsacr |= 3 << 10; + } + } + +-- +2.23.0 diff --git a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch b/hw-arm-expose-host-CPU-frequency-info-to-guest.patch index 0b04076e5478d671dc55937313d677e603d23720..17c4eb399c5af0a2c6c3c918c49a7550f7ce6fc1 100644 --- a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch +++ b/hw-arm-expose-host-CPU-frequency-info-to-guest.patch @@ -1,57 +1,60 @@ -From 773b25c55c7428b64d21b23a6b08fc629a665ca5 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 29 Jul 2019 09:54:43 +0800 -Subject: [PATCH] hw/arm: expose host CPU frequency info to guest +From b70d020dba72283d7b16a77c377512c84aab5f81 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Mon, 20 Apr 2020 10:38:12 +0800 +Subject: [PATCH] arm64: Add the cpufreq device to show cpufreq info to guest -On ARM64, CPU frequency is fetched by ACPI CPPC, so we add virtual -CPPC registers and ACPI _CPC objects. +On ARM64 platform, cpu frequency is retrieved via ACPI CPPC. +A virtual cpufreq device based on ACPI CPPC is created to +present cpu frequency info to the guest. -The default frequency is set to the nominal frequency of Hi1616, which -will not support CPPC in future. On Hi1620 we are fetching the value -from Host CPPC sys file. +The default frequency is set to host cpu nominal frequency, +which is obtained from the host CPPC sysfs. Other performance +data are set to the same value, since we don't support guest +performance scaling here. -All performance data are set to the same value for we don't support -guest initiating performance scaling. - -We don't emulate performance counters and simply return 1 for all -counter readings, and guest Linux should fall back to use the desired +Performance counters are also not emulated and they simply +return 1 if read, and guest should fallback to use desired performance value as the current performance. -Signed-off-by: Heyi Guo -Signed-off-by: zhanghailiang +Guest kernel version above 4.18 is required to make it work. + +This series is backported from: +https://patchwork.kernel.org/cover/11379943/ + +Signed-off-by: Ying Fang --- default-configs/aarch64-softmmu.mak | 1 + hw/acpi/Makefile.objs | 1 + hw/acpi/aml-build.c | 22 +++ - hw/acpi/cpufreq.c | 278 ++++++++++++++++++++++++++++ + hw/acpi/cpufreq.c | 287 ++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 78 +++++++- hw/arm/virt.c | 13 ++ hw/char/Kconfig | 4 + include/hw/acpi/acpi-defs.h | 38 ++++ include/hw/acpi/aml-build.h | 3 + include/hw/arm/virt.h | 1 + - 10 files changed, 437 insertions(+), 2 deletions(-) + 10 files changed, 446 insertions(+), 2 deletions(-) create mode 100644 hw/acpi/cpufreq.c diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak -index 4ea9add0..37399c14 100644 +index 958b1e08..0a030e85 100644 --- a/default-configs/aarch64-softmmu.mak +++ b/default-configs/aarch64-softmmu.mak -@@ -10,3 +10,4 @@ CONFIG_XLNX_ZYNQMP=y +@@ -6,3 +6,4 @@ include arm-softmmu.mak CONFIG_XLNX_ZYNQMP_ARM=y CONFIG_XLNX_VERSAL=y - CONFIG_ARM_SMMUV3=y + CONFIG_SBSA_REF=y +CONFIG_CPUFREQ=y diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs -index 2d46e378..60979db9 100644 +index 9bb2101e..1a720c38 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs -@@ -12,6 +12,7 @@ common-obj-y += acpi_interface.o - common-obj-y += bios-linker-loader.o - common-obj-y += aml-build.o +@@ -13,6 +13,7 @@ common-obj-y += bios-linker-loader.o + common-obj-y += aml-build.o utils.o + common-obj-$(CONFIG_ACPI_PCI) += pci.o common-obj-$(CONFIG_TPM) += tpm.o +common-obj-$(CONFIG_CPUFREQ) += cpufreq.o - + common-obj-$(CONFIG_IPMI) += ipmi.o common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c @@ -61,7 +64,7 @@ index 555c24f2..73f97751 100644 @@ -1369,6 +1369,28 @@ Aml *aml_sleep(uint64_t msec) return var; } - + +/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */ +Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, + uint8_t reg_offset, AmlAccessType type, uint64_t addr) @@ -89,10 +92,10 @@ index 555c24f2..73f97751 100644 int hi, lo; diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c new file mode 100644 -index 00000000..c123a22b +index 00000000..d02a25a6 --- /dev/null +++ b/hw/acpi/cpufreq.c -@@ -0,0 +1,278 @@ +@@ -0,0 +1,287 @@ +/* + * ACPI CPPC register device + * @@ -124,6 +127,7 @@ index 00000000..c123a22b +#include "hw/acpi/acpi-defs.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" ++#include "hw/boards.h" + +#define TYPE_CPUFREQ "cpufreq" +#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ) @@ -189,6 +193,9 @@ index 00000000..c123a22b + uint64_t r; + uint64_t n; + ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ + if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { + warn_report("cpufreq_read: offset 0x%lx out of range", offset); + return 0; @@ -258,6 +265,8 @@ index 00000000..c123a22b + uint64_t value, unsigned size) +{ + uint64_t n; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; + + if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { + error_printf("cpufreq_write: offset 0x%lx out of range", offset); @@ -339,6 +348,9 @@ index 00000000..c123a22b + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + CpuhzState *s = CPUFREQ(obj); + ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ + s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; + if (s->reg_size > MAX_SUPPORT_SPACE) { + error_report("Required space 0x%x excesses the max support 0x%x", @@ -372,7 +384,7 @@ index 00000000..c123a22b +type_init(cpufreq_register_types) + diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index bf9c0bc2..33a8e2e3 100644 +index 0afb3727..29494ebd 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -45,11 +45,73 @@ @@ -380,10 +392,10 @@ index bf9c0bc2..33a8e2e3 100644 #include "sysemu/numa.h" #include "kvm_arm.h" +#include "hw/acpi/acpi-defs.h" - + #define ARM_SPI_BASE 32 #define ACPI_POWER_BUTTON_DEVICE "PWRB" - + -static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) +static void acpi_dsdt_add_psd(Aml *dev, int cpus) +{ @@ -449,7 +461,7 @@ index bf9c0bc2..33a8e2e3 100644 + const MemMapEntry *cppc_memmap) { uint16_t i; - + @@ -57,6 +119,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) Aml *dev = aml_device("C%.03X", i); aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); @@ -469,7 +481,7 @@ index bf9c0bc2..33a8e2e3 100644 aml_append(scope, dev); } } -@@ -740,7 +814,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +@@ -718,7 +792,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) * the RTC ACPI device at all when using UEFI. */ scope = aml_scope("\\_SB"); @@ -479,10 +491,10 @@ index bf9c0bc2..33a8e2e3 100644 (irqmap[VIRT_UART] + ARM_SPI_BASE)); acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index ce2664a3..ec6f00ab 100644 +index d9496c93..0fa355ba 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -132,6 +132,7 @@ static const MemMapEntry base_memmap[] = { +@@ -135,6 +135,7 @@ static const MemMapEntry base_memmap[] = { [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, [VIRT_SMMU] = { 0x09050000, 0x00020000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, @@ -490,10 +502,10 @@ index ce2664a3..ec6f00ab 100644 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, -@@ -725,6 +726,16 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, +@@ -731,6 +732,16 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, g_free(nodename); } - + +static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem) +{ + hwaddr base = vms->memmap[VIRT_CPUFREQ].base; @@ -507,21 +519,21 @@ index ce2664a3..ec6f00ab 100644 static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) { char *nodename; -@@ -1618,6 +1629,8 @@ static void machvirt_init(MachineState *machine) - +@@ -1682,6 +1693,8 @@ static void machvirt_init(MachineState *machine) + create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); - + + create_cpufreq(vms, sysmem); + if (vms->secure) { create_secure_ram(vms, secure_sysmem); create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); diff --git a/hw/char/Kconfig b/hw/char/Kconfig -index 6360c9ff..8cc3ae2a 100644 +index 40e7a8b8..2f61bf53 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig -@@ -40,3 +40,7 @@ config SCLPCONSOLE - +@@ -46,3 +46,7 @@ config SCLPCONSOLE + config TERMINAL3270 bool + @@ -529,13 +541,13 @@ index 6360c9ff..8cc3ae2a 100644 + bool + default y diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h -index f9aa4bd3..b4899a32 100644 +index 57a3f58b..39ae91d3 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h -@@ -652,4 +652,42 @@ struct AcpiIortRC { +@@ -634,4 +634,42 @@ struct AcpiIortRC { } QEMU_PACKED; typedef struct AcpiIortRC AcpiIortRC; - + +/* + * CPPC register definition from kernel header + * include/acpi/cppc_acpi.h @@ -586,11 +598,11 @@ index 1a563ad7..375335ab 100644 +Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, + uint8_t reg_offset, AmlAccessType type, + uint64_t addr); - + /* Block AML object primitives */ Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 507517c6..8465f9bd 100644 +index a7209420..43a6ce91 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -66,6 +66,7 @@ enum { @@ -601,6 +613,5 @@ index 507517c6..8465f9bd 100644 VIRT_MMIO, VIRT_RTC, VIRT_FW_CFG, --- +-- 2.19.1 - diff --git a/hw-arm-virt-Add-memory-hotplug-framework.patch b/hw-arm-virt-Add-memory-hotplug-framework.patch new file mode 100644 index 0000000000000000000000000000000000000000..dcb0f21f5b63e10636d889f6cae99a4d738d1d0e --- /dev/null +++ b/hw-arm-virt-Add-memory-hotplug-framework.patch @@ -0,0 +1,130 @@ +From e14fadc66d488ad10a10a2076721b72cc239ded9 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Wed, 18 Sep 2019 14:06:26 +0100 +Subject: [PATCH] hw/arm/virt: Add memory hotplug framework + +This patch adds the memory hot-plug/hot-unplug infrastructure +in machvirt. The device memory is not yet exposed to the Guest +either through DT or ACPI and hence both cold/hot plug of memory +is explicitly disabled for now. + +Signed-off-by: Eric Auger +Signed-off-by: Kwangwoo Lee +Signed-off-by: Shameer Kolothum +Reviewed-by: Peter Maydell +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-5-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/Kconfig | 2 ++ + hw/arm/virt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index ab65ecd216..84961c17ab 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -20,6 +20,8 @@ config ARM_VIRT + select SMBIOS + select VIRTIO_MMIO + select ACPI_PCI ++ select MEM_DEVICE ++ select DIMM + + config CHEETAH + bool +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 23d72aed97..c7c07fe3ac 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -65,6 +65,8 @@ + #include "hw/arm/smmuv3.h" + #include "hw/acpi/acpi.h" + #include "target/arm/internals.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/mem/nvdimm.h" + + #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ +@@ -1998,6 +2000,42 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + return ms->possible_cpus; + } + ++static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ ++ /* ++ * The device memory is not yet exposed to the Guest either through ++ * DT or ACPI and hence both cold/hot plug of memory is explicitly ++ * disabled for now. ++ */ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ error_setg(errp, "memory cold/hot plug is not yet supported"); ++ return; ++ } ++ ++ pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); ++} ++ ++static void virt_memory_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ Error *local_err = NULL; ++ ++ pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); ++ ++ error_propagate(errp, local_err); ++} ++ ++static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ virt_memory_pre_plug(hotplug_dev, dev, errp); ++ } ++} ++ + static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +@@ -2009,12 +2047,23 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + SYS_BUS_DEVICE(dev)); + } + } ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ virt_memory_plug(hotplug_dev, dev, errp); ++ } ++} ++ ++static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ error_setg(errp, "device unplug request for unsupported device" ++ " type: %s", object_get_typename(OBJECT(dev))); + } + + static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) + { +- if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) { ++ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || ++ (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { + return HOTPLUG_HANDLER(machine); + } + +@@ -2078,7 +2127,9 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + mc->kvm_type = virt_kvm_type; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; ++ hc->pre_plug = virt_machine_device_pre_plug_cb; + hc->plug = virt_machine_device_plug_cb; ++ hc->unplug_request = virt_machine_device_unplug_request_cb; + mc->numa_mem_supported = true; + } + +-- +2.19.1 diff --git a/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch b/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch new file mode 100644 index 0000000000000000000000000000000000000000..b32b2a01929189ff6f89e94f011d4d9cc3811a3b --- /dev/null +++ b/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch @@ -0,0 +1,252 @@ +From ce813d8daa2e01df52509f4bb52b9ab774408706 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:27 +0100 +Subject: [PATCH] hw/arm/virt: Enable device memory cold/hot plug with ACPI + boot + +This initializes the GED device with base memory and irq, configures +ged memory hotplug event and builds the corresponding aml code. With +this, both hot and cold plug of device memory is enabled now for Guest +with ACPI boot. Memory cold plug support with Guest DT boot is not yet +supported. + +As DSDT table gets changed by this, update bios-tables-test-allowed-diff.h +to avoid "make check" failure. + +Signed-off-by: Shameer Kolothum +Message-Id: <20190918130633.4872-6-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + hw/arm/Kconfig | 2 ++ + hw/arm/virt-acpi-build.c | 21 ++++++++++++++ + hw/arm/virt.c | 59 +++++++++++++++++++++++++++++++++++----- + include/hw/arm/virt.h | 4 +++ + 4 files changed, 79 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 84961c17ab..ad7f7c089b 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -22,6 +22,8 @@ config ARM_VIRT + select ACPI_PCI + select MEM_DEVICE + select DIMM ++ select ACPI_MEMORY_HOTPLUG ++ select ACPI_HW_REDUCED + + config CHEETAH + bool +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index fe54411f6a..fca53ae01f 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -40,6 +40,8 @@ + #include "hw/acpi/aml-build.h" + #include "hw/acpi/utils.h" + #include "hw/acpi/pci.h" ++#include "hw/acpi/memory_hotplug.h" ++#include "hw/acpi/generic_event_device.h" + #include "hw/pci/pcie_host.h" + #include "hw/pci/pci.h" + #include "hw/arm/virt.h" +@@ -779,6 +781,7 @@ static void + build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + { + Aml *scope, *dsdt; ++ MachineState *ms = MACHINE(vms); + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; + +@@ -803,6 +806,24 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + vms->highmem, vms->highmem_ecam); + acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], + (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); ++ if (vms->acpi_dev) { ++ build_ged_aml(scope, "\\_SB."GED_DEVICE, ++ HOTPLUG_HANDLER(vms->acpi_dev), ++ irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, ++ memmap[VIRT_ACPI_GED].base); ++ } ++ ++ if (vms->acpi_dev) { ++ uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), ++ "ged-event", &error_abort); ++ ++ if (event & ACPI_GED_MEM_HOTPLUG_EVT) { ++ build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL, ++ AML_SYSTEM_MEMORY, ++ memmap[VIRT_PCDIMM_ACPI].base); ++ } ++ } ++ + acpi_dsdt_add_power_button(scope); + + aml_append(dsdt, scope); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index c7c07fe3ac..8ccabd5159 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -67,6 +67,7 @@ + #include "target/arm/internals.h" + #include "hw/mem/pc-dimm.h" + #include "hw/mem/nvdimm.h" ++#include "hw/acpi/generic_event_device.h" + + #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ +@@ -137,6 +138,8 @@ static const MemMapEntry base_memmap[] = { + [VIRT_GPIO] = { 0x09030000, 0x00001000 }, + [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, + [VIRT_SMMU] = { 0x09050000, 0x00020000 }, ++ [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, ++ [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, + [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ +@@ -173,6 +176,7 @@ static const int a15irqmap[] = { + [VIRT_PCIE] = 3, /* ... to 6 */ + [VIRT_GPIO] = 7, + [VIRT_SECURE_UART] = 8, ++ [VIRT_ACPI_GED] = 9, + [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ + [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ + [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ +@@ -630,6 +634,29 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) + } + } + ++static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) ++{ ++ DeviceState *dev; ++ MachineState *ms = MACHINE(vms); ++ int irq = vms->irqmap[VIRT_ACPI_GED]; ++ uint32_t event = 0; ++ ++ if (ms->ram_slots) { ++ event = ACPI_GED_MEM_HOTPLUG_EVT; ++ } ++ ++ dev = qdev_create(NULL, TYPE_ACPI_GED); ++ qdev_prop_set_uint32(dev, "ged-event", event); ++ ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); ++ ++ qdev_init_nofail(dev); ++ ++ return dev; ++} ++ + static void create_its(VirtMachineState *vms, DeviceState *gicdev) + { + const char *itsclass = its_class_name(); +@@ -1603,6 +1630,7 @@ static void machvirt_init(MachineState *machine) + MemoryRegion *ram = g_new(MemoryRegion, 1); + bool firmware_loaded; + bool aarch64 = true; ++ bool has_ged = !vmc->no_ged; + unsigned int smp_cpus = machine->smp.cpus; + unsigned int max_cpus = machine->smp.max_cpus; + +@@ -1824,6 +1852,10 @@ static void machvirt_init(MachineState *machine) + + create_gpio(vms, pic); + ++ if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { ++ vms->acpi_dev = create_acpi_ged(vms, pic); ++ } ++ + /* Create mmio transports, so the user can create virtio backends + * (which will be automatically plugged in to the transports). If + * no backend is created the transport will just sit harmlessly idle. +@@ -2003,14 +2035,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); + +- /* +- * The device memory is not yet exposed to the Guest either through +- * DT or ACPI and hence both cold/hot plug of memory is explicitly +- * disabled for now. +- */ +- if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +- error_setg(errp, "memory cold/hot plug is not yet supported"); ++ if (is_nvdimm) { ++ error_setg(errp, "nvdimm is not yet supported"); ++ return; ++ } ++ ++ if (!vms->acpi_dev) { ++ error_setg(errp, ++ "memory hotplug is not enabled: missing acpi-ged device"); + return; + } + +@@ -2020,11 +2055,18 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + static void virt_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { ++ HotplugHandlerClass *hhc; + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + Error *local_err = NULL; + + pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); ++ if (local_err) { ++ goto out; ++ } + ++ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); ++ hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); ++out: + error_propagate(errp, local_err); + } + +@@ -2231,8 +2273,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 1) + + static void virt_machine_4_0_options(MachineClass *mc) + { ++ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); ++ + virt_machine_4_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); ++ vmc->no_ged = true; + } + DEFINE_VIRT_MACHINE(4, 0) + +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index a9d6977afc..0350285136 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -78,6 +78,8 @@ enum { + VIRT_GPIO, + VIRT_SECURE_UART, + VIRT_SECURE_MEM, ++ VIRT_PCDIMM_ACPI, ++ VIRT_ACPI_GED, + VIRT_LOWMEMMAP_LAST, + }; + +@@ -107,6 +109,7 @@ typedef struct { + bool claim_edge_triggered_timers; + bool smbios_old_sys_ver; + bool no_highmem_ecam; ++ bool no_ged; /* Machines < 4.1 has no support for ACPI GED device */ + bool kvm_no_adjvtime; + } VirtMachineClass; + +@@ -135,6 +138,7 @@ typedef struct { + uint32_t iommu_phandle; + int psci_conduit; + hwaddr highest_gpa; ++ DeviceState *acpi_dev; + } VirtMachineState; + + #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +-- +2.19.1 diff --git a/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch new file mode 100644 index 0000000000000000000000000000000000000000..1e3befaf62920ca12cae4c8ead6d731800ef79a8 --- /dev/null +++ b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch @@ -0,0 +1,170 @@ +From 3a0af1446395e74476a763ca12713b28c099a144 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 12:50:54 +0800 +Subject: [PATCH] hw/arm/virt: Factor out some CPU init codes to pre_plug hook + +The init path of hotplugged CPU is pre_plug/realize/plug, so we +must move these init code in machvirt_init to pre_plug hook, to +let them be shared by all CPUs. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 108 +++++++++++++++++++++++++++----------------------- + 1 file changed, 58 insertions(+), 50 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 64532b61b2..83f4887e57 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -196,6 +196,8 @@ static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("max"), + }; + ++static MemoryRegion *secure_sysmem; ++ + static bool cpu_type_valid(const char *cpu) + { + int i; +@@ -1629,7 +1631,6 @@ static void machvirt_init(MachineState *machine) + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; + MemoryRegion *sysmem = get_system_memory(); +- MemoryRegion *secure_sysmem = NULL; + int n, virt_max_cpus; + MemoryRegion *ram = g_new(MemoryRegion, 1); + bool firmware_loaded; +@@ -1752,57 +1753,10 @@ static void machvirt_init(MachineState *machine) + } + + cpuobj = object_new(possible_cpus->cpus[n].type); +- object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, +- "mp-affinity", NULL); ++ aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); + + cs = CPU(cpuobj); + cs->cpu_index = n; +- +- numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), +- &error_fatal); +- +- aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); +- +- if (!vms->secure) { +- object_property_set_bool(cpuobj, false, "has_el3", NULL); +- } +- +- if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) { +- object_property_set_bool(cpuobj, false, "has_el2", NULL); +- } +- +- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { +- object_property_set_int(cpuobj, vms->psci_conduit, +- "psci-conduit", NULL); +- +- /* Secondary CPUs start in PSCI powered-down state */ +- if (n > 0) { +- object_property_set_bool(cpuobj, true, +- "start-powered-off", NULL); +- } +- } +- +- if (vmc->kvm_no_adjvtime && +- object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { +- object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); +- } +- +- if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { +- object_property_set_bool(cpuobj, false, "pmu", NULL); +- } +- +- if (object_property_find(cpuobj, "reset-cbar", NULL)) { +- object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, +- "reset-cbar", &error_abort); +- } +- +- object_property_set_link(cpuobj, OBJECT(sysmem), "memory", +- &error_abort); +- if (vms->secure) { +- object_property_set_link(cpuobj, OBJECT(secure_sysmem), +- "secure-memory", &error_abort); +- } +- + object_property_set_bool(cpuobj, true, "realized", &error_fatal); + object_unref(cpuobj); + } +@@ -2089,10 +2043,16 @@ out: + static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- CPUState *cs = CPU(dev); + ARMCPUTopoInfo topo; ++ Object *cpuobj = OBJECT(dev); ++ CPUState *cs = CPU(dev); + ARMCPU *cpu = ARM_CPU(dev); + MachineState *ms = MACHINE(hotplug_dev); ++ MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ MemoryRegion *sysmem = get_system_memory(); + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; + +@@ -2145,6 +2105,54 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + return; + } + cpu->thread_id = topo.smt_id; ++ ++ /* Init some properties */ ++ ++ object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id, ++ "mp-affinity", NULL); ++ ++ numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), ++ &error_fatal); ++ ++ if (!vms->secure) { ++ object_property_set_bool(cpuobj, false, "has_el3", NULL); ++ } ++ ++ if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) { ++ object_property_set_bool(cpuobj, false, "has_el2", NULL); ++ } ++ ++ if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { ++ object_property_set_int(cpuobj, vms->psci_conduit, ++ "psci-conduit", NULL); ++ ++ /* Secondary CPUs start in PSCI powered-down state */ ++ if (cs->cpu_index > 0) { ++ object_property_set_bool(cpuobj, true, ++ "start-powered-off", NULL); ++ } ++ } ++ ++ if (vmc->kvm_no_adjvtime && ++ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { ++ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); ++ } ++ ++ if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { ++ object_property_set_bool(cpuobj, false, "pmu", NULL); ++ } ++ ++ if (object_property_find(cpuobj, "reset-cbar", NULL)) { ++ object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, ++ "reset-cbar", &error_abort); ++ } ++ ++ object_property_set_link(cpuobj, OBJECT(sysmem), "memory", ++ &error_abort); ++ if (vms->secure) { ++ object_property_set_link(cpuobj, OBJECT(secure_sysmem), ++ "secure-memory", &error_abort); ++ } + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, +-- +2.19.1 diff --git a/hw-arm-virt-Introduce-cpu-topology-support.patch b/hw-arm-virt-Introduce-cpu-topology-support.patch index 027a5112effa77c9d37642f88cf9d00120bc6f47..932f467fe274453668edf80bac5d023817d6f95b 100644 --- a/hw-arm-virt-Introduce-cpu-topology-support.patch +++ b/hw-arm-virt-Introduce-cpu-topology-support.patch @@ -1,6 +1,6 @@ -From 123b4eb3cb7b9b4e3e0705a9b5f974b37d3b8431 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 5 Aug 2019 15:04:31 +0800 +From 73fc4af05ebe12d77915e6b3c85c48f5e0c432f3 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 22 Apr 2020 19:23:27 +0800 Subject: [PATCH] hw/arm/virt: Introduce cpu topology support Add topology support for guest vcpu by cpu-map in dtb when the guest is booted @@ -11,13 +11,13 @@ Signed-off-by: zhanghailiang (picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by Andrew Jones ) --- - device_tree.c | 32 +++++++++++++++++++++++ - hw/acpi/aml-build.c | 50 ++++++++++++++++++++++++++++++++++++ + device_tree.c | 32 ++++++++++++++++++++++ + hw/acpi/aml-build.c | 53 ++++++++++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 4 +++ - hw/arm/virt.c | 29 +++++++++++++++++++++ + hw/arm/virt.c | 32 +++++++++++++++++++++- include/hw/acpi/aml-build.h | 2 ++ include/sysemu/device_tree.h | 1 + - 6 files changed, 118 insertions(+) + 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/device_tree.c b/device_tree.c index f8b46b3c..03906a14 100644 @@ -26,7 +26,7 @@ index f8b46b3c..03906a14 100644 @@ -524,6 +524,38 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) return retval; } - + +/** + * qemu_fdt_add_path + * @fdt: Flattened Device Tree @@ -63,7 +63,7 @@ index f8b46b3c..03906a14 100644 { const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 73f97751..9d39ad10 100644 +index 73f97751..f2c8c28f 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -25,6 +25,7 @@ @@ -71,13 +71,13 @@ index 73f97751..9d39ad10 100644 #include "qemu/bitops.h" #include "sysemu/numa.h" +#include "sysemu/cpus.h" - + static GArray *build_alloc_array(void) { -@@ -51,6 +52,55 @@ static void build_append_array(GArray *array, GArray *val) +@@ -51,6 +52,58 @@ static void build_append_array(GArray *array, GArray *val) g_array_append_vals(array, val->data, val->len); } - + +/* + * ACPI 6.2 Processor Properties Topology Table (PPTT) + */ @@ -97,6 +97,9 @@ index 73f97751..9d39ad10 100644 +{ + int pptt_start = table_data->len; + int uid = 0, cpus = 0, socket; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cores = ms->smp.cores; ++ unsigned int smp_threads = ms->smp.threads; + + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + @@ -128,28 +131,28 @@ index 73f97751..9d39ad10 100644 +} + #define ACPI_NAMESEG_LEN 4 - + static void diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 33a8e2e3..18653e6d 100644 +index 29494ebd..fe54411f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -870,6 +870,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) +@@ -848,6 +848,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); - + + acpi_add_table(table_offsets, tables_blob); + + build_pptt(tables_blob, tables->linker, vms->smp_cpus); + acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, vms); - + diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 57a78b16..16700a2e 100644 +index 0fa355ba..272455bc 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -42,6 +42,7 @@ +@@ -44,6 +44,7 @@ #include "net/net.h" #include "sysemu/device_tree.h" #include "sysemu/numa.h" @@ -157,10 +160,20 @@ index 57a78b16..16700a2e 100644 #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "hw/loader.h" -@@ -364,8 +365,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) +@@ -312,7 +313,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + int cpu; + int addr_cells = 1; + const MachineState *ms = MACHINE(vms); +- ++ unsigned int smp_cores = ms->smp.cores; ++ unsigned int smp_threads = ms->smp.threads; + /* + * From Documentation/devicetree/bindings/arm/cpus.txt + * On ARM v8 64-bit systems value should be set to 2, +@@ -368,8 +370,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) ms->possible_cpus->cpus[cs->cpu_index].props.node_id); } - + + qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(vms->fdt)); + @@ -192,7 +205,7 @@ index 57a78b16..16700a2e 100644 + g_free(cpu_path); + } } - + static void fdt_add_its_gic_node(VirtMachineState *vms) diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 375335ab..bfb0b100 100644 @@ -201,11 +214,11 @@ index 375335ab..bfb0b100 100644 @@ -417,6 +417,8 @@ build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s) void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, uint64_t len, int node, MemoryAffinityFlags flags); - + +void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus); + void build_slit(GArray *table_data, BIOSLinker *linker); - + void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h index c16fd69b..d62fc873 100644 @@ -216,9 +229,8 @@ index c16fd69b..d62fc873 100644 int qemu_fdt_nop_node(void *fdt, const char *node_path); int qemu_fdt_add_subnode(void *fdt, const char *name); +int qemu_fdt_add_path(void *fdt, const char *path); - + #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ do { \ --- -2.19.1 - +-- +2.23.0 diff --git a/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch b/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch new file mode 100644 index 0000000000000000000000000000000000000000..262cb508bcb8ba48bf93a3875957f2c9ace7698d --- /dev/null +++ b/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch @@ -0,0 +1,402 @@ +From 5d1be90750551f1debf5767d7a6e2b9c50054c05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 9 Dec 2019 10:03:06 +0100 +Subject: [PATCH] hw/arm/virt: Simplify by moving the gic in the machine state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make the gic a field in the machine state, and instead of filling +an array of qemu_irq and passing it around, directly call +qdev_get_gpio_in() on the gic field. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Luc Michel +Message-id: 20191209090306.20433-1-philmd@redhat.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 109 +++++++++++++++++++++--------------------- + include/hw/arm/virt.h | 1 + + 2 files changed, 55 insertions(+), 55 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 18321e522b..8638aeedb7 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -634,7 +634,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) + } + } + +-static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) ++static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + { + DeviceState *dev; + MachineState *ms = MACHINE(vms); +@@ -650,14 +650,14 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); +- sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); + + qdev_init_nofail(dev); + + return dev; + } + +-static void create_its(VirtMachineState *vms, DeviceState *gicdev) ++static void create_its(VirtMachineState *vms) + { + const char *itsclass = its_class_name(); + DeviceState *dev; +@@ -669,7 +669,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev) + + dev = qdev_create(NULL, itsclass); + +- object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3", ++ object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3", + &error_abort); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base); +@@ -677,7 +677,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev) + fdt_add_its_gic_node(vms); + } + +-static void create_v2m(VirtMachineState *vms, qemu_irq *pic) ++static void create_v2m(VirtMachineState *vms) + { + int i; + int irq = vms->irqmap[VIRT_GIC_V2M]; +@@ -690,17 +690,17 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic) + qdev_init_nofail(dev); + + for (i = 0; i < NUM_GICV2M_SPIS; i++) { +- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, ++ qdev_get_gpio_in(vms->gic, irq + i)); + } + + fdt_add_v2m_gic_node(vms); + } + +-static void create_gic(VirtMachineState *vms, qemu_irq *pic) ++static void create_gic(VirtMachineState *vms) + { + MachineState *ms = MACHINE(vms); + /* We create a standalone GIC */ +- DeviceState *gicdev; + SysBusDevice *gicbusdev; + const char *gictype; + int type = vms->gic_version, i; +@@ -709,15 +709,15 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) + + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); + +- gicdev = qdev_create(NULL, gictype); +- qdev_prop_set_uint32(gicdev, "revision", type); +- qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); ++ vms->gic = qdev_create(NULL, gictype); ++ qdev_prop_set_uint32(vms->gic, "revision", type); ++ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); + /* Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ +- qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32); ++ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32); + if (!kvm_irqchip_in_kernel()) { +- qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure); ++ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure); + } + + if (type == 3) { +@@ -727,25 +727,25 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) + + nb_redist_regions = virt_gicv3_redist_region_count(vms); + +- qdev_prop_set_uint32(gicdev, "len-redist-region-count", ++ qdev_prop_set_uint32(vms->gic, "len-redist-region-count", + nb_redist_regions); +- qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count); ++ qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count); + + if (nb_redist_regions == 2) { + uint32_t redist1_capacity = + vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; + +- qdev_prop_set_uint32(gicdev, "redist-region-count[1]", ++ qdev_prop_set_uint32(vms->gic, "redist-region-count[1]", + MIN(smp_cpus - redist0_count, redist1_capacity)); + } + } else { + if (!kvm_irqchip_in_kernel()) { +- qdev_prop_set_bit(gicdev, "has-virtualization-extensions", ++ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions", + vms->virt); + } + } +- qdev_init_nofail(gicdev); +- gicbusdev = SYS_BUS_DEVICE(gicdev); ++ qdev_init_nofail(vms->gic); ++ gicbusdev = SYS_BUS_DEVICE(vms->gic); + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base); + if (type == 3) { + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base); +@@ -781,23 +781,23 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) + + for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + qdev_connect_gpio_out(cpudev, irq, +- qdev_get_gpio_in(gicdev, ++ qdev_get_gpio_in(vms->gic, + ppibase + timer_irq[irq])); + } + + if (type == 3) { +- qemu_irq irq = qdev_get_gpio_in(gicdev, ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, + ppibase + ARCH_GIC_MAINT_IRQ); + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", + 0, irq); + } else if (vms->virt) { +- qemu_irq irq = qdev_get_gpio_in(gicdev, ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, + ppibase + ARCH_GIC_MAINT_IRQ); + sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); + } + + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, +- qdev_get_gpio_in(gicdev, ppibase ++ qdev_get_gpio_in(vms->gic, ppibase + + VIRTUAL_PMU_IRQ)); + + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); +@@ -809,20 +809,16 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) + qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); + } + +- for (i = 0; i < NUM_IRQS; i++) { +- pic[i] = qdev_get_gpio_in(gicdev, i); +- } +- + fdt_add_gic_node(vms); + + if (type == 3 && vms->its) { +- create_its(vms, gicdev); ++ create_its(vms); + } else if (type == 2) { +- create_v2m(vms, pic); ++ create_v2m(vms); + } + } + +-static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, ++static void create_uart(const VirtMachineState *vms, int uart, + MemoryRegion *mem, Chardev *chr) + { + char *nodename; +@@ -838,7 +834,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, + qdev_init_nofail(dev); + memory_region_add_subregion(mem, base, + sysbus_mmio_get_region(s, 0)); +- sysbus_connect_irq(s, 0, pic[irq]); ++ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); + + nodename = g_strdup_printf("/pl011@%" PRIx64, base); + qemu_fdt_add_subnode(vms->fdt, nodename); +@@ -880,7 +876,7 @@ static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem) + memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); + } + +-static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) ++static void create_rtc(const VirtMachineState *vms) + { + char *nodename; + hwaddr base = vms->memmap[VIRT_RTC].base; +@@ -888,7 +884,7 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) + int irq = vms->irqmap[VIRT_RTC]; + const char compat[] = "arm,pl031\0arm,primecell"; + +- sysbus_create_simple("pl031", base, pic[irq]); ++ sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq)); + + nodename = g_strdup_printf("/pl031@%" PRIx64, base); + qemu_fdt_add_subnode(vms->fdt, nodename); +@@ -916,7 +912,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque) + } + } + +-static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) ++static void create_gpio(const VirtMachineState *vms) + { + char *nodename; + DeviceState *pl061_dev; +@@ -925,7 +921,8 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + int irq = vms->irqmap[VIRT_GPIO]; + const char compat[] = "arm,pl061\0arm,primecell"; + +- pl061_dev = sysbus_create_simple("pl061", base, pic[irq]); ++ pl061_dev = sysbus_create_simple("pl061", base, ++ qdev_get_gpio_in(vms->gic, irq)); + + uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt); + nodename = g_strdup_printf("/pl061@%" PRIx64, base); +@@ -959,7 +956,7 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + g_free(nodename); + } + +-static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic) ++static void create_virtio_devices(const VirtMachineState *vms) + { + int i; + hwaddr size = vms->memmap[VIRT_MMIO].size; +@@ -995,7 +992,8 @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic) + int irq = vms->irqmap[VIRT_MMIO] + i; + hwaddr base = vms->memmap[VIRT_MMIO].base + i * size; + +- sysbus_create_simple("virtio-mmio", base, pic[irq]); ++ sysbus_create_simple("virtio-mmio", base, ++ qdev_get_gpio_in(vms->gic, irq)); + } + + /* We add dtb nodes in reverse order so that they appear in the finished +@@ -1244,7 +1242,7 @@ static void create_pcie_irq_map(const VirtMachineState *vms, + 0x7 /* PCI irq */); + } + +-static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, ++static void create_smmu(const VirtMachineState *vms, + PCIBus *bus) + { + char *node; +@@ -1267,7 +1265,8 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + for (i = 0; i < NUM_SMMU_IRQS; i++) { +- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, ++ qdev_get_gpio_in(vms->gic, irq + i)); + } + + node = g_strdup_printf("/smmuv3@%" PRIx64, base); +@@ -1294,7 +1293,7 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, + g_free(node); + } + +-static void create_pcie(VirtMachineState *vms, qemu_irq *pic) ++static void create_pcie(VirtMachineState *vms) + { + hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base; + hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size; +@@ -1354,7 +1353,8 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { +- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, ++ qdev_get_gpio_in(vms->gic, irq + i)); + gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); + } + +@@ -1414,7 +1414,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) + if (vms->iommu) { + vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt); + +- create_smmu(vms, pic, pci->bus); ++ create_smmu(vms, pci->bus); + + qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", + 0x0, vms->iommu_phandle, 0x0, 0x10000); +@@ -1423,7 +1423,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) + g_free(nodename); + } + +-static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic) ++static void create_platform_bus(VirtMachineState *vms) + { + DeviceState *dev; + SysBusDevice *s; +@@ -1439,8 +1439,8 @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic) + + s = SYS_BUS_DEVICE(dev); + for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) { +- int irqn = vms->irqmap[VIRT_PLATFORM_BUS] + i; +- sysbus_connect_irq(s, i, pic[irqn]); ++ int irq = vms->irqmap[VIRT_PLATFORM_BUS] + i; ++ sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq)); + } + + memory_region_add_subregion(sysmem, +@@ -1621,7 +1621,6 @@ static void machvirt_init(MachineState *machine) + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; +- qemu_irq pic[NUM_IRQS]; + MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *secure_sysmem = NULL; + int n, virt_max_cpus; +@@ -1829,29 +1828,29 @@ static void machvirt_init(MachineState *machine) + + virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); + +- create_gic(vms, pic); ++ create_gic(vms); + + fdt_add_pmu_nodes(vms); + +- create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); ++ create_uart(vms, VIRT_UART, sysmem, serial_hd(0)); + + create_cpufreq(vms, sysmem); + + if (vms->secure) { + create_secure_ram(vms, secure_sysmem); +- create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); ++ create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); + } + + vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64); + +- create_rtc(vms, pic); ++ create_rtc(vms); + +- create_pcie(vms, pic); ++ create_pcie(vms); + + if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { +- vms->acpi_dev = create_acpi_ged(vms, pic); ++ vms->acpi_dev = create_acpi_ged(vms); + } else { +- create_gpio(vms, pic); ++ create_gpio(vms); + } + + /* connect powerdown request */ +@@ -1862,12 +1861,12 @@ static void machvirt_init(MachineState *machine) + * (which will be automatically plugged in to the transports). If + * no backend is created the transport will just sit harmlessly idle. + */ +- create_virtio_devices(vms, pic); ++ create_virtio_devices(vms); + + vms->fw_cfg = create_fw_cfg(vms, &address_space_memory); + rom_set_fw(vms->fw_cfg); + +- create_platform_bus(vms, pic); ++ create_platform_bus(vms); + + vms->bootinfo.ram_size = machine->ram_size; + vms->bootinfo.kernel_filename = machine->kernel_filename; +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index dcceb9c615..3dfefca93b 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -138,6 +138,7 @@ typedef struct { + uint32_t iommu_phandle; + int psci_conduit; + hwaddr highest_gpa; ++ DeviceState *gic; + DeviceState *acpi_dev; + Notifier powerdown_notifier; + } VirtMachineState; +-- +2.19.1 diff --git a/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch b/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch new file mode 100644 index 0000000000000000000000000000000000000000..0602ab8d4d0d7af63f034c9b66c984e5aed627a7 --- /dev/null +++ b/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch @@ -0,0 +1,75 @@ +From 8d287871fd4e1b4654fe9e5011b80614cb44f6d8 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:28 +0100 +Subject: [PATCH] hw/arm/virt-acpi-build: Add PC-DIMM in SRAT + +Generate Memory Affinity Structures for PC-DIMM ranges. + +Also, Linux and Windows need ACPI SRAT table to make memory hotplug +work properly, however currently QEMU doesn't create SRAT table if +numa options aren't present on CLI. Hence add support(>=4.2) to +create numa node automatically (auto_enable_numa_with_memhp) when +QEMU is started with memory hotplug enabled but without '-numa' +options on CLI. + +Signed-off-by: Shameer Kolothum +Signed-off-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-7-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/virt-acpi-build.c | 9 +++++++++ + hw/arm/virt.c | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index fca53ae01f..9622994e50 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -592,6 +592,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + int i, srat_start; + uint64_t mem_base; + MachineClass *mc = MACHINE_GET_CLASS(vms); ++ MachineState *ms = MACHINE(vms); + const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(MACHINE(vms)); + + srat_start = table_data->len; +@@ -617,6 +618,14 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + } + } + ++ if (ms->device_memory) { ++ numamem = acpi_data_push(table_data, sizeof *numamem); ++ build_srat_memory(numamem, ms->device_memory->base, ++ memory_region_size(&ms->device_memory->mr), ++ nb_numa_nodes - 1, ++ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); ++ } ++ + build_header(linker, table_data, (void *)(table_data->data + srat_start), + "SRAT", table_data->len - srat_start, 3, NULL, NULL); + } +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 8ccabd5159..ab33cce4b3 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2173,6 +2173,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + hc->plug = virt_machine_device_plug_cb; + hc->unplug_request = virt_machine_device_unplug_request_cb; + mc->numa_mem_supported = true; ++ mc->auto_enable_numa_with_memhp = true; + } + + static void virt_instance_init(Object *obj) +@@ -2278,6 +2279,7 @@ static void virt_machine_4_0_options(MachineClass *mc) + virt_machine_4_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); + vmc->no_ged = true; ++ mc->auto_enable_numa_with_memhp = false; + } + DEFINE_VIRT_MACHINE(4, 0) + +-- +2.19.1 diff --git a/hw-arm64-add-vcpu-cache-info-support.patch b/hw-arm64-add-vcpu-cache-info-support.patch index c9e843719b59a99112ee1867475846378c84264e..79e1dede39def063dc9d8a4f4b87339bcd39c435 100644 --- a/hw-arm64-add-vcpu-cache-info-support.patch +++ b/hw-arm64-add-vcpu-cache-info-support.patch @@ -1,6 +1,6 @@ -From 8db6d888e3eb131900111506b93f6101413df5b4 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Mon, 5 Aug 2019 15:30:05 +0800 +From 5a0ed254f99ca37498bd81994b906b6984b5ffa9 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 22 Apr 2020 19:25:00 +0800 Subject: [PATCH] hw/arm64: add vcpu cache info support Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. @@ -8,16 +8,16 @@ Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. Signed-off-by: zhanghailiang Signed-off-by: Honghao --- - hw/acpi/aml-build.c | 124 ++++++++++++++++++++++++++++++++++++ - hw/arm/virt.c | 76 +++++++++++++++++++++- + hw/acpi/aml-build.c | 126 ++++++++++++++++++++++++++++++++++++ + hw/arm/virt.c | 80 ++++++++++++++++++++++- include/hw/acpi/aml-build.h | 46 +++++++++++++ - 3 files changed, 245 insertions(+), 1 deletion(-) + 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 9d39ad10..99209c0a 100644 +index f2c8c28f..74e95005 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c -@@ -55,6 +55,129 @@ static void build_append_array(GArray *array, GArray *val) +@@ -55,6 +55,131 @@ static void build_append_array(GArray *array, GArray *val) /* * ACPI 6.2 Processor Properties Topology Table (PPTT) */ @@ -115,6 +115,8 @@ index 9d39ad10..99209c0a 100644 + int pptt_start = table_data->len; + int uid = 0, cpus = 0, socket; + struct offset_status offset; ++ const MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cores = ms->smp.cores; + + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + @@ -147,25 +149,27 @@ index 9d39ad10..99209c0a 100644 static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, uint32_t parent, uint32_t id) { -@@ -100,6 +223,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) +@@ -103,6 +228,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) (void *)(table_data->data + pptt_start), "PPTT", table_data->len - pptt_start, 1, NULL, NULL); } +#endif - + #define ACPI_NAMESEG_LEN 4 - + diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 16700a2e..96f56e2e 100644 +index 272455bc..9669c70b 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -304,6 +304,77 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) +@@ -308,6 +308,81 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags); } - + +static void fdt_add_l3cache_nodes(const VirtMachineState *vms) +{ + int i; ++ const MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cores = ms->smp.cores; + unsigned int sockets = vms->smp_cpus / smp_cores; + + /* If current is not equal to max */ @@ -191,6 +195,8 @@ index 16700a2e..96f56e2e 100644 +static void fdt_add_l2cache_nodes(const VirtMachineState *vms) +{ + int i, j; ++ const MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cores = ms->smp.cores; + signed int sockets = vms->smp_cpus / smp_cores; + + /* If current is not equal to max */ @@ -237,17 +243,17 @@ index 16700a2e..96f56e2e 100644 static void fdt_add_cpu_nodes(const VirtMachineState *vms) { int cpu; -@@ -336,6 +407,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) +@@ -341,6 +416,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells); qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); - + + fdt_add_l3cache_nodes(vms); + fdt_add_l2cache_nodes(vms); + for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); -@@ -364,7 +438,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) +@@ -369,7 +447,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", ms->possible_cpus->cpus[cs->cpu_index].props.node_id); } @@ -255,7 +261,7 @@ index 16700a2e..96f56e2e 100644 + fdt_add_l1cache_prop(vms, nodename, cpu); qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", qemu_fdt_alloc_phandle(vms->fdt)); - + diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index bfb0b100..0be3453a 100644 --- a/include/hw/acpi/aml-build.h @@ -263,7 +269,7 @@ index bfb0b100..0be3453a 100644 @@ -223,6 +223,52 @@ struct AcpiBuildTables { BIOSLinker *linker; } AcpiBuildTables; - + +#ifdef __aarch64__ +/* Definitions of the hardcoded cache info*/ + @@ -313,6 +319,5 @@ index bfb0b100..0be3453a 100644 /** * init_aml_allocator: * --- +-- 2.23.0 - diff --git a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch new file mode 100644 index 0000000000000000000000000000000000000000..770f12b1acf9dfc3c4289e9a9bea7d5936df1968 --- /dev/null +++ b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch @@ -0,0 +1,45 @@ +From aae0faa5d3bee91c66dc4c1543190f55a242771e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 25 Sep 2019 14:16:43 +0200 +Subject: [PATCH] hw/core/loader: Fix possible crash in rom_copy() + +Both, "rom->addr" and "addr" are derived from the binary image +that can be loaded with the "-kernel" paramer. The code in +rom_copy() then calculates: + + d = dest + (rom->addr - addr); + +and uses "d" as destination in a memcpy() some lines later. Now with +bad kernel images, it is possible that rom->addr is smaller than addr, +thus "rom->addr - addr" gets negative and the memcpy() then tries to +copy contents from the image to a bad memory location. This could +maybe be used to inject code from a kernel image into the QEMU binary, +so we better fix it with an additional sanity check here. + +Cc: qemu-stable@nongnu.org +Reported-by: Guangming Liu +Buglink: https://bugs.launchpad.net/qemu/+bug/1844635 +Message-Id: <20190925130331.27825-1-thuth@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Thomas Huth +(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319) +Signed-off-by: Michael Roth +--- + hw/core/loader.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/loader.c b/hw/core/loader.c +index 425bf69a99..838a34174a 100644 +--- a/hw/core/loader.c ++++ b/hw/core/loader.c +@@ -1242,7 +1242,7 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size) + if (rom->addr + rom->romsize < addr) { + continue; + } +- if (rom->addr > end) { ++ if (rom->addr > end || rom->addr < addr) { + break; + } + +-- +2.23.0 diff --git a/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b77e0b0ce8a678b0c13b7f9f852522617b90c71 --- /dev/null +++ b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch @@ -0,0 +1,170 @@ +From 6bbfb186c8d66b745aeb08143d3198fcedc52d6c Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 11:26:35 +0800 +Subject: [PATCH] hw/intc/gicv3: Add CPU hotplug realize hook + +GICv3 exposes individual CPU realization capability through +this hook. It will be used for hotplugged CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3.c | 17 ++++++++++++++++- + hw/intc/arm_gicv3_common.c | 8 ++++++++ + hw/intc/arm_gicv3_kvm.c | 11 +++++++++++ + include/hw/intc/arm_gicv3.h | 2 ++ + include/hw/intc/arm_gicv3_common.h | 4 ++++ + 5 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index 2fe79f794d..cacef26546 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -361,6 +361,19 @@ static const MemoryRegionOps gic_ops[] = { + } + }; + ++static void gicv3_cpu_realize(GICv3State *s, int i) ++{ ++ gicv3_init_one_cpuif(s, i); ++} ++ ++static void arm_gicv3_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s); ++ ++ agc->parent_cpu_hotplug_realize(s, ncpu); ++ gicv3_cpu_realize(s, ncpu); ++} ++ + static void arm_gic_realize(DeviceState *dev, Error **errp) + { + /* Device instance realize function for the GIC sysbus device */ +@@ -388,7 +401,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + } + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_init_one_cpuif(s, i); ++ gicv3_cpu_realize(s, i); + } + } + +@@ -398,6 +411,8 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data) + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + ARMGICv3Class *agc = ARM_GICV3_CLASS(klass); + ++ agc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; ++ agcc->cpu_hotplug_realize = arm_gicv3_cpu_hotplug_realize; + agcc->post_load = arm_gicv3_post_load; + device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize); + } +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 798f295d7c..8740a52c9f 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -313,6 +313,11 @@ static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) + gicv3_set_gicv3state(cpu, &s->cpu[ncpu]); + } + ++static void arm_gicv3_common_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ arm_gicv3_common_cpu_realize(s, ncpu); ++} ++ + static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = ARM_GICV3_COMMON(dev); +@@ -357,6 +362,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + + for (i = 0; i < s->num_cpu; i++) { + CPUState *cpu = qemu_get_cpu(i); ++ + uint64_t cpu_affid; + int last; + +@@ -508,12 +514,14 @@ static Property arm_gicv3_common_properties[] = { + static void arm_gicv3_common_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); ++ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass); + + dc->reset = arm_gicv3_common_reset; + dc->realize = arm_gicv3_common_realize; + dc->props = arm_gicv3_common_properties; + dc->vmsd = &vmstate_gicv3; ++ agcc->cpu_hotplug_realize = arm_gicv3_common_cpu_hotplug_realize; + albifc->arm_linux_init = arm_gic_common_linux_init; + } + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index b2936938cb..f8d7be5479 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -78,6 +78,7 @@ typedef struct KVMARMGICv3Class { + ARMGICv3CommonClass parent_class; + DeviceRealize parent_realize; + void (*parent_reset)(DeviceState *dev); ++ CPUHotplugRealize parent_cpu_hotplug_realize; + } KVMARMGICv3Class; + + static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) +@@ -768,6 +769,14 @@ static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) + define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); + } + ++static void kvm_arm_gicv3_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ KVMARMGICv3Class *kagcc = KVM_ARM_GICV3_GET_CLASS(s); ++ ++ kagcc->parent_cpu_hotplug_realize(s, ncpu); ++ kvm_arm_gicv3_cpu_realize(s, ncpu); ++} ++ + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = KVM_ARM_GICV3(dev); +@@ -884,6 +893,8 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass); + ++ kgc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; ++ agcc->cpu_hotplug_realize = kvm_arm_gicv3_cpu_hotplug_realize; + agcc->pre_save = kvm_arm_gicv3_get; + agcc->post_load = kvm_arm_gicv3_put; + device_class_set_parent_realize(dc, kvm_arm_gicv3_realize, +diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h +index 4a6fd85e22..98f2bdb7e9 100644 +--- a/include/hw/intc/arm_gicv3.h ++++ b/include/hw/intc/arm_gicv3.h +@@ -26,6 +26,8 @@ typedef struct ARMGICv3Class { + ARMGICv3CommonClass parent_class; + /*< public >*/ + ++ CPUHotplugRealize parent_cpu_hotplug_realize; ++ + DeviceRealize parent_realize; + } ARMGICv3Class; + +diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h +index 31ec9a1ae4..45cc50ed3b 100644 +--- a/include/hw/intc/arm_gicv3_common.h ++++ b/include/hw/intc/arm_gicv3_common.h +@@ -286,11 +286,15 @@ GICV3_BITMAP_ACCESSORS(edge_trigger) + #define ARM_GICV3_COMMON_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON) + ++typedef void (*CPUHotplugRealize)(GICv3State *s, int ncpu); ++ + typedef struct ARMGICv3CommonClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ + ++ CPUHotplugRealize cpu_hotplug_realize; ++ + void (*pre_save)(GICv3State *s); + void (*post_load)(GICv3State *s); + } ARMGICv3CommonClass; +-- +2.19.1 diff --git a/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch new file mode 100644 index 0000000000000000000000000000000000000000..30175fb5126a8a9b7138c206365b61c96bcddaf0 --- /dev/null +++ b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch @@ -0,0 +1,357 @@ +From 0a75312c069d89be94bcaa688429d8f60a0c528b Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:15:35 +0800 +Subject: [PATCH] intc/gicv3: Add pre-sizing capability to GICv3 + +Currently GICv3 supports fixed smp_cpus CPUs, and all CPUs are +present always. Now we want to pre-sizing GICv3 to support max_cpus +CPUs and not all of them are present always, so some sizing codes +should be concerned. + +GIC irqs, GICR and GICC are pre-created for all possible CPUs at +start, but only smp_cpus CPUs are realize and irqs of smp_cpus CPUs +are connected. + +Other code changes are mainly for arm_gicv3, and we do little about +kvm_arm_gicv3 becasue KVM will deal with the sizing information properly. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 17 +++++++++++---- + hw/intc/arm_gicv3.c | 43 +++++++++++++++++++++++++------------- + hw/intc/arm_gicv3_common.c | 23 ++++++++++++++++++-- + hw/intc/arm_gicv3_cpuif.c | 4 ++++ + hw/intc/arm_gicv3_kvm.c | 28 ++++++++++++++++++++++++- + include/hw/arm/virt.h | 3 ++- + 6 files changed, 96 insertions(+), 22 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 55d403bad6..dda22194b5 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -761,14 +761,19 @@ static void create_gic(VirtMachineState *vms) + SysBusDevice *gicbusdev; + const char *gictype; + int type = vms->gic_version, i; ++ /* The max number of CPUs suppored by GIC */ ++ unsigned int num_cpus = ms->smp.cpus; ++ /* The number of CPUs present before boot */ + unsigned int smp_cpus = ms->smp.cpus; + uint32_t nb_redist_regions = 0; + ++ assert(num_cpus >= smp_cpus); ++ + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); + + vms->gic = qdev_create(NULL, gictype); + qdev_prop_set_uint32(vms->gic, "revision", type); +- qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); ++ qdev_prop_set_uint32(vms->gic, "num-cpu", num_cpus); + /* Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ +@@ -780,7 +785,7 @@ static void create_gic(VirtMachineState *vms) + if (type == 3) { + uint32_t redist0_capacity = + vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; +- uint32_t redist0_count = MIN(smp_cpus, redist0_capacity); ++ uint32_t redist0_count = MIN(num_cpus, redist0_capacity); + + nb_redist_regions = virt_gicv3_redist_region_count(vms); + +@@ -793,7 +798,7 @@ static void create_gic(VirtMachineState *vms) + vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; + + qdev_prop_set_uint32(vms->gic, "redist-region-count[1]", +- MIN(smp_cpus - redist0_count, redist1_capacity)); ++ MIN(num_cpus - redist0_count, redist1_capacity)); + } + } else { + if (!kvm_irqchip_in_kernel()) { +@@ -820,7 +825,11 @@ static void create_gic(VirtMachineState *vms) + + /* Wire the outputs from each CPU's generic timer and the GICv3 + * maintenance interrupt signal to the appropriate GIC PPI inputs, +- * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. ++ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's ++ * inputs. ++ * ++ * The irqs of remaining CPUs (if we has) will be connected during ++ * hotplugging. + */ + for (i = 0; i < smp_cpus; i++) { + connect_gic_cpu_irqs(vms, i); +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index cacef26546..a60185113f 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -20,6 +20,7 @@ + #include "qemu/module.h" + #include "hw/sysbus.h" + #include "hw/intc/arm_gicv3.h" ++#include "qom/cpu.h" + #include "gicv3_internal.h" + + static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio) +@@ -206,7 +207,9 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) + assert(len > 0); + + for (i = 0; i < s->num_cpu; i++) { +- s->cpu[i].seenbetter = false; ++ if (qemu_get_cpu(i)) { ++ s->cpu[i].seenbetter = false; ++ } + } + + /* Find the highest priority pending interrupt in this range. */ +@@ -248,16 +251,18 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) + * now be the new best one). + */ + for (i = 0; i < s->num_cpu; i++) { +- GICv3CPUState *cs = &s->cpu[i]; ++ if (qemu_get_cpu(i)) { ++ GICv3CPUState *cs = &s->cpu[i]; + +- if (cs->seenbetter) { +- cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); +- } ++ if (cs->seenbetter) { ++ cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); ++ } + +- if (!cs->seenbetter && cs->hppi.prio != 0xff && +- cs->hppi.irq >= start && cs->hppi.irq < start + len) { +- gicv3_full_update_noirqset(s); +- break; ++ if (!cs->seenbetter && cs->hppi.prio != 0xff && ++ cs->hppi.irq >= start && cs->hppi.irq < start + len) { ++ gicv3_full_update_noirqset(s); ++ break; ++ } + } + } + } +@@ -268,7 +273,9 @@ void gicv3_update(GICv3State *s, int start, int len) + + gicv3_update_noirqset(s, start, len); + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpuif_update(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpuif_update(&s->cpu[i]); ++ } + } + } + +@@ -280,7 +287,9 @@ void gicv3_full_update_noirqset(GICv3State *s) + int i; + + for (i = 0; i < s->num_cpu; i++) { +- s->cpu[i].hppi.prio = 0xff; ++ if (qemu_get_cpu(i)) { ++ s->cpu[i].hppi.prio = 0xff; ++ } + } + + /* Note that we can guarantee that these functions will not +@@ -291,7 +300,9 @@ void gicv3_full_update_noirqset(GICv3State *s) + gicv3_update_noirqset(s, GIC_INTERNAL, s->num_irq - GIC_INTERNAL); + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_redist_update_noirqset(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_redist_update_noirqset(&s->cpu[i]); ++ } + } + } + +@@ -304,7 +315,9 @@ void gicv3_full_update(GICv3State *s) + + gicv3_full_update_noirqset(s); + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpuif_update(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpuif_update(&s->cpu[i]); ++ } + } + } + +@@ -401,7 +414,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + } + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpu_realize(s, i); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpu_realize(s, i); ++ } + } + } + +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 8740a52c9f..913bf068be 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -24,10 +24,12 @@ + #include "qemu/osdep.h" + #include "qapi/error.h" + #include "qemu/module.h" ++#include "qemu/error-report.h" + #include "qom/cpu.h" + #include "hw/intc/arm_gicv3_common.h" + #include "gicv3_internal.h" + #include "hw/arm/linux-boot-if.h" ++#include "hw/boards.h" + #include "sysemu/kvm.h" + + +@@ -363,10 +365,15 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + for (i = 0; i < s->num_cpu; i++) { + CPUState *cpu = qemu_get_cpu(i); + ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ const CPUArchIdList *possible_cpus = NULL; + uint64_t cpu_affid; + int last; + +- arm_gicv3_common_cpu_realize(s, i); ++ if (cpu) { ++ arm_gicv3_common_cpu_realize(s, i); ++ } + + /* Pre-construct the GICR_TYPER: + * For our implementation: +@@ -380,7 +387,19 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + * VLPIS == 0 (virtual LPIs not supported) + * PLPIS == 0 (physical LPIs not supported) + */ +- cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL); ++ if (cpu) { ++ cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL); ++ } else { ++ if (!mc->possible_cpu_arch_ids) { ++ error_report("MachineClass must implement possible_cpu_arch_ids " ++ "hook to support pre-sizing GICv3"); ++ exit(1); ++ } ++ ++ possible_cpus = mc->possible_cpu_arch_ids(ms); ++ cpu_affid = possible_cpus->cpus[i].arch_id; ++ } ++ + last = (i == s->num_cpu - 1); + + /* The CPU mp-affinity property is in MPIDR register format; squash +diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c +index 56aa5efede..a20aa693ea 100644 +--- a/hw/intc/arm_gicv3_cpuif.c ++++ b/hw/intc/arm_gicv3_cpuif.c +@@ -1648,6 +1648,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs, + aff, targetlist); + + for (i = 0; i < s->num_cpu; i++) { ++ if (!qemu_get_cpu(i)) { ++ continue; ++ } ++ + GICv3CPUState *ocs = &s->cpu[i]; + + if (irm) { +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index f8d7be5479..8eea7c9dd9 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -341,6 +341,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c = &s->cpu[ncpu]; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + reg64 = c->gicr_propbaser; + regl = (uint32_t)reg64; + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); +@@ -366,6 +370,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c = &s->cpu[ncpu]; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + reg = c->gicr_ctlr; + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); + +@@ -462,6 +470,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + GICv3CPUState *c = &s->cpu[ncpu]; + int num_pri_bits; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); + kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, + &c->icc_ctlr_el1[GICV3_NS], true); +@@ -525,6 +537,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + /* Redistributor state (one per CPU) */ + + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); +@@ -560,6 +576,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + + if (redist_typer & GICR_TYPER_PLPIS) { + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); +@@ -613,6 +633,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + */ + + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + int num_pri_bits; + +@@ -806,7 +830,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + } + + for (i = 0; i < s->num_cpu; i++) { +- kvm_arm_gicv3_cpu_realize(s, i); ++ if (qemu_get_cpu(i)) { ++ kvm_arm_gicv3_cpu_realize(s, i); ++ } + } + + /* Try to create the device via the device control API */ +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 6880ebe07c..beef4c8002 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -168,8 +168,9 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) + vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; + + assert(vms->gic_version == 3); ++ GICv3State *s = ARM_GICV3_COMMON(vms->gic); + +- return vms->smp_cpus > redist0_capacity ? 2 : 1; ++ return s->num_cpu > redist0_capacity ? 2 : 1; + } + + #endif /* QEMU_ARM_VIRT_H */ +-- +2.19.1 diff --git a/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch new file mode 100644 index 0000000000000000000000000000000000000000..5232d3f2aeda4d3a8a83a725173eaff72d2af8d5 --- /dev/null +++ b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch @@ -0,0 +1,50 @@ +From a7391f391336024986a5997e3beae8882c983ed0 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 12:55:17 +0800 +Subject: [PATCH] intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out realization code to let +it can be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3_common.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 5edabb928f..798f295d7c 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -303,6 +303,16 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, + } + } + ++static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) ++{ ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ ++ s->cpu[ncpu].cpu = cpu; ++ s->cpu[ncpu].gic = s; ++ /* Store GICv3CPUState in CPUARMState gicv3state pointer */ ++ gicv3_set_gicv3state(cpu, &s->cpu[ncpu]); ++} ++ + static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = ARM_GICV3_COMMON(dev); +@@ -350,10 +360,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + uint64_t cpu_affid; + int last; + +- s->cpu[i].cpu = cpu; +- s->cpu[i].gic = s; +- /* Store GICv3CPUState in CPUARMState gicv3state pointer */ +- gicv3_set_gicv3state(cpu, &s->cpu[i]); ++ arm_gicv3_common_cpu_realize(s, i); + + /* Pre-construct the GICR_TYPER: + * For our implementation: +-- +2.19.1 diff --git a/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch new file mode 100644 index 0000000000000000000000000000000000000000..95c60b02c66e48b2fbe6d64c5e139aa3ecdcfae9 --- /dev/null +++ b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch @@ -0,0 +1,197 @@ +From de97ff4a01008ad98f7d69adc4b84843fff3ce19 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:59:55 +0800 +Subject: [PATCH] intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out some code to let it can +be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3.c | 5 +- + hw/intc/arm_gicv3_cpuif.c | 122 ++++++++++++++++++-------------------- + hw/intc/gicv3_internal.h | 2 +- + 3 files changed, 64 insertions(+), 65 deletions(-) + +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index 66eaa97198..2fe79f794d 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -367,6 +367,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + GICv3State *s = ARM_GICV3(dev); + ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s); + Error *local_err = NULL; ++ int i; + + agc->parent_realize(dev, &local_err); + if (local_err) { +@@ -386,7 +387,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + return; + } + +- gicv3_init_cpuif(s); ++ for (i = 0; i < s->num_cpu; i++) { ++ gicv3_init_one_cpuif(s, i); ++ } + } + + static void arm_gicv3_class_init(ObjectClass *klass, void *data) +diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c +index 3b212d91c8..56aa5efede 100644 +--- a/hw/intc/arm_gicv3_cpuif.c ++++ b/hw/intc/arm_gicv3_cpuif.c +@@ -2597,78 +2597,74 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque) + gicv3_cpuif_update(cs); + } + +-void gicv3_init_cpuif(GICv3State *s) ++void gicv3_init_one_cpuif(GICv3State *s, int ncpu) + { + /* Called from the GICv3 realize function; register our system + * registers with the CPU + */ +- int i; +- +- for (i = 0; i < s->num_cpu; i++) { +- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); +- GICv3CPUState *cs = &s->cpu[i]; +- +- /* Note that we can't just use the GICv3CPUState as an opaque pointer +- * in define_arm_cp_regs_with_opaque(), because when we're called back +- * it might be with code translated by CPU 0 but run by CPU 1, in +- * which case we'd get the wrong value. +- * So instead we define the regs with no ri->opaque info, and +- * get back to the GICv3CPUState from the CPUARMState. +- */ +- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); +- if (arm_feature(&cpu->env, ARM_FEATURE_EL2) +- && cpu->gic_num_lrs) { +- int j; ++ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); ++ GICv3CPUState *cs = &s->cpu[ncpu]; ++ ++ /* Note that we can't just use the GICv3CPUState as an opaque pointer ++ * in define_arm_cp_regs_with_opaque(), because when we're called back ++ * it might be with code translated by CPU 0 but run by CPU 1, in ++ * which case we'd get the wrong value. ++ * So instead we define the regs with no ri->opaque info, and ++ * get back to the GICv3CPUState from the CPUARMState. ++ */ ++ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++ if (arm_feature(&cpu->env, ARM_FEATURE_EL2) ++ && cpu->gic_num_lrs) { ++ int j; + +- cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; ++ cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; + +- cs->num_list_regs = cpu->gic_num_lrs; +- cs->vpribits = cpu->gic_vpribits; +- cs->vprebits = cpu->gic_vprebits; ++ cs->num_list_regs = cpu->gic_num_lrs; ++ cs->vpribits = cpu->gic_vpribits; ++ cs->vprebits = cpu->gic_vprebits; + +- /* Check against architectural constraints: getting these +- * wrong would be a bug in the CPU code defining these, +- * and the implementation relies on them holding. +- */ +- g_assert(cs->vprebits <= cs->vpribits); +- g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); +- g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); ++ /* Check against architectural constraints: getting these ++ * wrong would be a bug in the CPU code defining these, ++ * and the implementation relies on them holding. ++ */ ++ g_assert(cs->vprebits <= cs->vpribits); ++ g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); ++ g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); + +- define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); ++ define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); + +- for (j = 0; j < cs->num_list_regs; j++) { +- /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs +- * are split into two cp15 regs, LR (the low part, with the +- * same encoding as the AArch64 LR) and LRC (the high part). +- */ +- ARMCPRegInfo lr_regset[] = { +- { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH, +- .opc0 = 3, .opc1 = 4, .crn = 12, +- .crm = 12 + (j >> 3), .opc2 = j & 7, +- .type = ARM_CP_IO | ARM_CP_NO_RAW, +- .access = PL2_RW, +- .readfn = ich_lr_read, +- .writefn = ich_lr_write, +- }, +- { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32, +- .cp = 15, .opc1 = 4, .crn = 12, +- .crm = 14 + (j >> 3), .opc2 = j & 7, +- .type = ARM_CP_IO | ARM_CP_NO_RAW, +- .access = PL2_RW, +- .readfn = ich_lr_read, +- .writefn = ich_lr_write, +- }, +- REGINFO_SENTINEL +- }; +- define_arm_cp_regs(cpu, lr_regset); +- } +- if (cs->vprebits >= 6) { +- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo); +- } +- if (cs->vprebits == 7) { +- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo); +- } ++ for (j = 0; j < cs->num_list_regs; j++) { ++ /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs ++ * are split into two cp15 regs, LR (the low part, with the ++ * same encoding as the AArch64 LR) and LRC (the high part). ++ */ ++ ARMCPRegInfo lr_regset[] = { ++ { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH, ++ .opc0 = 3, .opc1 = 4, .crn = 12, ++ .crm = 12 + (j >> 3), .opc2 = j & 7, ++ .type = ARM_CP_IO | ARM_CP_NO_RAW, ++ .access = PL2_RW, ++ .readfn = ich_lr_read, ++ .writefn = ich_lr_write, ++ }, ++ { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32, ++ .cp = 15, .opc1 = 4, .crn = 12, ++ .crm = 14 + (j >> 3), .opc2 = j & 7, ++ .type = ARM_CP_IO | ARM_CP_NO_RAW, ++ .access = PL2_RW, ++ .readfn = ich_lr_read, ++ .writefn = ich_lr_write, ++ }, ++ REGINFO_SENTINEL ++ }; ++ define_arm_cp_regs(cpu, lr_regset); ++ } ++ if (cs->vprebits >= 6) { ++ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo); ++ } ++ if (cs->vprebits == 7) { ++ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo); + } +- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs); + } ++ arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs); + } +diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h +index 05303a55c8..cfbfe8a549 100644 +--- a/hw/intc/gicv3_internal.h ++++ b/hw/intc/gicv3_internal.h +@@ -297,7 +297,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, + void gicv3_dist_set_irq(GICv3State *s, int irq, int level); + void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level); + void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); +-void gicv3_init_cpuif(GICv3State *s); ++void gicv3_init_one_cpuif(GICv3State *s, int ncpu); + + /** + * gicv3_cpuif_update: +-- +2.19.1 diff --git a/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch new file mode 100644 index 0000000000000000000000000000000000000000..6af9a8f4f55fa4ce936c9d5898cd5c232abcaa9a --- /dev/null +++ b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch @@ -0,0 +1,45 @@ +From f45964c7e0df4ef17457a9ea92bfd255064139e1 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 12:49:12 +0800 +Subject: [PATCH] intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out realization code to let +it can be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3_kvm.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index b1e74147ba..b2936938cb 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -761,6 +761,12 @@ static void vm_change_state_handler(void *opaque, int running, + } + } + ++static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) ++{ ++ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); ++ ++ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++} + + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + { +@@ -791,9 +797,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + } + + for (i = 0; i < s->num_cpu; i++) { +- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); +- +- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++ kvm_arm_gicv3_cpu_realize(s, i); + } + + /* Try to create the device via the device control API */ +-- +2.19.1 diff --git a/libvhost-user-fix-SLAVE_SEND_FD-handling.patch b/libvhost-user-fix-SLAVE_SEND_FD-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..71cbf7baa7b59006c74a8eadb9b74b10079a9a9d --- /dev/null +++ b/libvhost-user-fix-SLAVE_SEND_FD-handling.patch @@ -0,0 +1,42 @@ +From 28a9a3558a427493049723fff390add7026653eb Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 3 Sep 2019 23:04:22 +0300 +Subject: [PATCH] libvhost-user: fix SLAVE_SEND_FD handling + +It doesn't look like this could possibly work properly since +VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD is defined to 10, but the +dev->protocol_features has a bitmap. I suppose the peer this +was tested with also supported VHOST_USER_PROTOCOL_F_LOG_SHMFD, +in which case the test would always be false, but nevertheless +the code seems wrong. + +Use has_feature() to fix this. + +Fixes: d84599f56c82 ("libvhost-user: support host notifier") +Signed-off-by: Johannes Berg +Message-Id: <20190903200422.11693-1-johannes@sipsolutions.net> +Reviewed-by: Tiwei Bie +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 8726b70b449896f1211f869ec4f608904f027207) +Signed-off-by: Michael Roth +--- + contrib/libvhost-user/libvhost-user.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c +index 4b36e35a82..cb5f5770e4 100644 +--- a/contrib/libvhost-user/libvhost-user.c ++++ b/contrib/libvhost-user/libvhost-user.c +@@ -1097,7 +1097,8 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, + + vmsg.fd_num = fd_num; + +- if ((dev->protocol_features & VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) == 0) { ++ if (!has_feature(dev->protocol_features, ++ VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD)) { + return false; + } + +-- +2.23.0 diff --git a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch index 3d4e4ad5bb7e833e97c2d51f9ab2cf5ae555e823..731d06a74024c81bcc1ececeb79da2b873c2546f 100644 --- a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch +++ b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch @@ -1,7 +1,7 @@ -From 896b9892d4df316b85836daa973e442c0c64cec6 Mon Sep 17 00:00:00 2001 +From 27a9f40b308efd8ddcb81e286441865b5a0cb541 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" +Date: Tue, 14 Apr 2020 21:52:42 +0800 +Subject: [PATCH] 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 . @@ -19,7 +19,7 @@ index e1f8b745..137a2730 100644 +++ 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 @@ -30,12 +30,12 @@ index e1f8b745..137a2730 100644 #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 +index 2431ec35..cdfd5f33 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h -@@ -265,8 +265,10 @@ struct kvm_vcpu_events { +@@ -308,8 +308,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 @@ -46,17 +46,16 @@ index e6a98c14..dfd3a028 100644 #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 +index c8423e76..744e888e 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_MANUAL_DIRTY_LOG_PROTECT 166 /* Obsolete */ #define KVM_CAP_HYPERV_CPUID 167 +#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 - - #ifdef KVM_CAP_IRQ_ROUTING - --- -2.19.1 - + #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168 + #define KVM_CAP_PPC_IRQ_XIVE 169 + #define KVM_CAP_ARM_SVE 170 +-- +2.23.0 diff --git a/make-release-pull-in-edk2-submodules-so-we-can-build.patch b/make-release-pull-in-edk2-submodules-so-we-can-build.patch new file mode 100644 index 0000000000000000000000000000000000000000..70bcc864d0fd976919e540165bc7167e5026c46e --- /dev/null +++ b/make-release-pull-in-edk2-submodules-so-we-can-build.patch @@ -0,0 +1,60 @@ +From c5c9b1362d1652a9d0f79f6d9ae2f80d4b5fe432 Mon Sep 17 00:00:00 2001 +From: Michael Roth +Date: Thu, 12 Sep 2019 18:12:01 -0500 +Subject: [PATCH] make-release: pull in edk2 submodules so we can build it from + tarballs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The `make efi` target added by 536d2173 is built from the roms/edk2 +submodule, which in turn relies on additional submodules nested under +roms/edk2. + +The make-release script currently only pulls in top-level submodules, +so these nested submodules are missing in the resulting tarball. + +We could try to address this situation more generally by recursively +pulling in all submodules, but this doesn't necessarily ensure the +end-result will build properly (this case also required other changes). + +Additionally, due to the nature of submodules, we may not always have +control over how these sorts of things are dealt with, so for now we +continue to handle it on a case-by-case in the make-release script. + +Cc: Laszlo Ersek +Cc: Bruce Rogers +Cc: qemu-stable@nongnu.org # v4.1.0 +Reported-by: Bruce Rogers +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Michael Roth +Message-Id: <20190912231202.12327-2-mdroth@linux.vnet.ibm.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 45c61c6c23918e3b05ed9ecac5b2328ebae5f774) +Signed-off-by: Michael Roth +--- + scripts/make-release | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/scripts/make-release b/scripts/make-release +index b4af9c9e52..a2a8cda33c 100755 +--- a/scripts/make-release ++++ b/scripts/make-release +@@ -20,6 +20,14 @@ git checkout "v${version}" + git submodule update --init + (cd roms/seabios && git describe --tags --long --dirty > .version) + (cd roms/skiboot && ./make_version.sh > .version) ++# Fetch edk2 submodule's submodules, since it won't have access to them via ++# the tarball later. ++# ++# A more uniform way to handle this sort of situation would be nice, but we ++# don't necessarily have much control over how a submodule handles its ++# submodule dependencies, so we continue to handle these on a case-by-case ++# basis for now. ++(cd roms/edk2 && git submodule update --init) + popd + tar --exclude=.git -cjf ${destination}.tar.bz2 ${destination} + rm -rf ${destination} +-- +2.23.0 diff --git a/memory-unref-the-memory-region-in-simplify-flatview.patch b/memory-unref-the-memory-region-in-simplify-flatview.patch deleted file mode 100644 index eb199646181ccf95dcfef2208a6b5592ff20b6d8..0000000000000000000000000000000000000000 --- a/memory-unref-the-memory-region-in-simplify-flatview.patch +++ /dev/null @@ -1,85 +0,0 @@ -From b9f43f0cca03586a31b53e47ade72e77db01cb4c Mon Sep 17 00:00:00 2001 -From: King Wang -Date: Fri, 12 Jul 2019 14:52:41 +0800 -Subject: [PATCH 2/5] memory: unref the memory region in simplify flatview - -The memory region reference is increased when insert a range -into flatview range array, then decreased by destroy flatview. -If some flat range merged by flatview_simplify, the memory region -reference can not be decreased by destroy flatview any more. - -In this case, start virtual machine by the command line: -qemu-system-x86_64 --name guest=ubuntu,debug-threads=on --machine pc,accel=kvm,usb=off,dump-guest-core=off --cpu host --m 16384 --realtime mlock=off --smp 8,sockets=2,cores=4,threads=1 --object memory-backend-file,id=ram-node0,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592 --numa node,nodeid=0,cpus=0-3,memdev=ram-node0 --object memory-backend-file,id=ram-node1,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592 --numa node,nodeid=1,cpus=4-7,memdev=ram-node1 --no-user-config --nodefaults --rtc base=utc --no-shutdown --boot strict=on --device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 --device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2 --device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 --drive file=ubuntu.qcow2,format=qcow2,if=none,id=drive-virtio-disk0,cache=none,aio=native --device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 --chardev pty,id=charserial0 --device isa-serial,chardev=charserial0,id=serial0 --device usb-tablet,id=input0,bus=usb.0,port=1 --vnc 0.0.0.0:0 --device VGA,id=video0,vgamem_mb=16,bus=pci.0,addr=0x5 --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 --msg timestamp=on - -And run the script in guest OS: -while true -do - setpci -s 00:06.0 04.b=03 - setpci -s 00:06.0 04.b=07 -done - -I found the reference of node0 HostMemoryBackendFile is a big one. -(gdb) p numa_info[0]->node_memdev->parent.ref -$6 = 1636278 -(gdb) - -Signed-off-by: King Wang -Message-Id: <20190712065241.11784-1-king.wang@huawei.com> -Signed-off-by: Paolo Bonzini ---- - memory.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/memory.c b/memory.c -index 9fbca52..0b49281 100644 ---- a/memory.c -+++ b/memory.c -@@ -320,7 +320,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) - /* Attempt to simplify a view by merging adjacent ranges */ - static void flatview_simplify(FlatView *view) - { -- unsigned i, j; -+ unsigned i, j, k; - - i = 0; - while (i < view->nr) { -@@ -331,6 +331,9 @@ static void flatview_simplify(FlatView *view) - ++j; - } - ++i; -+ for (k = i; k < j; k++) { -+ memory_region_unref(view->ranges[k].mr); -+ } - memmove(&view->ranges[i], &view->ranges[j], - (view->nr - j) * sizeof(view->ranges[j])); - view->nr -= j - i; --- -1.8.3.1 - diff --git a/migration-Make-global-sem_sync-semaphore-by-channel.patch b/migration-Make-global-sem_sync-semaphore-by-channel.patch new file mode 100644 index 0000000000000000000000000000000000000000..d9dbab23e4f83d88595956668c61385618864fd7 --- /dev/null +++ b/migration-Make-global-sem_sync-semaphore-by-channel.patch @@ -0,0 +1,100 @@ +From 8c3794d709eefdae777477bef7ff3511d55bf418 Mon Sep 17 00:00:00 2001 +From: Juan Quintela +Date: Wed, 14 Aug 2019 04:02:14 +0200 +Subject: [PATCH 05/10] migration: Make global sem_sync semaphore by channel + +This makes easy to debug things because when you want for all threads +to arrive at that semaphore, you know which one your are waiting for. + +Change-Id: I533af8cdc68f619b68eff8e4e573c4de371a3954 +Signed-off-by: Juan Quintela +Message-Id: <20190814020218.1868-3-quintela@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +--- + migration/ram.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index c75716bb..51811c2d 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -661,6 +661,8 @@ typedef struct { + uint64_t num_packets; + /* pages sent through this channel */ + uint64_t num_pages; ++ /* syncs main thread and channels */ ++ QemuSemaphore sem_sync; + } MultiFDSendParams; + + typedef struct { +@@ -896,8 +898,6 @@ struct { + MultiFDSendParams *params; + /* array of pages to sent */ + MultiFDPages_t *pages; +- /* syncs main thread and channels */ +- QemuSemaphore sem_sync; + /* global number of generated multifd packets */ + uint64_t packet_num; + /* send channels ready */ +@@ -1037,6 +1037,7 @@ void multifd_save_cleanup(void) + p->c = NULL; + qemu_mutex_destroy(&p->mutex); + qemu_sem_destroy(&p->sem); ++ qemu_sem_destroy(&p->sem_sync); + g_free(p->name); + p->name = NULL; + multifd_pages_clear(p->pages); +@@ -1046,7 +1047,6 @@ void multifd_save_cleanup(void) + p->packet = NULL; + } + qemu_sem_destroy(&multifd_send_state->channels_ready); +- qemu_sem_destroy(&multifd_send_state->sem_sync); + g_free(multifd_send_state->params); + multifd_send_state->params = NULL; + multifd_pages_clear(multifd_send_state->pages); +@@ -1096,7 +1096,7 @@ static void multifd_send_sync_main(RAMState *rs) + MultiFDSendParams *p = &multifd_send_state->params[i]; + + trace_multifd_send_sync_main_wait(p->id); +- qemu_sem_wait(&multifd_send_state->sem_sync); ++ qemu_sem_wait(&p->sem_sync); + } + trace_multifd_send_sync_main(multifd_send_state->packet_num); + } +@@ -1156,7 +1156,7 @@ static void *multifd_send_thread(void *opaque) + qemu_mutex_unlock(&p->mutex); + + if (flags & MULTIFD_FLAG_SYNC) { +- qemu_sem_post(&multifd_send_state->sem_sync); ++ qemu_sem_post(&p->sem_sync); + } + qemu_sem_post(&multifd_send_state->channels_ready); + } else if (p->quit) { +@@ -1179,7 +1179,7 @@ out: + */ + if (ret != 0) { + if (flags & MULTIFD_FLAG_SYNC) { +- qemu_sem_post(&multifd_send_state->sem_sync); ++ qemu_sem_post(&p->sem_sync); + } + qemu_sem_post(&multifd_send_state->channels_ready); + } +@@ -1225,7 +1225,6 @@ int multifd_save_setup(void) + multifd_send_state = g_malloc0(sizeof(*multifd_send_state)); + multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); + multifd_send_state->pages = multifd_pages_init(page_count); +- qemu_sem_init(&multifd_send_state->sem_sync, 0); + qemu_sem_init(&multifd_send_state->channels_ready, 0); + + for (i = 0; i < thread_count; i++) { +@@ -1233,6 +1232,7 @@ int multifd_save_setup(void) + + qemu_mutex_init(&p->mutex); + qemu_sem_init(&p->sem, 0); ++ qemu_sem_init(&p->sem_sync, 0); + p->quit = false; + p->pending_job = 0; + p->id = i; +-- +2.19.1 diff --git a/migration-Maybe-VM-is-paused-when-migration-is-cance.patch b/migration-Maybe-VM-is-paused-when-migration-is-cance.patch new file mode 100644 index 0000000000000000000000000000000000000000..6c918f3c17ca619dfb88e1856d3d26625419f465 --- /dev/null +++ b/migration-Maybe-VM-is-paused-when-migration-is-cance.patch @@ -0,0 +1,57 @@ +From 5e99e1329fa52dce8ab784a960e64a3e19b429aa Mon Sep 17 00:00:00 2001 +From: Zhimin Feng +Date: Tue, 14 Jan 2020 17:43:09 +0800 +Subject: [PATCH 07/10] migration: Maybe VM is paused when migration is + cancelled + +If the migration is cancelled when it is in the completion phase, +the migration state is set to MIGRATION_STATUS_CANCELLING. +The VM maybe wait for the 'pause_sem' semaphore in migration_maybe_pause +function, so that VM always is paused. + +Change-Id: Ib2f2f42ee1edbb14da269ee19ba1fe16dd363822 +Reported-by: Euler Robot +Signed-off-by: Zhimin Feng +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +--- + migration/migration.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index bea9b1d7..114c33a1 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2731,14 +2731,22 @@ static int migration_maybe_pause(MigrationState *s, + /* This block intentionally left blank */ + } + +- qemu_mutex_unlock_iothread(); +- migrate_set_state(&s->state, *current_active_state, +- MIGRATION_STATUS_PRE_SWITCHOVER); +- qemu_sem_wait(&s->pause_sem); +- migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER, +- new_state); +- *current_active_state = new_state; +- qemu_mutex_lock_iothread(); ++ /* ++ * If the migration is cancelled when it is in the completion phase, ++ * the migration state is set to MIGRATION_STATUS_CANCELLING. ++ * So we don't need to wait a semaphore, otherwise we would always ++ * wait for the 'pause_sem' semaphore. ++ */ ++ if (s->state != MIGRATION_STATUS_CANCELLING) { ++ qemu_mutex_unlock_iothread(); ++ migrate_set_state(&s->state, *current_active_state, ++ MIGRATION_STATUS_PRE_SWITCHOVER); ++ qemu_sem_wait(&s->pause_sem); ++ migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER, ++ new_state); ++ *current_active_state = new_state; ++ qemu_mutex_lock_iothread(); ++ } + + return s->state == new_state ? 0 : -EINVAL; + } +-- +2.19.1 diff --git a/migration-add-qemu_file_update_transfer-interface.patch b/migration-add-qemu_file_update_transfer-interface.patch new file mode 100644 index 0000000000000000000000000000000000000000..4222fd0adb202051cd57a3f0cab01e5ad52f8248 --- /dev/null +++ b/migration-add-qemu_file_update_transfer-interface.patch @@ -0,0 +1,50 @@ +From 7572495245a437da717e6829a9ce852cc3f229c9 Mon Sep 17 00:00:00 2001 +From: Zheng Chuan +Date: Mon, 20 Apr 2020 15:13:47 +0800 +Subject: [PATCH 02/10] migration: add qemu_file_update_transfer interface + +Add qemu_file_update_transfer for just update bytes_xfer for speed +limitation. This will be used for further migration feature such as +multifd migration. + +Change-Id: I969aa15305c961254b6fb9805b0ed2d65826cc5d +Signed-off-by: Ivan Ren +Reviewed-by: Wei Yang +Reviewed-by: Juan Quintela +Message-Id: <1564464816-21804-2-git-send-email-ivanren@tencent.com> +Signed-off-by: Dr. David Alan Gilbert +--- + migration/qemu-file.c | 5 +++++ + migration/qemu-file.h | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/migration/qemu-file.c b/migration/qemu-file.c +index 04315855..18f48052 100644 +--- a/migration/qemu-file.c ++++ b/migration/qemu-file.c +@@ -615,6 +615,11 @@ void qemu_file_reset_rate_limit(QEMUFile *f) + f->bytes_xfer = 0; + } + ++void qemu_file_update_transfer(QEMUFile *f, int64_t len) ++{ ++ f->bytes_xfer += len; ++} ++ + void qemu_put_be16(QEMUFile *f, unsigned int v) + { + qemu_put_byte(f, v >> 8); +diff --git a/migration/qemu-file.h b/migration/qemu-file.h +index 13baf896..5de9fa2e 100644 +--- a/migration/qemu-file.h ++++ b/migration/qemu-file.h +@@ -147,6 +147,7 @@ int qemu_peek_byte(QEMUFile *f, int offset); + void qemu_file_skip(QEMUFile *f, int size); + void qemu_update_position(QEMUFile *f, size_t size); + void qemu_file_reset_rate_limit(QEMUFile *f); ++void qemu_file_update_transfer(QEMUFile *f, int64_t len); + void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); + int64_t qemu_file_get_rate_limit(QEMUFile *f); + void qemu_file_set_error(QEMUFile *f, int ret); +-- +2.19.1 diff --git a/migration-add-speed-limit-for-multifd-migration.patch b/migration-add-speed-limit-for-multifd-migration.patch new file mode 100644 index 0000000000000000000000000000000000000000..690d9c9cf095cafdb2ff18025d70ee57a2527de2 --- /dev/null +++ b/migration-add-speed-limit-for-multifd-migration.patch @@ -0,0 +1,127 @@ +From bc5780480db9e38699df0b4697e60a9f36258dc4 Mon Sep 17 00:00:00 2001 +From: Ivan Ren +Date: Tue, 30 Jul 2019 13:33:35 +0800 +Subject: [PATCH 03/10] migration: add speed limit for multifd migration + +Limit the speed of multifd migration through common speed limitation +qemu file. + +Change-Id: Id2abfc7ea85679bd53130a43043cc70179a52e87 +Signed-off-by: Ivan Ren +Message-Id: <1564464816-21804-3-git-send-email-ivanren@tencent.com> +Reviewed-by: Wei Yang +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/ram.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 889148dd..88ddd2bb 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -922,7 +922,7 @@ struct { + * false. + */ + +-static int multifd_send_pages(void) ++static int multifd_send_pages(RAMState *rs) + { + int i; + static int next_channel; +@@ -954,6 +954,7 @@ static int multifd_send_pages(void) + multifd_send_state->pages = p->pages; + p->pages = pages; + transferred = ((uint64_t) pages->used) * TARGET_PAGE_SIZE + p->packet_len; ++ qemu_file_update_transfer(rs->f, transferred); + ram_counters.multifd_bytes += transferred; + ram_counters.transferred += transferred;; + qemu_mutex_unlock(&p->mutex); +@@ -962,7 +963,7 @@ static int multifd_send_pages(void) + return 1; + } + +-static int multifd_queue_page(RAMBlock *block, ram_addr_t offset) ++static int multifd_queue_page(RAMState *rs, RAMBlock *block, ram_addr_t offset) + { + MultiFDPages_t *pages = multifd_send_state->pages; + +@@ -981,12 +982,12 @@ static int multifd_queue_page(RAMBlock *block, ram_addr_t offset) + } + } + +- if (multifd_send_pages() < 0) { ++ if (multifd_send_pages(rs) < 0) { + return -1; + } + + if (pages->block != block) { +- return multifd_queue_page(block, offset); ++ return multifd_queue_page(rs, block, offset); + } + + return 1; +@@ -1054,7 +1055,7 @@ void multifd_save_cleanup(void) + multifd_send_state = NULL; + } + +-static void multifd_send_sync_main(void) ++static void multifd_send_sync_main(RAMState *rs) + { + int i; + +@@ -1062,7 +1063,7 @@ static void multifd_send_sync_main(void) + return; + } + if (multifd_send_state->pages->used) { +- if (multifd_send_pages() < 0) { ++ if (multifd_send_pages(rs) < 0) { + error_report("%s: multifd_send_pages fail", __func__); + return; + } +@@ -1083,6 +1084,7 @@ static void multifd_send_sync_main(void) + p->packet_num = multifd_send_state->packet_num++; + p->flags |= MULTIFD_FLAG_SYNC; + p->pending_job++; ++ qemu_file_update_transfer(rs->f, p->packet_len); + qemu_mutex_unlock(&p->mutex); + qemu_sem_post(&p->sem); + } +@@ -2079,7 +2081,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage) + static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, + ram_addr_t offset) + { +- if (multifd_queue_page(block, offset) < 0) { ++ if (multifd_queue_page(rs, block, offset) < 0) { + return -1; + } + ram_counters.normal++; +@@ -3482,7 +3484,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) + ram_control_before_iterate(f, RAM_CONTROL_SETUP); + ram_control_after_iterate(f, RAM_CONTROL_SETUP); + +- multifd_send_sync_main(); ++ multifd_send_sync_main(*rsp); + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + +@@ -3570,7 +3572,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) + ram_control_after_iterate(f, RAM_CONTROL_ROUND); + + out: +- multifd_send_sync_main(); ++ multifd_send_sync_main(rs); + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + ram_counters.transferred += 8; +@@ -3629,7 +3631,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque) + + rcu_read_unlock(); + +- multifd_send_sync_main(); ++ multifd_send_sync_main(rs); + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + +-- +2.19.1 diff --git a/migration-always-initialise-ram_counters-for-a-new-m.patch b/migration-always-initialise-ram_counters-for-a-new-m.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccd0db9ab87204ca41e17c1120618748eb4383fe --- /dev/null +++ b/migration-always-initialise-ram_counters-for-a-new-m.patch @@ -0,0 +1,125 @@ +From af2aa4f553565ae6b2248204c154748f38ec4746 Mon Sep 17 00:00:00 2001 +From: Ivan Ren +Date: Fri, 2 Aug 2019 18:18:41 +0800 +Subject: [PATCH 01/10] migration: always initialise ram_counters for a new + migration + +This patch fix a multifd migration bug in migration speed calculation, this +problem can be reproduced as follows: +1. start a vm and give a heavy memory write stress to prevent the vm be + successfully migrated to destination +2. begin a migration with multifd +3. migrate for a long time [actually, this can be measured by transferred bytes] +4. migrate cancel +5. begin a new migration with multifd, the migration will directly run into + migration_completion phase + +Reason as follows: + +Migration update bandwidth and s->threshold_size in function +migration_update_counters after BUFFER_DELAY time: + + current_bytes = migration_total_bytes(s); + transferred = current_bytes - s->iteration_initial_bytes; + time_spent = current_time - s->iteration_start_time; + bandwidth = (double)transferred / time_spent; + s->threshold_size = bandwidth * s->parameters.downtime_limit; + +In multifd migration, migration_total_bytes function return +qemu_ftell(s->to_dst_file) + ram_counters.multifd_bytes. +s->iteration_initial_bytes will be initialized to 0 at every new migration, +but ram_counters is a global variable, and history migration data will be +accumulated. So if the ram_counters.multifd_bytes is big enough, it may lead +pending_size >= s->threshold_size become false in migration_iteration_run +after the first migration_update_counters. + +Change-Id: Ib153d8676a5b82650bfb1156060e09f0d29f3ac6 +Signed-off-by: Ivan Ren +Reviewed-by: Juan Quintela +Reviewed-by: Wei Yang +Suggested-by: Wei Yang +Message-Id: <1564741121-1840-1-git-send-email-ivanren@tencent.com> +Signed-off-by: Dr. David Alan Gilbert +--- + migration/migration.c | 25 +++++++++++++++++++------ + migration/savevm.c | 1 + + 2 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 8a607fe1..bea9b1d7 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1908,6 +1908,11 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, + } + + migrate_init(s); ++ /* ++ * set ram_counters memory to zero for a ++ * new migration ++ */ ++ memset(&ram_counters, 0, sizeof(ram_counters)); + + return true; + } +@@ -3025,6 +3030,17 @@ static void migration_calculate_complete(MigrationState *s) + } + } + ++static void update_iteration_initial_status(MigrationState *s) ++{ ++ /* ++ * Update these three fields at the same time to avoid mismatch info lead ++ * wrong speed calculation. ++ */ ++ s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ++ s->iteration_initial_bytes = migration_total_bytes(s); ++ s->iteration_initial_pages = ram_get_total_transferred_pages(); ++} ++ + static void migration_update_counters(MigrationState *s, + int64_t current_time) + { +@@ -3060,9 +3076,7 @@ static void migration_update_counters(MigrationState *s, + + qemu_file_reset_rate_limit(s->to_dst_file); + +- s->iteration_start_time = current_time; +- s->iteration_initial_bytes = current_bytes; +- s->iteration_initial_pages = ram_get_total_transferred_pages(); ++ update_iteration_initial_status(s); + + trace_migrate_transferred(transferred, time_spent, + bandwidth, s->threshold_size); +@@ -3186,7 +3200,7 @@ static void *migration_thread(void *opaque) + rcu_register_thread(); + + object_ref(OBJECT(s)); +- s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ++ update_iteration_initial_status(s); + + qemu_savevm_state_header(s->to_dst_file); + +@@ -3251,8 +3265,7 @@ static void *migration_thread(void *opaque) + * the local variables. This is important to avoid + * breaking transferred_bytes and bandwidth calculation + */ +- s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); +- s->iteration_initial_bytes = 0; ++ update_iteration_initial_status(s); + } + + current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); +diff --git a/migration/savevm.c b/migration/savevm.c +index 79ed44d4..480c511b 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -1424,6 +1424,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) + } + + migrate_init(ms); ++ memset(&ram_counters, 0, sizeof(ram_counters)); + ms->to_dst_file = f; + + qemu_mutex_unlock_iothread(); +-- +2.19.1 diff --git a/migration-multifd-fix-destroyed-mutex-access-in-term.patch b/migration-multifd-fix-destroyed-mutex-access-in-term.patch new file mode 100644 index 0000000000000000000000000000000000000000..a927ea533c253ff242c5867cde1055453668c1c5 --- /dev/null +++ b/migration-multifd-fix-destroyed-mutex-access-in-term.patch @@ -0,0 +1,64 @@ +From 34d797aa134a33c1d67ca85d9d9f996d58162276 Mon Sep 17 00:00:00 2001 +From: Jiahui Cen +Date: Wed, 23 Oct 2019 11:47:37 +0800 +Subject: [PATCH 09/10] migration/multifd: fix destroyed mutex access in + terminating multifd threads + +One multifd will lock all the other multifds' IOChannel mutex to inform them +to quit by setting p->quit or shutting down p->c. In this senario, if some +multifds had already been terminated and multifd_load_cleanup/multifd_save_cleanup +had destroyed their mutex, it could cause destroyed mutex access when trying +lock their mutex. + +Here is the coredump stack: + #0 0x00007f81a2794437 in raise () from /usr/lib64/libc.so.6 + #1 0x00007f81a2795b28 in abort () from /usr/lib64/libc.so.6 + #2 0x00007f81a278d1b6 in __assert_fail_base () from /usr/lib64/libc.so.6 + #3 0x00007f81a278d262 in __assert_fail () from /usr/lib64/libc.so.6 + #4 0x000055eb1bfadbd3 in qemu_mutex_lock_impl (mutex=0x55eb1e2d1988, file=, line=) at util/qemu-thread-posix.c:64 + #5 0x000055eb1bb4564a in multifd_send_terminate_threads (err=) at migration/ram.c:1015 + #6 0x000055eb1bb4bb7f in multifd_send_thread (opaque=0x55eb1e2d19f8) at migration/ram.c:1171 + #7 0x000055eb1bfad628 in qemu_thread_start (args=0x55eb1e170450) at util/qemu-thread-posix.c:502 + #8 0x00007f81a2b36df5 in start_thread () from /usr/lib64/libpthread.so.0 + #9 0x00007f81a286048d in clone () from /usr/lib64/libc.so.6 + +To fix it up, let's destroy the mutex after all the other multifd threads had +been terminated. + +Change-Id: I4124d43e8558ba302052bdc53fdae7cfcf9d8687 +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +--- + migration/ram.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/migration/ram.c b/migration/ram.c +index 029f1cdf..d7d2d5ec 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1033,6 +1033,10 @@ void multifd_save_cleanup(void) + if (p->running) { + qemu_thread_join(&p->thread); + } ++ } ++ for (i = 0; i < migrate_multifd_channels(); i++) { ++ MultiFDSendParams *p = &multifd_send_state->params[i]; ++ + socket_send_channel_destroy(p->c); + p->c = NULL; + qemu_mutex_destroy(&p->mutex); +@@ -1306,6 +1310,10 @@ int multifd_load_cleanup(Error **errp) + qemu_sem_post(&p->sem_sync); + qemu_thread_join(&p->thread); + } ++ } ++ for (i = 0; i < migrate_multifd_channels(); i++) { ++ MultiFDRecvParams *p = &multifd_recv_state->params[i]; ++ + object_unref(OBJECT(p->c)); + p->c = NULL; + qemu_mutex_destroy(&p->mutex); +-- +2.19.1 diff --git a/migration-multifd-fix-nullptr-access-in-multifd_send.patch b/migration-multifd-fix-nullptr-access-in-multifd_send.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2d278a135434e3b0838be7876b1fe2a616816cd --- /dev/null +++ b/migration-multifd-fix-nullptr-access-in-multifd_send.patch @@ -0,0 +1,62 @@ +From 6a08ee257a95d9f2514bd995e90ddf46d3f78b41 Mon Sep 17 00:00:00 2001 +From: Zheng Chuan +Date: Tue, 21 Apr 2020 19:49:26 +0800 +Subject: [PATCH 10/10] migration/multifd: fix nullptr access in + multifd_send_terminate_threads + +If the multifd_send_threads is not created when migration is failed, +multifd_save_cleanup would be called twice. In this senario, the +multifd_send_state is accessed after it has been released, the result +is that the source VM is crashing down. + +Here is the coredump stack: + Program received signal SIGSEGV, Segmentation fault. + 0x00005629333a78ef in multifd_send_terminate_threads (err=err@entry=0x0) at migration/ram.c:1012 + 1012 MultiFDSendParams *p = &multifd_send_state->params[i]; + #0 0x00005629333a78ef in multifd_send_terminate_threads (err=err@entry=0x0) at migration/ram.c:1012 + #1 0x00005629333ab8a9 in multifd_save_cleanup () at migration/ram.c:1028 + #2 0x00005629333abaea in multifd_new_send_channel_async (task=0x562935450e70, opaque=) at migration/ram.c:1202 + #3 0x000056293373a562 in qio_task_complete (task=task@entry=0x562935450e70) at io/task.c:196 + #4 0x000056293373a6e0 in qio_task_thread_result (opaque=0x562935450e70) at io/task.c:111 + #5 0x00007f475d4d75a7 in g_idle_dispatch () from /usr/lib64/libglib-2.0.so.0 + #6 0x00007f475d4da9a9 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 + #7 0x0000562933785b33 in glib_pollfds_poll () at util/main-loop.c:219 + #8 os_host_main_loop_wait (timeout=) at util/main-loop.c:242 + #9 main_loop_wait (nonblocking=nonblocking@entry=0) at util/main-loop.c:518 + #10 0x00005629334c5acf in main_loop () at vl.c:1810 + #11 0x000056293334d7bb in main (argc=, argv=, envp=) at vl.c:4471 + +If the multifd_send_threads is not created when migration is failed. +In this senario, we don't call multifd_save_cleanup in multifd_new_send_channel_async. + +Change-Id: I7441efe2ed542054ecd2a4da8146e2652824b452 +Signed-off-by: Zhimin Feng +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +--- + migration/ram.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/migration/ram.c b/migration/ram.c +index d7d2d5ec..1858d66c 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1205,7 +1205,15 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) + + if (qio_task_propagate_error(task, &local_err)) { + migrate_set_error(migrate_get_current(), local_err); +- multifd_save_cleanup(); ++ /* Error happen, we need to tell who pay attention to me */ ++ qemu_sem_post(&multifd_send_state->channels_ready); ++ qemu_sem_post(&p->sem_sync); ++ /* ++ * Although multifd_send_thread is not created, but main migration ++ * thread neet to judge whether it is running, so we need to mark ++ * its status. ++ */ ++ p->quit = true; + } else { + p->c = QIO_CHANNEL(sioc); + qio_channel_set_delay(p->c, false); +-- +2.19.1 diff --git a/migration-multifd-fix-nullptr-access-in-terminating-m.patch b/migration-multifd-fix-nullptr-access-in-terminating-m.patch new file mode 100644 index 0000000000000000000000000000000000000000..d403b28f28a708a94d7799618053e53c7d75b939 --- /dev/null +++ b/migration-multifd-fix-nullptr-access-in-terminating-m.patch @@ -0,0 +1,75 @@ +From d9a847f0982fcca6f63031215065c346fcc27bbc Mon Sep 17 00:00:00 2001 +From: Zheng Chuan +Date: Fri, 24 Apr 2020 11:58:33 +0800 +Subject: [PATCH 06/10] migration/multifd: fix nullptr access in terminating + multifd threads + +One multifd channel will shutdown all the other multifd's IOChannel when it +fails to receive an IOChannel. In this senario, if some multifds had not +received its IOChannel yet, it would try to shutdown its IOChannel which could +cause nullptr access at qio_channel_shutdown. + +Here is the coredump stack: + #0 object_get_class (obj=obj@entry=0x0) at qom/object.c:908 + #1 0x00005563fdbb8f4a in qio_channel_shutdown (ioc=0x0, how=QIO_CHANNEL_SHUTDOWN_BOTH, errp=0x0) at io/channel.c:355 + #2 0x00005563fd7b4c5f in multifd_recv_terminate_threads (err=) at migration/ram.c:1280 + #3 0x00005563fd7bc019 in multifd_recv_new_channel (ioc=ioc@entry=0x556400255610, errp=errp@entry=0x7ffec07dce00) at migration/ram.c:1478 + #4 0x00005563fda82177 in migration_ioc_process_incoming (ioc=ioc@entry=0x556400255610, errp=errp@entry=0x7ffec07dce30) at migration/migration.c:605 + #5 0x00005563fda8567d in migration_channel_process_incoming (ioc=0x556400255610) at migration/channel.c:44 + #6 0x00005563fda83ee0 in socket_accept_incoming_migration (listener=0x5563fff6b920, cioc=0x556400255610, opaque=) at migration/socket +.c:166 + #7 0x00005563fdbc25cd in qio_net_listener_channel_func (ioc=, condition=, opaque=) at io/net-listener.c:54 + #8 0x00007f895b6fe9a9 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 + #9 0x00005563fdc18136 in glib_pollfds_poll () at util/main-loop.c:218 + #10 0x00005563fdc181b5 in os_host_main_loop_wait (timeout=1000000000) at util/main-loop.c:241 + #11 0x00005563fdc183a2 in main_loop_wait (nonblocking=nonblocking@entry=0) at util/main-loop.c:517 + #12 0x00005563fd8edb37 in main_loop () at vl.c:1791 + #13 0x00005563fd74fd45 in main (argc=, argv=, envp=) at vl.c:4473 + +To fix it up, let's check p->c before calling qio_channel_shutdown. + +Change-Id: Ib36c1b3d866a3ad92d1460512df840cfb8736ab6 +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +--- + migration/ram.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 51811c2d..756a525f 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1112,6 +1112,7 @@ static void *multifd_send_thread(void *opaque) + rcu_register_thread(); + + if (multifd_send_initial_packet(p, &local_err) < 0) { ++ ret = -1; + goto out; + } + /* initial packet */ +@@ -1178,9 +1179,7 @@ out: + * who pay attention to me. + */ + if (ret != 0) { +- if (flags & MULTIFD_FLAG_SYNC) { +- qemu_sem_post(&p->sem_sync); +- } ++ qemu_sem_post(&p->sem_sync); + qemu_sem_post(&multifd_send_state->channels_ready); + } + +@@ -1279,7 +1278,9 @@ static void multifd_recv_terminate_threads(Error *err) + - normal quit, i.e. everything went fine, just finished + - error quit: We close the channels so the channel threads + finish the qio_channel_read_all_eof() */ +- qio_channel_shutdown(p->c, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); ++ if (p->c) { ++ qio_channel_shutdown(p->c, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); ++ } + qemu_mutex_unlock(&p->mutex); + } + } +-- +2.19.1 diff --git a/migration-multifd-fix-potential-wrong-acception-orde.patch b/migration-multifd-fix-potential-wrong-acception-orde.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5502038c8f9e1b555dd0e421b58b277f94b0bef --- /dev/null +++ b/migration-multifd-fix-potential-wrong-acception-orde.patch @@ -0,0 +1,294 @@ +From 71f3e496c128b46f803cc4776154b02a5e505cb2 Mon Sep 17 00:00:00 2001 +From: Zheng Chuan +Date: Wed, 22 Apr 2020 13:45:39 +0800 +Subject: [PATCH] migration/multifd: fix potential wrong acception order of + IOChannel + +Multifd assumes the migration thread IOChannel is always established before +the multifd IOChannels, but this assumption will be broken in many situations +like network packet loss. + +For example: +Step1: Source (migration thread IOChannel) --SYN--> Destination +Step2: Source (migration thread IOChannel) <--SYNACK Destination +Step3: Source (migration thread IOChannel, lost) --ACK-->X Destination +Step4: Source (multifd IOChannel) --SYN--> Destination +Step5: Source (multifd IOChannel) <--SYNACK Destination +Step6: Source (multifd IOChannel, ESTABLISHED) --ACK--> Destination +Step7: Destination accepts multifd IOChannel +Step8: Source (migration thread IOChannel, ESTABLISHED) -ACK,DATA-> Destination +Step9: Destination accepts migration thread IOChannel + +The above situation can be reproduced by creating a weak network environment, +such as "tc qdisc add dev eth0 root netem loss 50%". The wrong acception order +will cause magic check failure and thus lead to migration failure. + +This patch fixes this issue by sending a migration IOChannel initial packet with +a unique id when using multifd migration. Since the multifd IOChannels will also +send initial packets, the destination can judge whether the processing IOChannel +belongs to multifd by checking the id in the initial packet. This mechanism can +ensure that different IOChannels will go to correct branches in our test. + +Change-Id: I63d1c32c7b66063bd6a3c5e7d63500555bd148b9 +Signed-off-by: Jiahui Cen +Signed-off-by: Ying Fang + +diff --git a/migration/channel.c b/migration/channel.c +index 20e4c8e2..74621814 100644 +--- a/migration/channel.c ++++ b/migration/channel.c +@@ -82,6 +82,15 @@ void migration_channel_connect(MigrationState *s, + return; + } + } else { ++ if (migrate_use_multifd()) { ++ /* multifd migration cannot distinguish migration IOChannel ++ * from multifd IOChannels, so we need to send an initial packet ++ * to show it is migration IOChannel ++ */ ++ migration_send_initial_packet(ioc, ++ migrate_multifd_channels(), ++ &error); ++ } + QEMUFile *f = qemu_fopen_channel_output(ioc); + + qemu_mutex_lock(&s->qemu_file_lock); +diff --git a/migration/migration.c b/migration/migration.c +index 114c33a1..8f2fc2b4 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -517,12 +517,6 @@ static void migration_incoming_setup(QEMUFile *f) + { + MigrationIncomingState *mis = migration_incoming_get_current(); + +- if (multifd_load_setup() != 0) { +- /* We haven't been able to create multifd threads +- nothing better to do */ +- exit(EXIT_FAILURE); +- } +- + if (!mis->from_src_file) { + mis->from_src_file = f; + } +@@ -580,36 +574,41 @@ void migration_fd_process_incoming(QEMUFile *f) + void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) + { + MigrationIncomingState *mis = migration_incoming_get_current(); +- bool start_migration; +- +- if (!mis->from_src_file) { +- /* The first connection (multifd may have multiple) */ +- QEMUFile *f = qemu_fopen_channel_input(ioc); ++ Error *local_err = NULL; ++ int id = 0; + +- /* If it's a recovery, we're done */ +- if (postcopy_try_recover(f)) { +- return; +- } ++ if (migrate_use_multifd()) { ++ id = migration_recv_initial_packet(ioc, &local_err); ++ } ++ if (!migrate_use_multifd() || id == migrate_multifd_channels()) { ++ if (!mis->from_src_file) { ++ /* The migration connection (multifd may have multiple) */ ++ QEMUFile *f = qemu_fopen_channel_input(ioc); + +- migration_incoming_setup(f); ++ /* If it's a recovery, we're done */ ++ if (postcopy_try_recover(f)) { ++ return; ++ } + +- /* +- * Common migration only needs one channel, so we can start +- * right now. Multifd needs more than one channel, we wait. +- */ +- start_migration = !migrate_use_multifd(); +- } else { +- Error *local_err = NULL; ++ migration_incoming_setup(f); ++ } ++ } else if (id >= 0) { + /* Multiple connections */ + assert(migrate_use_multifd()); +- start_migration = multifd_recv_new_channel(ioc, &local_err); ++ multifd_recv_new_channel(ioc, id, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } ++ } else { ++ /* Bad connections */ ++ multifd_recv_terminate_threads(local_err); ++ error_propagate(errp, local_err); ++ return; + } + +- if (start_migration) { ++ /* Once we have all the channels we need, we can start migration */ ++ if (migration_has_all_channels()) { + migration_incoming_process(); + } + } +diff --git a/migration/migration.h b/migration/migration.h +index 1fdd7b21..feb34430 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -339,4 +339,7 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); + void migration_make_urgent_request(void); + void migration_consume_urgent_request(void); + ++int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp); ++int migration_recv_initial_packet(QIOChannel *c, Error **errp); ++ + #endif +diff --git a/migration/ram.c b/migration/ram.c +index 756a525f..029f1cdf 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -593,7 +593,7 @@ typedef struct { + uint8_t id; + uint8_t unused1[7]; /* Reserved for future use */ + uint64_t unused2[4]; /* Reserved for future use */ +-} __attribute__((packed)) MultiFDInit_t; ++} __attribute__((packed)) MigrationInit_t; + + typedef struct { + uint32_t magic; +@@ -702,26 +702,26 @@ typedef struct { + QemuSemaphore sem_sync; + } MultiFDRecvParams; + +-static int multifd_send_initial_packet(MultiFDSendParams *p, Error **errp) ++int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp) + { +- MultiFDInit_t msg; ++ MigrationInit_t msg; + int ret; + + msg.magic = cpu_to_be32(MULTIFD_MAGIC); + msg.version = cpu_to_be32(MULTIFD_VERSION); +- msg.id = p->id; ++ msg.id = id; + memcpy(msg.uuid, &qemu_uuid.data, sizeof(msg.uuid)); + +- ret = qio_channel_write_all(p->c, (char *)&msg, sizeof(msg), errp); ++ ret = qio_channel_write_all(c, (char *)&msg, sizeof(msg), errp); + if (ret != 0) { + return -1; + } + return 0; + } + +-static int multifd_recv_initial_packet(QIOChannel *c, Error **errp) ++int migration_recv_initial_packet(QIOChannel *c, Error **errp) + { +- MultiFDInit_t msg; ++ MigrationInit_t msg; + int ret; + + ret = qio_channel_read_all(c, (char *)&msg, sizeof(msg), errp); +@@ -756,8 +756,8 @@ static int multifd_recv_initial_packet(QIOChannel *c, Error **errp) + } + + if (msg.id > migrate_multifd_channels()) { +- error_setg(errp, "multifd: received channel version %d " +- "expected %d", msg.version, MULTIFD_VERSION); ++ error_setg(errp, "multifd: received channel id %d " ++ "expected [0-%d]", msg.id, migrate_multifd_channels()); + return -1; + } + +@@ -1111,7 +1111,7 @@ static void *multifd_send_thread(void *opaque) + trace_multifd_send_thread_start(p->id); + rcu_register_thread(); + +- if (multifd_send_initial_packet(p, &local_err) < 0) { ++ if (migration_send_initial_packet(p->c, p->id, &local_err) < 0) { + ret = -1; + goto out; + } +@@ -1255,7 +1255,7 @@ struct { + uint64_t packet_num; + } *multifd_recv_state; + +-static void multifd_recv_terminate_threads(Error *err) ++void multifd_recv_terminate_threads(Error *err) + { + int i; + +@@ -1470,21 +1470,10 @@ bool multifd_recv_all_channels_created(void) + * - Return false and do not set @errp when correctly receiving the current one; + * - Return false and set @errp when failing to receive the current channel. + */ +-bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) ++void multifd_recv_new_channel(QIOChannel *ioc, int id, Error **errp) + { + MultiFDRecvParams *p; + Error *local_err = NULL; +- int id; +- +- id = multifd_recv_initial_packet(ioc, &local_err); +- if (id < 0) { +- multifd_recv_terminate_threads(local_err); +- error_propagate_prepend(errp, local_err, +- "failed to receive packet" +- " via multifd channel %d: ", +- atomic_read(&multifd_recv_state->count)); +- return false; +- } + + p = &multifd_recv_state->params[id]; + if (p->c != NULL) { +@@ -1492,7 +1481,7 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) + id); + multifd_recv_terminate_threads(local_err); + error_propagate(errp, local_err); +- return false; ++ return; + } + p->c = ioc; + object_ref(OBJECT(ioc)); +@@ -1503,8 +1492,6 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) + qemu_thread_create(&p->thread, p->name, multifd_recv_thread, p, + QEMU_THREAD_JOINABLE); + atomic_inc(&multifd_recv_state->count); +- return atomic_read(&multifd_recv_state->count) == +- migrate_multifd_channels(); + } + + /** +diff --git a/migration/ram.h b/migration/ram.h +index bd0eee79..a788ff0e 100644 +--- a/migration/ram.h ++++ b/migration/ram.h +@@ -46,7 +46,8 @@ void multifd_save_cleanup(void); + int multifd_load_setup(void); + int multifd_load_cleanup(Error **errp); + bool multifd_recv_all_channels_created(void); +-bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp); ++void multifd_recv_new_channel(QIOChannel *ioc, int id, Error **errp); ++void multifd_recv_terminate_threads(Error *err); + + uint64_t ram_pagesize_summary(void); + int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); +diff --git a/migration/socket.c b/migration/socket.c +index 98efdc02..bc0960c6 100644 +--- a/migration/socket.c ++++ b/migration/socket.c +@@ -181,6 +181,12 @@ static void socket_start_incoming_migration(SocketAddress *saddr, + + qio_net_listener_set_name(listener, "migration-socket-listener"); + ++ if (multifd_load_setup() != 0) { ++ /* We haven't been able to create multifd threads ++ nothing better to do */ ++ exit(EXIT_FAILURE); ++ } ++ + if (qio_net_listener_open_sync(listener, saddr, errp) < 0) { + object_unref(OBJECT(listener)); + return; +-- +2.23.0 diff --git a/migration-ram-Do-error_free-after-migrate_set_error-.patch b/migration-ram-Do-error_free-after-migrate_set_error-.patch new file mode 100644 index 0000000000000000000000000000000000000000..0039f43d86d5506bfca2953904a215d3f178526a --- /dev/null +++ b/migration-ram-Do-error_free-after-migrate_set_error-.patch @@ -0,0 +1,69 @@ +From 05d1fbd2390d441e5acb606dba3d308d506a8eb1 Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Tue, 5 May 2020 11:44:20 +0800 +Subject: [PATCH 1/3] migration/ram: Do error_free after migrate_set_error to + avoid memleaks + +If local_err is not NULL, it use error_copy to set migrate error in +multifd_send_terminate_threads. Thus, we should free it. + +Similarly, fix another leak in multifd_recv_thread. + +The leak stack: +Direct leak of 96 byte(s) in 2 object(s) allocated from: + #0 0xfffdd97fe938 in __interceptor_calloc (/lib64/libasan.so.4+0xee938) + #1 0xfffdd85a8bb0 in g_malloc0 (/lib64/libglib-2.0.so.0+0x58bb0) + #2 0xaaadfc6e41c4 in error_setv util/error.c:61 + #3 0xaaadfc6e4880 in error_setg_errno_internal util/error.c:109 + #4 0xaaadfc6192a8 in qio_channel_socket_writev io/channel-socket.c:552 + #5 0xaaadfc614604 in qio_channel_writev_all io/channel.c:171 + #6 0xaaadfc6147ec in qio_channel_write_all io/channel.c:257 + #7 0xaaadfbaec5fc in multifd_send_thread /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1145 + #8 0xaaadfc6db768 in qemu_thread_start util/qemu-thread-posix.c:502 + #9 0xfffdd79a88c8 (/lib64/libpthread.so.0+0x88c8) + #10 0xfffdd78e9578 (/lib64/libc.so.6+0xd9578) + +Indirect leak of 104 byte(s) in 2 object(s) allocated from: + #0 0xfffdd97feb40 in realloc (/lib64/libasan.so.4+0xeeb40) + #1 0xfffdd78fa6e0 in __vasprintf_chk (/lib64/libc.so.6+0xea6e0) + #2 0xfffdd85ee710 in g_vasprintf (/lib64/libglib-2.0.so.0+0x9e710) + #3 0xfffdd85c45c4 in g_strdup_vprintf (/lib64/libglib-2.0.so.0+0x745c4) + #4 0xfffdd85c4674 in g_strdup_printf (/lib64/libglib-2.0.so.0+0x74674) + #5 0xaaadfc6e4214 in error_setv util/error.c:65 + #6 0xaaadfc6e4880 in error_setg_errno_internal util/error.c:109 + #7 0xaaadfc6192a8 in qio_channel_socket_writev io/channel-socket.c:552 + #8 0xaaadfc614604 in qio_channel_writev_all io/channel.c:171 + #9 0xaaadfc6147ec in qio_channel_write_all io/channel.c:257 + #10 0xaaadfbaec5fc in multifd_send_thread /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1145 + #11 0xaaadfc6db768 in qemu_thread_start util/qemu-thread-posix.c:502 + #12 0xfffdd79a88c8 (/lib64/libpthread.so.0+0x88c8) + #13 0xfffdd78e9578 (/lib64/libc.so.6+0xd9578) + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +--- + migration/ram.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/migration/ram.c b/migration/ram.c +index 1858d66c..6baf1412 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1176,6 +1176,7 @@ static void *multifd_send_thread(void *opaque) + out: + if (local_err) { + multifd_send_terminate_threads(local_err); ++ error_free(local_err); + } + + /* +@@ -1427,6 +1428,7 @@ static void *multifd_recv_thread(void *opaque) + + if (local_err) { + multifd_recv_terminate_threads(local_err); ++ error_free(local_err); + } + qemu_mutex_lock(&p->mutex); + p->running = false; +-- +2.23.0 diff --git a/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch b/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch new file mode 100644 index 0000000000000000000000000000000000000000..f9cb2bf652b90968144c673fd6c59655acfd785f --- /dev/null +++ b/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch @@ -0,0 +1,54 @@ +From 4d456b243a41a8e91535b2820fd6ed4f6fb4a194 Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Tue, 5 May 2020 15:50:54 +0800 +Subject: [PATCH 2/3] migration/ram: fix memleaks in + multifd_new_send_channel_async + +When error happen in multifd_new_send_channel_async, 'sioc' will not be used +to create the multifd_send_thread. Let's free it to avoid a memleak. And also +do error_free after migrate_set_error() to avoid another leak in the same place. + +The leak stack: +Direct leak of 2160 byte(s) in 6 object(s) allocated from: + #0 0xfffdd97fe754 in malloc (/lib64/libasan.so.4+0xee754) + #1 0xfffdd85a8b48 in g_malloc (/lib64/libglib-2.0.so.0+0x58b48) + #2 0xaaadfc4e2b10 in object_new_with_type qom/object.c:634 + #3 0xaaadfc619468 in qio_channel_socket_new io/channel-socket.c:56 + #4 0xaaadfc3d3e74 in socket_send_channel_create migration/socket.c:37 + #5 0xaaadfbaed6f4 in multifd_save_setup /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1255 + #6 0xaaadfc3d2f78 in migrate_fd_connect migration/migration.c:3359 + #7 0xaaadfc3d6240 in migration_channel_connect migration/channel.c:101 + #8 0xaaadfc3d3590 in socket_outgoing_migration migration/socket.c:108 + #9 0xaaadfc625a64 in qio_task_complete io/task.c:195 + #10 0xaaadfc625ed0 in qio_task_thread_result io/task.c:111 + #11 0xfffdd859edec (/lib64/libglib-2.0.so.0+0x4edec) + #12 0xfffdd85a2a78 in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x52a78) + #13 0xaaadfc6d3b84 in glib_pollfds_poll util/main-loop.c:218 + #14 0xaaadfc6d3b84 in os_host_main_loop_wait util/main-loop.c:241 + #15 0xaaadfc6d3b84 in main_loop_wait util/main-loop.c:517 + #16 0xaaadfbf9206c in main_loop /usr/src/debug/qemu-4.1.0-4_asan.aarch64/vl.c:1791 + #17 0xaaadfba1b124 in main /usr/src/debug/qemu-4.1.0-4_asan.aarch64/vl.c:4473 + #18 0xfffdd7833f5c in __libc_start_main (/lib64/libc.so.6+0x23f5c) + #19 0xaaadfba26360 (/usr/libexec/qemu-kvm+0x886360) + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +--- + migration/ram.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/migration/ram.c b/migration/ram.c +index 6baf1412..840e3548 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1215,6 +1215,8 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) + * its status. + */ + p->quit = true; ++ object_unref(OBJECT(sioc)); ++ error_free(local_err); + } else { + p->c = QIO_CHANNEL(sioc); + qio_channel_set_delay(p->c, false); +-- +2.23.0 diff --git a/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch b/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e0fb101d827377551a7858f225cf365367e12b7 --- /dev/null +++ b/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch @@ -0,0 +1,43 @@ +From 8ae2e3b8be812bcbdeb6151c685026bcaedd4a4b Mon Sep 17 00:00:00 2001 +From: Pan Nengyuan +Date: Sat, 9 May 2020 15:25:42 +0800 +Subject: [PATCH 3/3] migration/rdma: fix a memleak on error path in + rdma_start_incoming_migration + +'rdma->host' is malloced in qemu_rdma_data_init, but forgot to free on the error +path in rdma_start_incoming_migration(), this patch fix that. + +Direct leak of 2 byte(s) in 1 object(s) allocated from: + #0 0xfffce56d34fb in __interceptor_malloc (/lib64/libasan.so.4+0xd34fb) + #1 0xfffce5158aa3 in g_malloc (/lib64/libglib-2.0.so.0+0x58aa3) + #2 0xfffce5174213 in g_strdup (/lib64/libglib-2.0.so.0+0x74213) + #3 0xaaad7c569ddf in qemu_rdma_data_init /Images/qemu/migration/rdma.c:2647 + #4 0xaaad7c57c99f in rdma_start_incoming_migration /Images/qemu/migration/rdma.c:4020 + #5 0xaaad7c52b35f in qemu_start_incoming_migration /Images/qemu/migration/migration.c:371 + #6 0xaaad7be173bf in qemu_init /Images/qemu/softmmu/vl.c:4464 + #7 0xaaad7bb29843 in main /Images/qemu/softmmu/main.c:48 + #8 0xfffce3713f5f in __libc_start_main (/lib64/libc.so.6+0x23f5f) + #9 0xaaad7bb2bf73 (/Images/qemu/build/aarch64-softmmu/qemu-system-aarch64+0x8fbf73) + +Reported-by: Euler Robot +Signed-off-by: Pan Nengyuan +--- + migration/rdma.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/migration/rdma.c b/migration/rdma.c +index 3036221e..b5fdb6a7 100644 +--- a/migration/rdma.c ++++ b/migration/rdma.c +@@ -4068,6 +4068,9 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp) + return; + err: + error_propagate(errp, local_err); ++ if (rdma) { ++ g_free(rdma->host); ++ } + g_free(rdma); + g_free(rdma_return_path); + } +-- +2.23.0 diff --git a/migration-update-ram_counters-for-multifd-sync-packe.patch b/migration-update-ram_counters-for-multifd-sync-packe.patch new file mode 100644 index 0000000000000000000000000000000000000000..838380403f1ac31df0f2befd62a14711cee71e58 --- /dev/null +++ b/migration-update-ram_counters-for-multifd-sync-packe.patch @@ -0,0 +1,35 @@ +From e93040851d683f1f7750acfa0e862b4405678f24 Mon Sep 17 00:00:00 2001 +From: Zheng Chuan +Date: Fri, 24 Apr 2020 11:50:41 +0800 +Subject: [PATCH 04/10] migration: update ram_counters for multifd sync packet + +Multifd sync will send MULTIFD_FLAG_SYNC flag info to destination, add +these bytes to ram_counters record. + +Change-Id: I885166f412f58e74de40ea6ffec1c35e82ae4619 +Signed-off-by: Ivan Ren +Suggested-by: Wei Yang +Message-Id: <1564464816-21804-4-git-send-email-ivanren@tencent.com> +Reviewed-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +--- + migration/ram.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/migration/ram.c b/migration/ram.c +index 88ddd2bb..c75716bb 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1085,6 +1085,10 @@ static void multifd_send_sync_main(RAMState *rs) + p->flags |= MULTIFD_FLAG_SYNC; + p->pending_job++; + qemu_file_update_transfer(rs->f, p->packet_len); ++ ram_counters.multifd_bytes += p->packet_len; ++ ram_counters.transferred += p->packet_len; ++ ram_counters.multifd_bytes += p->packet_len; ++ ram_counters.transferred += p->packet_len; + qemu_mutex_unlock(&p->mutex); + qemu_sem_post(&p->sem); + } +-- +2.19.1 diff --git a/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch b/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch new file mode 100644 index 0000000000000000000000000000000000000000..52f07f951aef929e9fe58740955f97af25e5ba85 --- /dev/null +++ b/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch @@ -0,0 +1,52 @@ +From e092a17d3825a8f2c93cb429aaa5d857b579b64c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 22 Jul 2019 17:44:27 +0200 +Subject: [PATCH] mirror: Keep mirror_top_bs drained after dropping permissions + +mirror_top_bs is currently implicitly drained through its connection to +the source or the target node. However, the drain section for target_bs +ends early after moving mirror_top_bs from src to target_bs, so that +requests can already be restarted while mirror_top_bs is still present +in the chain, but has dropped all permissions and therefore runs into an +assertion failure like this: + + qemu-system-x86_64: block/io.c:1634: bdrv_co_write_req_prepare: + Assertion `child->perm & BLK_PERM_WRITE' failed. + +Keep mirror_top_bs drained until all graph changes have completed. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +(cherry picked from commit d2da5e288a2e71e82866c8fdefd41b5727300124) +Signed-off-by: Michael Roth +--- + block/mirror.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/mirror.c b/block/mirror.c +index 0e3f7923cf..681b305de6 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -661,7 +661,10 @@ static int mirror_exit_common(Job *job) + s->target = NULL; + + /* We don't access the source any more. Dropping any WRITE/RESIZE is +- * required before it could become a backing file of target_bs. */ ++ * required before it could become a backing file of target_bs. Not having ++ * these permissions any more means that we can't allow any new requests on ++ * mirror_top_bs from now on, so keep it drained. */ ++ bdrv_drained_begin(mirror_top_bs); + bs_opaque->stop = true; + bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, + &error_abort); +@@ -729,6 +732,7 @@ static int mirror_exit_common(Job *job) + bs_opaque->job = NULL; + + bdrv_drained_end(src); ++ bdrv_drained_end(mirror_top_bs); + s->in_drain = false; + bdrv_unref(mirror_top_bs); + bdrv_unref(src); +-- +2.23.0 diff --git a/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch b/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch index 51f4113b4a67e8c9dfd67d5f21011ee998e04d13..791449b59540fd0d66cac0c367af8436abb55741 100644 --- a/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch +++ b/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch @@ -1,6 +1,6 @@ -From 6f7a7f18f4460b0891eabbe1ca69e599216427b7 Mon Sep 17 00:00:00 2001 +From 117082ef493e62e6e2cd972b309e0cd72682ab02 Mon Sep 17 00:00:00 2001 From: Chen Qun -Date: Mon, 16 Mar 2020 14:26:06 +0800 +Date: Tue, 14 Apr 2020 19:50:59 +0800 Subject: [PATCH] moniter: fix memleak in monitor_fdset_dup_fd_find_remove When remove dup_fd in monitor_fdset_dup_fd_find_remove function, @@ -25,14 +25,14 @@ Reported-by: Euler Robot Signed-off-by: Chen Qun (cherry picked from commit a661614de18c89f58cad3fc1bb8aab44e820183a) --- - monitor.c | 1 + + monitor/misc.c | 1 + 1 file changed, 1 insertion(+) -diff --git a/monitor.c b/monitor.c -index 4807bbe..b5b15b5 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -2596,6 +2596,7 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) +diff --git a/monitor/misc.c b/monitor/misc.c +index 00338c00..0d6369ba 100644 +--- a/monitor/misc.c ++++ b/monitor/misc.c +@@ -1746,6 +1746,7 @@ static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) if (mon_fdset_fd_dup->fd == dup_fd) { if (remove) { QLIST_REMOVE(mon_fdset_fd_dup, next); @@ -40,6 +40,5 @@ index 4807bbe..b5b15b5 100644 if (QLIST_EMPTY(&mon_fdset->dup_fds)) { monitor_fdset_cleanup(mon_fdset); } --- -1.8.3.1 - +-- +2.23.0 diff --git a/nbd-Fix-regression-with-multiple-meta-contexts.patch b/nbd-Fix-regression-with-multiple-meta-contexts.patch deleted file mode 100644 index 432d00e17b5db6106d6644e2544542db762535cc..0000000000000000000000000000000000000000 --- a/nbd-Fix-regression-with-multiple-meta-contexts.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 32c6cb39cbadd6fc2026ff6311fcf58549f71d49 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Wed, 15 Apr 2020 14:29:04 +0800 -Subject: [PATCH] nbd: Fix regression with multiple meta contexts - -Detected by a hang in the libnbd testsuite. If a client requests -multiple meta contexts (both base:allocation and qemu:dirty-bitmap:x) -at the same time, our attempt to silence a false-positive warning -about a potential uninitialized variable introduced botched logic: we -were short-circuiting the second context, and never sending the -NBD_REPLY_FLAG_DONE. Combining two 'if' into one 'if/else' in -bdf200a55 was wrong (I'm a bit embarrassed that such a change was my -initial suggestion after the v1 patch, then I did not review the v2 -patch that actually got committed). Revert that, and instead silence -the false positive warning by replacing 'return ret' with 'return 0' -(the value it always has at that point in the code, even though it -eluded the deduction abilities of the robot that reported the false -positive). - -Fixes: bdf200a5535 -Signed-off-by: Eric Blake -Message-Id: <20200206173832.130004-1-eblake@redhat.com> -Reviewed-by: Laurent Vivier -(cherry picked from commit 73e064ccf09d908febc83761addcc6e76feabf78) ---- - nbd/server.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/nbd/server.c b/nbd/server.c -index aefb07d..3630352 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -2304,15 +2304,22 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, - !client->export_meta.bitmap, - NBD_META_ID_BASE_ALLOCATION, - errp); -- } else { /* client->export_meta.bitmap */ -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ if (client->export_meta.bitmap) { - ret = nbd_co_send_bitmap(client, request->handle, - client->exp->export_bitmap, - request->from, request->len, - dont_fragment, - true, NBD_META_ID_DIRTY_BITMAP, errp); -+ if (ret < 0) { -+ return ret; -+ } - } - -- return ret; -+ return 0; - } else { - return nbd_send_generic_reply(client, request->handle, -EINVAL, - "CMD_BLOCK_STATUS not negotiated", --- -1.8.3.1 - diff --git a/pc-Don-t-make-die-id-mandatory-unless-necessary.patch b/pc-Don-t-make-die-id-mandatory-unless-necessary.patch new file mode 100644 index 0000000000000000000000000000000000000000..c51b40f33020e36547f44b895b040acc07bf741c --- /dev/null +++ b/pc-Don-t-make-die-id-mandatory-unless-necessary.patch @@ -0,0 +1,102 @@ +From 7ebcd375ade505358c1c45542de22f188c599bdd Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Fri, 16 Aug 2019 14:07:50 -0300 +Subject: [PATCH] pc: Don't make die-id mandatory unless necessary + +We have this issue reported when using libvirt to hotplug CPUs: +https://bugzilla.redhat.com/show_bug.cgi?id=1741451 + +Basically, libvirt is not copying die-id from +query-hotpluggable-cpus, but die-id is now mandatory. + +We could blame libvirt and say it is not following the documented +interface, because we have this buried in the QAPI schema +documentation: + +> Note: currently there are 5 properties that could be present +> but management should be prepared to pass through other +> properties with device_add command to allow for future +> interface extension. This also requires the filed names to be kept in +> sync with the properties passed to -device/device_add. + +But I don't think this would be reasonable from us. We can just +make QEMU more flexible and let die-id to be omitted when there's +no ambiguity. This will allow us to keep compatibility with +existing libvirt versions. + +Test case included to ensure we don't break this again. + +Fixes: commit 176d2cda0dee ("i386/cpu: Consolidate die-id validity in smp context") +Signed-off-by: Eduardo Habkost +Message-Id: <20190816170750.23910-1-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit fea374e7c8079563bca7c8fac895c6a880f76adc) +Signed-off-by: Michael Roth +--- + hw/i386/pc.c | 8 ++++++ + tests/acceptance/pc_cpu_hotplug_props.py | 35 ++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + create mode 100644 tests/acceptance/pc_cpu_hotplug_props.py + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 549c437050..947f81070f 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -2403,6 +2403,14 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, + int max_socket = (ms->smp.max_cpus - 1) / + smp_threads / smp_cores / pcms->smp_dies; + ++ /* ++ * die-id was optional in QEMU 4.0 and older, so keep it optional ++ * if there's only one die per socket. ++ */ ++ if (cpu->die_id < 0 && pcms->smp_dies == 1) { ++ cpu->die_id = 0; ++ } ++ + if (cpu->socket_id < 0) { + error_setg(errp, "CPU socket-id is not set"); + return; +diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py +new file mode 100644 +index 0000000000..08b7e632c6 +--- /dev/null ++++ b/tests/acceptance/pc_cpu_hotplug_props.py +@@ -0,0 +1,35 @@ ++# ++# Ensure CPU die-id can be omitted on -device ++# ++# Copyright (c) 2019 Red Hat Inc ++# ++# Author: ++# Eduardo Habkost ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, see . ++# ++ ++from avocado_qemu import Test ++ ++class OmittedCPUProps(Test): ++ """ ++ :avocado: tags=arch:x86_64 ++ """ ++ def test_no_die_id(self): ++ self.vm.add_args('-nodefaults', '-S') ++ self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') ++ self.vm.add_args('-cpu', 'qemu64') ++ self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') ++ self.vm.launch() ++ self.assertEquals(len(self.vm.command('query-cpus')), 2) +-- +2.23.0 diff --git a/pr-manager-Fix-invalid-g_free-crash-bug.patch b/pr-manager-Fix-invalid-g_free-crash-bug.patch new file mode 100644 index 0000000000000000000000000000000000000000..b171cdb5ae34dab7135926c2250541814d543a02 --- /dev/null +++ b/pr-manager-Fix-invalid-g_free-crash-bug.patch @@ -0,0 +1,39 @@ +From 57fdf4a13ff16d9d48a43f02a5e7b42e3d264f83 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Thu, 22 Aug 2019 15:38:46 +0200 +Subject: [PATCH] pr-manager: Fix invalid g_free() crash bug +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +pr_manager_worker() passes its @opaque argument to g_free(). Wrong; +it points to pr_manager_worker()'s automatic @data. Broken when +commit 2f3a7ab39be converted @data from heap- to stack-allocated. Fix +by deleting the g_free(). + +Fixes: 2f3a7ab39bec4ba8022dc4d42ea641165b004e3e +Cc: qemu-stable@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Paolo Bonzini +Signed-off-by: Kevin Wolf +(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3) +Signed-off-by: Michael Roth +--- + scsi/pr-manager.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c +index ee43663576..0c866e8698 100644 +--- a/scsi/pr-manager.c ++++ b/scsi/pr-manager.c +@@ -39,7 +39,6 @@ static int pr_manager_worker(void *opaque) + int fd = data->fd; + int r; + +- g_free(data); + trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); + + /* The reference was taken in pr_manager_execute. */ +-- +2.23.0 diff --git a/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch b/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2a4e5c26f50c820eb9122e8a8449b76713a8db7 --- /dev/null +++ b/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch @@ -0,0 +1,35 @@ +From 405deba14f6b61b9c557484b46e863308c8cf373 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 28 Oct 2019 17:18:40 +0100 +Subject: [PATCH] qcow2: Fix QCOW2_COMPRESSED_SECTOR_MASK + +Masks for L2 table entries should have 64 bit. + +Fixes: b6c246942b14d3e0dec46a6c5868ed84e7dbea19 +Buglink: https://bugs.launchpad.net/qemu/+bug/1850000 +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20191028161841.1198-2-mreitz@redhat.com +Reviewed-by: Alberto Garcia +Signed-off-by: Max Reitz +(cherry picked from commit 24552feb6ae2f615b76c2b95394af43901f75046) +Signed-off-by: Michael Roth +--- + block/qcow2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/qcow2.h b/block/qcow2.h +index fc1b0d3c1e..359197f89f 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -77,7 +77,7 @@ + + /* Defined in the qcow2 spec (compressed cluster descriptor) */ + #define QCOW2_COMPRESSED_SECTOR_SIZE 512U +-#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1)) ++#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1ULL)) + + /* Must be at least 2 to cover COW */ + #define MIN_L2_CACHE_SIZE 2 /* cache entries */ +-- +2.23.0 diff --git a/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch b/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch new file mode 100644 index 0000000000000000000000000000000000000000..b4c25806d7f7b99408a0419987c22c2175f4fee3 --- /dev/null +++ b/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch @@ -0,0 +1,71 @@ +From 416a692e51b8b582407e30046ddcffbbe52ecf77 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 24 Oct 2019 16:26:58 +0200 +Subject: [PATCH] qcow2: Fix corruption bug in + qcow2_detect_metadata_preallocation() + +qcow2_detect_metadata_preallocation() calls qcow2_get_refcount() which +requires s->lock to be taken to protect its accesses to the refcount +table and refcount blocks. However, nothing in this code path actually +took the lock. This could cause the same cache entry to be used by two +requests at the same time, for different tables at different offsets, +resulting in image corruption. + +As it would be preferable to base the detection on consistent data (even +though it's just heuristics), let's take the lock not only around the +qcow2_get_refcount() calls, but around the whole function. + +This patch takes the lock in qcow2_co_block_status() earlier and asserts +in qcow2_detect_metadata_preallocation() that we hold the lock. + +Fixes: 69f47505ee66afaa513305de0c1895a224e52c45 +Cc: qemu-stable@nongnu.org +Reported-by: Michael Weiser +Signed-off-by: Kevin Wolf +Tested-by: Michael Weiser +Reviewed-by: Michael Weiser +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +(cherry picked from commit 5e9785505210e2477e590e61b1ab100d0ec22b01) +Signed-off-by: Michael Roth +--- + block/qcow2-refcount.c | 2 ++ + block/qcow2.c | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index ef965d7895..0d64bf5a5e 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -3455,6 +3455,8 @@ int qcow2_detect_metadata_preallocation(BlockDriverState *bs) + int64_t i, end_cluster, cluster_count = 0, threshold; + int64_t file_length, real_allocation, real_clusters; + ++ qemu_co_mutex_assert_locked(&s->lock); ++ + file_length = bdrv_getlength(bs->file->bs); + if (file_length < 0) { + return file_length; +diff --git a/block/qcow2.c b/block/qcow2.c +index 865839682c..c0f5439dc8 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1899,6 +1899,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, + unsigned int bytes; + int status = 0; + ++ qemu_co_mutex_lock(&s->lock); ++ + if (!s->metadata_preallocation_checked) { + ret = qcow2_detect_metadata_preallocation(bs); + s->metadata_preallocation = (ret == 1); +@@ -1906,7 +1908,6 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, + } + + bytes = MIN(INT_MAX, count); +- qemu_co_mutex_lock(&s->lock); + ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); + qemu_co_mutex_unlock(&s->lock); + if (ret < 0) { +-- +2.23.0 diff --git a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch new file mode 100644 index 0000000000000000000000000000000000000000..be2c3c72ced8b33f569fabef0c1f01dd382993ef --- /dev/null +++ b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch @@ -0,0 +1,58 @@ +From c9ffb12754b1575babfef45168b6e1b1af80a95f Mon Sep 17 00:00:00 2001 +From: Alberto Garcia +Date: Fri, 16 Aug 2019 15:17:42 +0300 +Subject: [PATCH] qcow2: Fix the calculation of the maximum L2 cache size + +The size of the qcow2 L2 cache defaults to 32 MB, which can be easily +larger than the maximum amount of L2 metadata that the image can have. +For example: with 64 KB clusters the user would need a qcow2 image +with a virtual size of 256 GB in order to have 32 MB of L2 metadata. + +Because of that, since commit b749562d9822d14ef69c9eaa5f85903010b86c30 +we forbid the L2 cache to become larger than the maximum amount of L2 +metadata for the image, calculated using this formula: + + uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); + +The problem with this formula is that the result should be rounded up +to the cluster size because an L2 table on disk always takes one full +cluster. + +For example, a 1280 MB qcow2 image with 64 KB clusters needs exactly +160 KB of L2 metadata, but we need 192 KB on disk (3 clusters) even if +the last 32 KB of those are not going to be used. + +However QEMU rounds the numbers down and only creates 2 cache tables +(128 KB), which is not enough for the image. + +A quick test doing 4KB random writes on a 1280 MB image gives me +around 500 IOPS, while with the correct cache size I get 16K IOPS. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b) +Signed-off-by: Michael Roth +--- + block/qcow2.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 039bdc2f7e..865839682c 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -826,7 +826,11 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts, + bool l2_cache_entry_size_set; + int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; + uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; +- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); ++ uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size); ++ /* An L2 table is always one cluster in size so the max cache size ++ * should be a multiple of the cluster size. */ ++ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t), ++ s->cluster_size); + + combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); + l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE); +-- +2.23.0 diff --git a/qemu-4.0.1.tar.xz b/qemu-4.1.0.tar.xz similarity index 79% rename from qemu-4.0.1.tar.xz rename to qemu-4.1.0.tar.xz index 703a6c2ff7a99ef107bc55570fc0d52b5e79f0a9..79ad0661eda38092de13a677ef70eeaece3ad848 100644 Binary files a/qemu-4.0.1.tar.xz and b/qemu-4.1.0.tar.xz differ diff --git a/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch b/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch deleted file mode 100644 index 8cd599a13bf7a4e4e2b45ab014cd05809051e4f7..0000000000000000000000000000000000000000 --- a/qemu-bridge-helper-move-repeating-code-in-parse_acl.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 3283dde4b5b5cce0f96f48d536bebff66d97ce0b Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 23 Jul 2019 16:17:53 +0530 -Subject: [PATCH 2/2] qemu-bridge-helper: move repeating code in parse_acl_file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Move repeating error handling sequence in parse_acl_file routine -to an 'err' label. - -This patch fixes CVE-2019-13164. - -Signed-off-by: Prasad J Pandit -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Daniel P. Berrangé -Reviewed-by: Li Qiang -Signed-off-by: Jason Wang -(cherry-picked from commit 3283dde4b5b5cce0f96f48d536bebff66d97ce0b) ---- - qemu-bridge-helper.c | 19 +++++++++---------- - 1 file changed, 9 insertions(+), 10 deletions(-) - -diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c -index 2058e10454..3d50ec094c 100644 ---- a/qemu-bridge-helper.c -+++ b/qemu-bridge-helper.c -@@ -102,9 +102,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - - if (arg == NULL) { - fprintf(stderr, "Invalid config line:\n %s\n", line); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - - *arg = 0; -@@ -121,9 +119,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - - if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) { - fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg)); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - - if (strcmp(cmd, "deny") == 0) { -@@ -149,15 +145,18 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - parse_acl_file(arg, acl_list); - } else { - fprintf(stderr, "Unknown command `%s'\n", cmd); -- fclose(f); -- errno = EINVAL; -- return -1; -+ goto err; - } - } - - fclose(f); -- - return 0; -+ -+err: -+ fclose(f); -+ errno = EINVAL; -+ return -1; -+ - } - - static bool has_vnet_hdr(int fd) --- -2.19.1 - diff --git a/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch b/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch deleted file mode 100644 index b6dc25e4dfdc9e204c78c545ad5582c52c07dc26..0000000000000000000000000000000000000000 --- a/qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 6f5d8671225dc77190647f18a27a0d156d4ca97a Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 23 Jul 2019 16:17:52 +0530 -Subject: [PATCH 1/2] qemu-bridge-helper: restrict interface name to IFNAMSIZ -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The network interface name in Linux is defined to be of size -IFNAMSIZ(=16), including the terminating null('\0') byte. -The same is applied to interface names read from 'bridge.conf' -file to form ACL rules. If user supplied '--br=bridge' name -is not restricted to the same length, it could lead to ACL bypass -issue. Restrict interface name to IFNAMSIZ, including null byte. - -This patch fixes CVE-2019-13164. - -Reported-by: Riccardo Schirone -Signed-off-by: Prasad J Pandit -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Daniel P. Berrangé -Reviewed-by: Li Qiang -Signed-off-by: Jason Wang -(cherry-picked from commit 6f5d8671225dc77190647f18a27a0d156d4ca97a) ---- - qemu-bridge-helper.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c -index 95624bc300..2058e10454 100644 ---- a/qemu-bridge-helper.c -+++ b/qemu-bridge-helper.c -@@ -119,6 +119,13 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) - } - *argend = 0; - -+ if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) { -+ fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg)); -+ fclose(f); -+ errno = EINVAL; -+ return -1; -+ } -+ - if (strcmp(cmd, "deny") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); - if (strcmp(arg, "all") == 0) { -@@ -269,6 +276,10 @@ int main(int argc, char **argv) - usage(); - return EXIT_FAILURE; - } -+ if (strlen(bridge) >= IFNAMSIZ) { -+ fprintf(stderr, "name `%s' too long: %zu\n", bridge, strlen(bridge)); -+ return EXIT_FAILURE; -+ } - - /* parse default acl file */ - QSIMPLEQ_INIT(&acl_list); --- -2.19.1 - diff --git a/qemu.spec b/qemu.spec index 41e2cccc8d89ee313206e4f7877988e50afeb2fa..57f1c7344e4d911bf9b197e22f6d52894a403e5e 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu -Version: 4.0.1 -Release: 11 +Version: 4.1.0 +Release: 6 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY @@ -10,61 +10,157 @@ Source1: 80-kvm.rules Source2: 99-qemu-guest-agent.rules Source3: bridge.conf -Patch0001: qxl-check-release-info-object.patch -Patch0002: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch -Patch0003: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch -Patch0004: pl031-support-rtc-timer-property-for-pl031.patch -Patch0005: vhost-cancel-migration-when-vhost-user-restarted.patch -Patch0006: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch -Patch0007: hw-arm-expose-host-CPU-frequency-info-to-guest.patch -Patch0008: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch -Patch0009: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch -Patch0010: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch -Patch0011: hw-arm-virt-Introduce-cpu-topology-support.patch -Patch0012: hw-arm64-add-vcpu-cache-info-support.patch -Patch0013: xhci-Fix-memory-leak-in-xhci_address_slot.patch -Patch0014: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch -Patch0015: ehci-fix-queue-dev-null-ptr-dereference.patch -Patch0016: memory-unref-the-memory-region-in-simplify-flatview.patch -Patch0017: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch -Patch0018: vhost-user-scsi-prevent-using-uninitialized-vqs.patch -Patch0019: cpu-add-Kunpeng-920-cpu-support.patch -Patch0020: cpu-parse-feature-to-avoid-failure.patch -Patch0021: cpu-add-Cortex-A72-processor-kvm-target-support.patch -Patch0022: vnc-fix-memory-leak-when-vnc-disconnect.patch -Patch0023: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch -Patch0024: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch -Patch0025: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch -Patch0026: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch -Patch0027: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch -Patch0028: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch -Patch0029: arm-translate-a64-fix-uninitialized-variable-warning.patch -Patch0030: nbd-fix-uninitialized-variable-warning.patch -Patch0031: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch -Patch0032: block-fix-memleaks-in-bdrv_refresh_filename.patch -Patch0033: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch -Patch0034: tcp_emu-Fix-oob-access.patch -Patch0035: slirp-use-correct-size-while-emulating-IRC-commands.patch -Patch0036: slirp-use-correct-size-while-emulating-commands.patch -Patch0037: tcp_emu-fix-unsafe-snprintf-usages.patch -Patch0038: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch -Patch0039: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch +Patch0001: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch +Patch0002: pl031-support-rtc-timer-property-for-pl031.patch +Patch0003: vhost-cancel-migration-when-vhost-user-restarted.patch +Patch0004: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch +Patch0005: bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch +Patch0006: hw-arm-expose-host-CPU-frequency-info-to-guest.patch +Patch0007: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +Patch0008: tests-bios-tables-test-disable-this-testcase.patch +Patch0009: hw-arm-virt-Introduce-cpu-topology-support.patch +Patch0010: hw-arm64-add-vcpu-cache-info-support.patch +Patch0011: xhci-Fix-memory-leak-in-xhci_address_slot.patch +Patch0012: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch +Patch0013: ehci-fix-queue-dev-null-ptr-dereference.patch +Patch0014: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch +Patch0015: vhost-user-scsi-prevent-using-uninitialized-vqs.patch +Patch0016: cpu-add-Kunpeng-920-cpu-support.patch +Patch0017: cpu-parse-feature-to-avoid-failure.patch +Patch0018: cpu-add-Cortex-A72-processor-kvm-target-support.patch +Patch0019: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch +Patch0020: vnc-fix-memory-leak-when-vnc-disconnect.patch +Patch0021: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch +Patch0022: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch +Patch0023: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch +Patch0024: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch +Patch0025: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch +Patch0026: arm-translate-a64-fix-uninitialized-variable-warning.patch +Patch0027: nbd-fix-uninitialized-variable-warning.patch +Patch0028: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch +Patch0029: block-fix-memleaks-in-bdrv_refresh_filename.patch +Patch0030: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch +Patch0031: tcp_emu-Fix-oob-access.patch +Patch0032: slirp-use-correct-size-while-emulating-IRC-commands.patch +Patch0033: slirp-use-correct-size-while-emulating-commands.patch +Patch0034: util-add-slirp_fmt-helpers.patch +Patch0035: tcp_emu-fix-unsafe-snprintf-usages.patch +Patch0036: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch +Patch0037: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch +Patch0038: memory-Align-MemoryRegionSections-fields.patch +Patch0039: memory-Provide-an-equality-function-for-MemoryRegion.patch Patch0040: vhost-Fix-memory-region-section-comparison.patch -Patch0041: memory-Align-MemoryRegionSections-fields.patch -Patch0042: memory-Provide-an-equality-function-for-MemoryRegion.patch -Patch0043: file-posix-Handle-undetectable-alignment.patch -Patch0044: block-backup-fix-max_transfer-handling-for-copy_rang.patch -Patch0045: block-backup-fix-backup_cow_with_offload-for-last-cl.patch -Patch0046: qcow2-Limit-total-allocation-range-to-INT_MAX.patch -Patch0047: mirror-Do-not-dereference-invalid-pointers.patch -Patch0048: COLO-compare-Fix-incorrect-if-logic.patch -Patch0049: qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch -Patch0050: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch -Patch0051: pcie-Compat-with-devices-which-do-not-support-Link-W.patch -Patch0052: aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch -Patch0053: async-use-explicit-memory-barriers.patch -Patch0054: Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch -Patch0055: nbd-Fix-regression-with-multiple-meta-contexts.patch +Patch0041: file-posix-Handle-undetectable-alignment.patch +Patch0042: block-backup-fix-max_transfer-handling-for-copy_rang.patch +Patch0043: block-backup-fix-backup_cow_with_offload-for-last-cl.patch +Patch0044: qcow2-Limit-total-allocation-range-to-INT_MAX.patch +Patch0045: mirror-Do-not-dereference-invalid-pointers.patch +Patch0046: COLO-compare-Fix-incorrect-if-logic.patch +Patch0047: qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch +Patch0048: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch +Patch0049: pcie-Compat-with-devices-which-do-not-support-Link-W.patch +Patch0050: aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch +Patch0051: async-use-explicit-memory-barriers.patch +Patch0052: dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch +Patch0053: Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch +Patch0054: pc-Don-t-make-die-id-mandatory-unless-necessary.patch +Patch0055: block-file-posix-Reduce-xfsctl-use.patch +Patch0056: pr-manager-Fix-invalid-g_free-crash-bug.patch +Patch0057: x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch +Patch0058: vpc-Return-0-from-vpc_co_create-on-success.patch +Patch0059: target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch +Patch0060: target-arm-Don-t-abort-on-M-profile-exception-return.patch +Patch0061: libvhost-user-fix-SLAVE_SEND_FD-handling.patch +Patch0062: qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch +Patch0063: block-nfs-tear-down-aio-before-nfs_close.patch +Patch0064: blockjob-update-nodes-head-while-removing-all-bdrv.patch +Patch0065: block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch +Patch0066: coroutine-Add-qemu_co_mutex_assert_locked.patch +Patch0067: qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch +Patch0068: hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch +Patch0069: make-release-pull-in-edk2-submodules-so-we-can-build.patch +Patch0070: roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch +Patch0071: block-snapshot-Restrict-set-of-snapshot-nodes.patch +Patch0072: vhost-user-save-features-if-the-char-dev-is-closed.patch +Patch0073: hw-core-loader-Fix-possible-crash-in-rom_copy.patch +Patch0074: ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch +Patch0075: virtio-new-post_load-hook.patch +Patch0076: virtio-net-prevent-offloads-reset-on-migration.patch +Patch0077: util-hbitmap-strict-hbitmap_reset.patch +Patch0078: hbitmap-handle-set-reset-with-zero-length.patch +Patch0079: target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch +Patch0080: scsi-lsi-exit-infinite-loop-while-executing-script-C.patch +Patch0081: virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch +Patch0082: qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch +Patch0083: util-iov-introduce-qemu_iovec_init_extended.patch +Patch0084: util-iov-improve-qemu_iovec_is_zero.patch +Patch0085: block-io-refactor-padding.patch +Patch0086: block-Make-wait-mark-serialising-requests-public.patch +Patch0087: block-Add-bdrv_co_get_self_request.patch +Patch0088: block-file-posix-Let-post-EOF-fallocate-serialize.patch +Patch0089: block-posix-Always-allocate-the-first-block.patch +Patch0090: block-create-Do-not-abort-if-a-block-driver-is-not-a.patch +Patch0091: mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch +Patch0092: target-arm-kvm-trivial-Clean-up-header-documentation.patch +Patch0093: target-arm-kvm64-kvm64-cpus-have-timer-registers.patch +Patch0094: target-arm-kvm-Implement-virtual-time-adjustment.patch +Patch0095: target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch +Patch0096: hw-acpi-Make-ACPI-IO-address-space-configurable.patch +Patch0097: hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch +Patch0098: hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch +Patch0099: hw-arm-virt-Add-memory-hotplug-framework.patch +Patch0100: hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch +Patch0101: hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch +Patch0102: hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch +Patch0103: hw-arm-Use-GED-for-system_powerdown-event.patch +Patch0104: docs-specs-Add-ACPI-GED-documentation.patch +Patch0105: tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch +Patch0106: tests-acpi-add-empty-files.patch +Patch0107: tests-allow-empty-expected-files.patch +Patch0108: tests-Add-bios-tests-to-arm-virt.patch +Patch0109: tests-document-how-to-update-acpi-tables.patch +Patch0110: hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch +Patch0111: bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch +Patch0112: Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch +Patch0113: acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch +Patch0114: acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch +Patch0115: arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch +Patch0116: acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch +Patch0117: acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch +Patch0118: arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch +Patch0119: arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch +Patch0120: arm-virt-Add-CPU-hotplug-framework.patch +Patch0121: arm-virt-Add-CPU-topology-support.patch +Patch0122: test-numa-Adjust-aarch64-numa-test.patch +Patch0123: hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch +Patch0124: hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch +Patch0125: arm-virt-gic-Construct-irqs-connection-from-create_g.patch +Patch0126: intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch +Patch0127: intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch +Patch0128: intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch +Patch0129: hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch +Patch0130: accel-kvm-Add-pre-park-vCPU-support.patch +Patch0131: intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch +Patch0132: acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch +Patch0133: arm-virt-Add-cpu_hotplug_enabled-field.patch +Patch0134: arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch +Patch0135: arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch +Patch0136: arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch +Patch0137: arm-virt-Start-up-CPU-hot-plug.patch +Patch0138: migration-always-initialise-ram_counters-for-a-new-m.patch +Patch0139: migration-add-qemu_file_update_transfer-interface.patch +Patch0140: migration-add-speed-limit-for-multifd-migration.patch +Patch0141: migration-update-ram_counters-for-multifd-sync-packe.patch +Patch0142: migration-Make-global-sem_sync-semaphore-by-channel.patch +Patch0143: migration-multifd-fix-nullptr-access-in-terminating-m.patch +Patch0144: migration-Maybe-VM-is-paused-when-migration-is-cance.patch +Patch0145: migration-multifd-fix-potential-wrong-acception-orde.patch +Patch0146: migration-multifd-fix-destroyed-mutex-access-in-term.patch +Patch0147: migration-multifd-fix-nullptr-access-in-multifd_send.patch +Patch0148: vtimer-compat-cross-version-migration-from-v4.0.1.patch +Patch0149: migration-ram-Do-error_free-after-migrate_set_error-.patch +Patch0150: migration-ram-fix-memleaks-in-multifd_new_send_chann.patch +Patch0151: migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch BuildRequires: flex BuildRequires: bison @@ -251,7 +347,9 @@ install -D -m 0644 %{_sourcedir}/99-qemu-guest-agent.rules %{buildroot}%{_udevdi mkdir -p %{buildroot}%{_localstatedir}/log touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log +# For qemu docs package %global qemudocdir %{_docdir}/%{name} +rm -rf %{buildroot}%{qemudocdir}/specs install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE chmod -x %{buildroot}%{_mandir}/man1/* @@ -266,6 +364,9 @@ rm -rf %{buildroot}%{_datadir}/%{name}/multiboot.bin rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin %endif +%ifarch x86_64 +rm -rf %{buildroot}%{_datadir}/%{name}/vgabios-ati.bin +%endif rm -rf %{buildroot}%{_datadir}/%{name}/openbios-* rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin @@ -281,6 +382,11 @@ rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid rm -rf %{buildroot}%{_datadir}/%{name}/spapr-* rm -rf %{buildroot}%{_datadir}/%{name}/u-boot* rm -rf %{buildroot}%{_bindir}/ivshmem* +rm -f %{buildroot}%{_datadir}/%{name}/edk2* +rm -rf %{buildroot}%{_datadir}/%{name}/firmware +rm -rf %{buildroot}%{_datadir}/%{name}/opensbi* +rm -rf %{buildroot}%{_datadir}/%{name}/qemu-nsis.bmp + for f in %{buildroot}%{_bindir}/* %{buildroot}%{_libdir}/* \ %{buildroot}%{_libexecdir}/*; do @@ -400,99 +506,123 @@ getent passwd qemu >/dev/null || \ %endif %changelog -* Fri Apr 24 2020 backport nbd fix from qemu upstream -- nbd: Fix regression with multiple meta contexts +* Sat May 9 2020 Huawei Technologies Co., Ltd. +- migration/ram: do error_free after migrate_set_error to avoid memleaks. +- migration/ram: fix memleaks in multifd_new_send_channel_async. +- migration/rdma: fix a memleak on error path in rdma_start_incoming_migration. + +* Fri May 8 2020 Huawei Technologies Co., Ltd. +- vtimer: compat cross version migration from v4.0.1 + +* Fri Apr 24 2020 Huawei Technologies Co., Ltd. +- migration: backport migration patches from upstream + +* Fri Apr 24 2020 Huawei Technologies Co., Ltd. +- arm/virt: Add CPU hotplug support + +* Wed Apr 22 2020 Huawei Technologies Co., Ltd. +- backport patch to enable arm/virt memory hotplug + +* Wed Apr 22 2020 Huawei Technologies Co., Ltd. +- backport patch to enable target/arm/kvm Adjust virtual time -* Fri Apr 24 2020 Huawei Technologies Co., Ltd. -- Fix use-afte-free in ip_reass() (CVE-2020-1983) +* Fri Apr 17 2020 Huawei Technologies Co., Ltd. +- backport patch bundles from qemu stable v4.1.1 -* Sat Apr 11 2020 Huawei Technologies Co., Ltd. +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. - aio-wait: delegate polling of main AioContext if BQL not held - async: use explicit memory barriers -* Wed Mar 18 2020 Huawei Technologies Co., Ltd. +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. - pcie: Add pcie-root-port fast plug/unplug feature -- pcie: Compat with devices which do not support Link Width +- pcie: Compat with devices which do not support Link Width, such as ioh3420 -* Tue Mar 17 2020 Huawei Technologies Co., Ltd. -- Put linuxboot_dma.bin and pvh.bin in x86 package +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- qcow2-bitmap: Fix uint64_t left-shift overflow -* Mon Mar 16 2020 backport some bug fix patches from upstream -- Patch from number 0040 to 0049 are picked from stable-4.1.1 +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- COLO-compare: Fix incorrect `if` logic -* Mon Mar 16 2020 Huawei Technologies Co., Ltd. -- moniter: fix memleak in monitor_fdset_dup_fd_find_remove +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- block/backup: fix max_transfer handling for copy_range +- block/backup: fix backup_cow_with_offload for last cluster +- qcow2: Limit total allocation range to INT_MAX +- mirror: Do not dereference invalid pointers + +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- file-posix: Handle undetectable alignment + +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- vhost: Fix memory region section comparison +- memory: Provide an equality function for MemoryRegionSections +- memory: Align MemoryRegionSections fields + +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. - block/iscsi: use MIN() between mx_sb_len and sb_len_wr +- moniter: fix memleak in monitor_fdset_dup_fd_find_remove -* Wed Mar 11 2020 backport from qemu upstream -- tcp_emu: Fix oob access -- slirp: use correct size while emulating IRC commands -- slirp: use correct size while emulating commands +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. - tcp_emu: fix unsafe snprintf() usages - -* Mon Mar 9 2020 backport from qemu upstream +- util: add slirp_fmt() helpers +- slirp: use correct size while emulating commands +- slirp: use correct size while emulating IRC commands +- tcp_emu: Fix oob access - iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711) -* Thu Feb 6 2020 Huawei Technologies Co., Ltd. -- spec: remove fno-inline option for configure - -* Thu Jan 16 2020 Huawei Technologies Co., Ltd. +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- 9pfs: local: Fix possible memory leak in local_link() +- scsi-disk: define props in scsi_block_disk to avoid memleaks +- arm/translate-a64: fix uninitialized variable warning +- block: fix memleaks in bdrv_refresh_filename +- vnc: fix memory leak when vnc disconnect - block: fix memleaks in bdrv_refresh_filename -* Mon Jan 13 2020 Huawei Technologies Co., Ltd. -- 9pfs: Fix a possible memory leak in local_link -- scsi-disk: disk define props in scsi_block to avoid memleaks -- arm/translate-a64: fix uninitialized variable warning -- nbd: fix uninitialized variable warning -- xhci: Fix memory leak in xhci_kick_epctx when poweroff +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- linux headers: update against "KVM/ARM: Fix >256 vcpus" +- intc/arm_gic: Support IRQ injection for more than 256 vcpus +- ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > -* 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 +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- vnc: fix memory leak when vnc disconnect -* Thu Dec 12 2019 backport from qemu upstream v4.0.1 release -- tpm: Exit in reset when backend indicates failure -- tpm_emulator: Translate TPM error codes to strings +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- pcie: disable the PCI_EXP_LINKSTA_DLLA cap for pcie-root-port by default -* Thu Oct 17 2019 backport from qemu upstream -- vnc-fix-memory-leak-when-vnc-disconnect.patch +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- cpu: add Kunpeng-920 cpu support +- cpu: parse +/- feature to avoid failure +- cpu: add Cortex-A72 processor kvm target support -* Mon Sep 9 2019 backport from qemu upstream -- ehci-fix-queue-dev-null-ptr-dereference.patch -- memory-unref-the-memory-region-in-simplify-flatview.patch -- util-async-hold-AioContext-ref-to-prevent-use-after-.patch -- vhost-user-scsi-prevent-using-uninitialized-vqs.patch +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- vhost-user-scsi: prevent using uninitialized vqs -* Fri Aug 30 2019 Huawei Technologies Co., Ltd. +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- util/async: hold AioContext ref to prevent use-after-free + +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. - xhci: Fix memory leak in xhci_address_slot - xhci: Fix memory leak in xhci_kick_epctx +- ehci: fix queue->dev null ptr dereference -* Wed Aug 7 2019 Huawei Technologies Co., Ltd. +* Thu Apr 16 2020 Huawei Technologies Co., Ltd. +- tests/bios-tables-test: disable this testcase - hw/arm/virt: Introduce cpu topology support - hw/arm64: add vcpu cache info support -* Tue Aug 6 2019 Huawei Technologies Co., Ltd. -- Update release version to 4.0.0-2 - -* Mon Aug 5 2019 Huawei Technologies Co., Ltd. -- enable make check +* Wed Apr 15 2020 Huawei Technologies Co., Ltd. - smbios: Add missing member of type 4 for smbios 3.0 -* Mon Aug 5 2019 fix CVE-2019-13164 -- qemu-bridge-helper: restrict interface name to IFNAMSIZ -- qemu-bridge-helper: move repeating code in parse_acl_file +* Wed Apr 15 2020 Huawei Technologies Co., Ltd. +- bios-tables-test: prepare to change ARM virt ACPI DSDT +- arm64: Add the cpufreq device to show cpufreq info to guest -* Tue Jul 30 2019 Huawei Technologies Co., Ltd. - qcow2: fix memory leak in qcow2_read_extensions -- hw/arm: expose host CPU frequency info to guest -* Fri Jul 26 2019 Huawei Technologies Co., Ltd. -- vhost: cancel migration when vhost-user restarted +* Wed Apr 15 2020 Huawei Technologies Co., Ltd. +- pl011: reset read FIFIO when UARTTIMSC=0 & UARTICR=0xff - pl031: support rtc-timer property for pl031 -- pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff -- ARM64: record vtimer tick when cpu is stopped +- vhost: cancel migration when vhost-user restarted -* Tue Jul 23 2019 openEuler Buildteam - version-release +* Mon Apr 13 2020 openEuler Buildteam - version-release - Package init - diff --git a/qxl-check-release-info-object.patch b/qxl-check-release-info-object.patch deleted file mode 100644 index aeddbe467c34aa83a3c7b8bca6b98b44abf546a6..0000000000000000000000000000000000000000 --- a/qxl-check-release-info-object.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cbed4e0108ca1403f1f47cde292330b87a0d8bf2 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Apr 2019 12:05:34 +0530 -Subject: [PATCH] qxl: check release info object - -When releasing spice resources in release_resource() routine, -if release info object 'ext.info' is null, it leads to null -pointer dereference. Add check to avoid it. - -(This is cherry-pick d52680fc932efb8a2f334cc6993e705ed1e31e99) - -Reported-by: Bugs SysSec -Signed-off-by: Prasad J Pandit -Message-id: 20190425063534.32747-1-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann ---- - hw/display/qxl.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/display/qxl.c b/hw/display/qxl.c -index c8ce578..632923a 100644 ---- a/hw/display/qxl.c -+++ b/hw/display/qxl.c -@@ -777,6 +777,9 @@ static void interface_release_resource(QXLInstance *sin, - QXLReleaseRing *ring; - uint64_t *item, id; - -+ if (!ext.info) { -+ return; -+ } - if (ext.group_id == MEMSLOT_GROUP_HOST) { - /* host group -> vga mode update request */ - QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); --- -1.8.3.1 - diff --git a/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch b/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch new file mode 100644 index 0000000000000000000000000000000000000000..00e672662ddd5d848fc031967a0efdcf9dc4432b --- /dev/null +++ b/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch @@ -0,0 +1,54 @@ +From fc5afb1a9230fe21d76bcef527b0d3cee90a2cd3 Mon Sep 17 00:00:00 2001 +From: Michael Roth +Date: Thu, 12 Sep 2019 18:12:02 -0500 +Subject: [PATCH] roms/Makefile.edk2: don't pull in submodules when building + from tarball +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently the `make efi` target pulls submodules nested under the +roms/edk2 submodule as dependencies. However, when we attempt to build +from a tarball this fails since we are no longer in a git tree. + +A preceding patch will pre-populate these submodules in the tarball, +so assume this build dependency is only needed when building from a +git tree. + +Cc: Laszlo Ersek +Cc: Bruce Rogers +Cc: qemu-stable@nongnu.org # v4.1.0 +Reported-by: Bruce Rogers +Reviewed-by: Laszlo Ersek +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Michael Roth +Message-Id: <20190912231202.12327-3-mdroth@linux.vnet.ibm.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit f3e330e3c319160ac04954399b5a10afc965098c) +Signed-off-by: Michael Roth +--- + roms/Makefile.edk2 | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/roms/Makefile.edk2 b/roms/Makefile.edk2 +index c2f2ff59d5..33a074d3a4 100644 +--- a/roms/Makefile.edk2 ++++ b/roms/Makefile.edk2 +@@ -46,8 +46,13 @@ all: $(foreach flashdev,$(flashdevs),../pc-bios/edk2-$(flashdev).fd.bz2) \ + # files. + .INTERMEDIATE: $(foreach flashdev,$(flashdevs),../pc-bios/edk2-$(flashdev).fd) + ++# Fetch edk2 submodule's submodules. If it is not in a git tree, assume ++# we're building from a tarball and that they've already been fetched by ++# make-release/tarball scripts. + submodules: +- cd edk2 && git submodule update --init --force ++ if test -d edk2/.git; then \ ++ cd edk2 && git submodule update --init --force; \ ++ fi + + # See notes on the ".NOTPARALLEL" target and the "+" indicator in + # "tests/uefi-test-tools/Makefile". +-- +2.23.0 diff --git a/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch b/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch new file mode 100644 index 0000000000000000000000000000000000000000..5d20a9f009c9bd52f9eef578344c5b0012ee8942 --- /dev/null +++ b/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch @@ -0,0 +1,104 @@ +From 051c9b3cbcb4beb42a6ed017c2146ec3e7a754fb Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 14 Aug 2019 17:35:21 +0530 +Subject: [PATCH] scsi: lsi: exit infinite loop while executing script + (CVE-2019-12068) + +When executing script in lsi_execute_script(), the LSI scsi adapter +emulator advances 's->dsp' index to read next opcode. This can lead +to an infinite loop if the next opcode is empty. Move the existing +loop exit after 10k iterations so that it covers no-op opcodes as +well. + +Reported-by: Bugs SysSec +Signed-off-by: Paolo Bonzini +Signed-off-by: Prasad J Pandit +Signed-off-by: Paolo Bonzini +(cherry picked from commit de594e47659029316bbf9391efb79da0a1a08e08) +Signed-off-by: Michael Roth +--- + hw/scsi/lsi53c895a.c | 41 +++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 10468c1ec1..72f7b59ab5 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -185,6 +185,9 @@ static const char *names[] = { + /* Flag set if this is a tagged command. */ + #define LSI_TAG_VALID (1 << 16) + ++/* Maximum instructions to process. */ ++#define LSI_MAX_INSN 10000 ++ + typedef struct lsi_request { + SCSIRequest *req; + uint32_t tag; +@@ -1132,7 +1135,21 @@ static void lsi_execute_script(LSIState *s) + + s->istat1 |= LSI_ISTAT1_SRUN; + again: +- insn_processed++; ++ if (++insn_processed > LSI_MAX_INSN) { ++ /* Some windows drivers make the device spin waiting for a memory ++ location to change. If we have been executed a lot of code then ++ assume this is the case and force an unexpected device disconnect. ++ This is apparently sufficient to beat the drivers into submission. ++ */ ++ if (!(s->sien0 & LSI_SIST0_UDC)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "lsi_scsi: inf. loop with UDC masked"); ++ } ++ lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); ++ lsi_disconnect(s); ++ trace_lsi_execute_script_stop(); ++ return; ++ } + insn = read_dword(s, s->dsp); + if (!insn) { + /* If we receive an empty opcode increment the DSP by 4 bytes +@@ -1569,19 +1586,7 @@ again: + } + } + } +- if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) { +- /* Some windows drivers make the device spin waiting for a memory +- location to change. If we have been executed a lot of code then +- assume this is the case and force an unexpected device disconnect. +- This is apparently sufficient to beat the drivers into submission. +- */ +- if (!(s->sien0 & LSI_SIST0_UDC)) { +- qemu_log_mask(LOG_GUEST_ERROR, +- "lsi_scsi: inf. loop with UDC masked"); +- } +- lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); +- lsi_disconnect(s); +- } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) { ++ if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) { + if (s->dcntl & LSI_DCNTL_SSM) { + lsi_script_dma_interrupt(s, LSI_DSTAT_SSI); + } else { +@@ -1969,6 +1974,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) + case 0x2f: /* DSP[24:31] */ + s->dsp &= 0x00ffffff; + s->dsp |= val << 24; ++ /* ++ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one ++ * instruction. Is this correct? ++ */ + if ((s->dmode & LSI_DMODE_MAN) == 0 + && (s->istat1 & LSI_ISTAT1_SRUN) == 0) + lsi_execute_script(s); +@@ -1987,6 +1996,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) + break; + case 0x3b: /* DCNTL */ + s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD); ++ /* ++ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one ++ * instruction. Is this correct? ++ */ + if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0) + lsi_execute_script(s); + break; +-- +2.23.0 diff --git a/slirp-use-correct-size-while-emulating-IRC-commands.patch b/slirp-use-correct-size-while-emulating-IRC-commands.patch index 4503688dd1502c85f7a8e0fee1e5a36bcca838b2..1b4039e1da3c0bcd08b97f4c61983ef3adac3823 100644 --- a/slirp-use-correct-size-while-emulating-IRC-commands.patch +++ b/slirp-use-correct-size-while-emulating-IRC-commands.patch @@ -1,6 +1,6 @@ -From 882149fd8401f8ff667ea384bb68008354fd110f Mon Sep 17 00:00:00 2001 +From 011880f527ff317a40769ea8673a6353e5db53ac Mon Sep 17 00:00:00 2001 From: Prasad J Pandit -Date: Wed, 11 Mar 2020 18:19:36 +0800 +Date: Tue, 14 Apr 2020 18:23:23 +0800 Subject: [PATCH] slirp: use correct size while emulating IRC commands While emulating IRC DCC commands, tcp_emu() uses 'mbuf' size @@ -13,40 +13,42 @@ Signed-off-by: default avatarPrasad J Pandit Reviewed-by: Samuel Thibault's avatarSamuel Thibault Message-Id: <20200109094228.79764-2-ppandit@redhat.com> --- - slirp/src/tcp_subr.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) + slirp/src/tcp_subr.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index 4608942f..2053b11b 100644 +index 9c94c03a..2a15b16a 100644 --- a/slirp/src/tcp_subr.c +++ b/slirp/src/tcp_subr.c -@@ -786,7 +786,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); -@@ -797,7 +797,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "DCC SEND %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); -@@ -808,7 +808,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "DCC MOVE %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); --- -2.21.1 (Apple Git-122.3) - +@@ -778,7 +778,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size, "DCC CHAT chat %lu %u%c\n", ++ m->m_len += snprintf(bptr, M_FREEROOM(m), ++ "DCC CHAT chat %lu %u%c\n", + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), 1); + } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, +@@ -789,7 +790,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, m->m_size, "DCC SEND %s %lu %u %u%c\n", buff, ++ snprintf(bptr, M_FREEROOM(m), ++ "DCC SEND %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); + } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, +@@ -800,7 +802,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, m->m_size, "DCC MOVE %s %lu %u %u%c\n", buff, ++ snprintf(bptr, M_FREEROOM(m), ++ "DCC MOVE %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); + } +-- +2.23.0 diff --git a/slirp-use-correct-size-while-emulating-commands.patch b/slirp-use-correct-size-while-emulating-commands.patch index 76507a4d82f3c769540cf34294d855242ac0737f..25f64e2738e2ae3cbff541719b726dff963007d2 100644 --- a/slirp-use-correct-size-while-emulating-commands.patch +++ b/slirp-use-correct-size-while-emulating-commands.patch @@ -1,6 +1,6 @@ -From 66e2f47a01ffcaafe11acae0a191efd1805f86c6 Mon Sep 17 00:00:00 2001 +From 662aa4f1d168b32335a4dc40782e816329afcac0 Mon Sep 17 00:00:00 2001 From: Prasad J Pandit -Date: Wed, 11 Mar 2020 18:27:22 +0800 +Date: Tue, 14 Apr 2020 18:36:12 +0800 Subject: [PATCH] slirp: use correct size while emulating commands While emulating services in tcp_emu(), it uses 'mbuf' size @@ -10,42 +10,40 @@ Signed-off-by: default avatarPrasad J Pandit Signed-off-by: Samuel Thibault's avatarSamuel Thibault Message-Id: <20200109094228.79764-3-ppandit@redhat.com> --- - slirp/src/tcp_subr.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) + slirp/src/tcp_subr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index 2053b11b..e898fd03 100644 +index 2a15b16a..019b637a 100644 --- a/slirp/src/tcp_subr.c +++ b/slirp/src/tcp_subr.c -@@ -707,7 +707,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size - m->m_len, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "ORT %d,%d,%d,%d,%d,%d\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - return 1; -@@ -740,7 +740,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size - m->m_len, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - -@@ -766,8 +766,8 @@ tcp_emu(struct socket *so, struct mbuf *m) - if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) -- m->m_len = snprintf(m->m_data, m->m_size, "%d", -- ntohs(so->so_fport)) + 1; -+ m->m_len = snprintf(m->m_data, M_ROOM(m), -+ "%d", ntohs(so->so_fport)) + 1; - return 1; - - case EMU_IRC: --- -2.21.1 (Apple Git-122.3) +@@ -696,7 +696,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + n4 = (laddr & 0xff); + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size - m->m_len, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, + n5, n6, x == 7 ? buff : ""); + return 1; +@@ -732,7 +732,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, m->m_size - m->m_len, ++ snprintf(bptr, M_FREEROOM(m), + "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", + n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); + +@@ -759,7 +759,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) + (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, + htons(lport), SS_FACCEPTONCE)) != NULL) + m->m_len = +- snprintf(m->m_data, m->m_size, "%d", ntohs(so->so_fport)) + 1; ++ snprintf(m->m_data, M_ROOM(m), ++ "%d", ntohs(so->so_fport)) + 1; + return 1; + + case EMU_IRC: +-- +2.23.0 diff --git a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch b/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch index c45af3e6aa3ba4b5c58583f5605c7a6b9f90e508..cfd1842d3f199ec1db6e324e448df37b4553ea2a 100644 --- a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +++ b/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch @@ -1,21 +1,19 @@ -From e52fdbd850b49304c5bbd5f19c9f518b80efef42 Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Wed, 31 Jul 2019 15:40:55 +0800 +From 2b8ad77678da175cb92c902955cb85827e661de3 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 14 Apr 2020 14:53:44 +0800 Subject: [PATCH] smbios: Add missing member of type 4 for smbios 3.0 According to smbios 3.0 spec, for processor information (type 4), -it adds three new members (Core Count 2, Core enabled 2, thread count 2) for 3.0, - -Without this three members, we can not get correct cpu frequency from dmi, +it adds three new members (Core Count 2, Core enabled 2, thread count 2) for 3.0, Without this three members, we can not get correct cpu frequency from dmi, Because it will failed to check the length of Processor Infomation in DMI. The corresponding codes in kernel is like: - if (dm->type == DMI_ENTRY_PROCESSOR && - dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) { - u16 val = (u16)get_unaligned((const u16 *) - (dmi_data + DMI_PROCESSOR_MAX_SPEED)); - *mhz = val > *mhz ? val : *mhz; - } + if (dm->type == DMI_ENTRY_PROCESSOR && + dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) { + u16 val = (u16)get_unaligned((const u16 *) + (dmi_data + DMI_PROCESSOR_MAX_SPEED)); + *mhz = val > *mhz ? val : *mhz; + } Signed-off-by: zhanghailiang --- @@ -24,11 +22,11 @@ Signed-off-by: zhanghailiang 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c -index 47be9071..b11ec6e3 100644 +index 7bcd67b0..51b00d44 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c -@@ -600,7 +600,9 @@ static void smbios_build_type_4_table(unsigned instance) - t->thread_count = smp_threads; +@@ -603,7 +603,9 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance) + t->thread_count = ms->smp.threads; t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */ t->processor_family2 = cpu_to_le16(0x01); /* Other */ - @@ -39,7 +37,7 @@ index 47be9071..b11ec6e3 100644 smbios_type4_count++; } diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h -index 6fef32a3..70eb7304 100644 +index 02a0ced0..6887bca4 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -193,6 +193,9 @@ struct smbios_type_4 { @@ -50,8 +48,7 @@ index 6fef32a3..70eb7304 100644 + uint16_t enabledcorecount2; + uint16_t threadcount2; } QEMU_PACKED; - - /* SMBIOS type 11 - OEM strings */ --- -2.19.1 + /* SMBIOS type 11 - OEM strings */ +-- +2.23.0 diff --git a/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch b/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca4b796b58600aa35771d26a247690dfca413cc9 --- /dev/null +++ b/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch @@ -0,0 +1,41 @@ +From cdc6896659b85f7ed8f7552850312e55170de0c5 Mon Sep 17 00:00:00 2001 +From: Christophe Lyon +Date: Fri, 25 Oct 2019 11:57:11 +0200 +Subject: [PATCH] target/arm: Allow reading flags from FPSCR for M-profile + +rt==15 is a special case when reading the flags: it means the +destination is APSR. This patch avoids rejecting +vmrs apsr_nzcv, fpscr +as illegal instruction. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Christophe Lyon +Message-id: 20191025095711.10853-1-christophe.lyon@linaro.org +[PMM: updated the comment] +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 2529ab43b8a05534494704e803e0332d111d8b91) +Signed-off-by: Michael Roth +--- + target/arm/translate-vfp.inc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c +index ef45cecbea..75406fd9db 100644 +--- a/target/arm/translate-vfp.inc.c ++++ b/target/arm/translate-vfp.inc.c +@@ -704,9 +704,10 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a) + if (arm_dc_feature(s, ARM_FEATURE_M)) { + /* + * The only M-profile VFP vmrs/vmsr sysreg is FPSCR. +- * Writes to R15 are UNPREDICTABLE; we choose to undef. ++ * Accesses to R15 are UNPREDICTABLE; we choose to undef. ++ * (FPSCR -> r15 is a special case which writes to the PSR flags.) + */ +- if (a->rt == 15 || a->reg != ARM_VFP_FPSCR) { ++ if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) { + return false; + } + } +-- +2.23.0 diff --git a/target-arm-Don-t-abort-on-M-profile-exception-return.patch b/target-arm-Don-t-abort-on-M-profile-exception-return.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6796e25b8b04c76a117ad129cb807a0da93da45 --- /dev/null +++ b/target-arm-Don-t-abort-on-M-profile-exception-return.patch @@ -0,0 +1,103 @@ +From 9027d3fba605d8f6093342ebe4a1da450d374630 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Thu, 22 Aug 2019 14:15:34 +0100 +Subject: [PATCH] target/arm: Don't abort on M-profile exception return in + linux-user mode + +An attempt to do an exception-return (branch to one of the magic +addresses) in linux-user mode for M-profile should behave like +a normal branch, because linux-user mode is always going to be +in 'handler' mode. This used to work, but we broke it when we added +support for the M-profile security extension in commit d02a8698d7ae2bfed. + +In that commit we allowed even handler-mode calls to magic return +values to be checked for and dealt with by causing an +EXCP_EXCEPTION_EXIT exception to be taken, because this is +needed for the FNC_RETURN return-from-non-secure-function-call +handling. For system mode we added a check in do_v7m_exception_exit() +to make any spurious calls from Handler mode behave correctly, but +forgot that linux-user mode would also be affected. + +How an attempted return-from-non-secure-function-call in linux-user +mode should be handled is not clear -- on real hardware it would +result in return to secure code (not to the Linux kernel) which +could then handle the error in any way it chose. For QEMU we take +the simple approach of treating this erroneous return the same way +it would be handled on a CPU without the security extensions -- +treat it as a normal branch. + +The upshot of all this is that for linux-user mode we should never +do any of the bx_excret magic, so the code change is simple. + +This ought to be a weird corner case that only affects broken guest +code (because Linux user processes should never be attempting to do +exception returns or NS function returns), except that the code that +assigns addresses in RAM for the process and stack in our linux-user +code does not attempt to avoid this magic address range, so +legitimate code attempting to return to a trampoline routine on the +stack can fall into this case. This change fixes those programs, +but we should also look at restricting the range of memory we +use for M-profile linux-user guests to the area that would be +real RAM in hardware. + +Cc: qemu-stable@nongnu.org +Reported-by: Christophe Lyon +Reviewed-by: Richard Henderson +Signed-off-by: Peter Maydell +Message-id: 20190822131534.16602-1-peter.maydell@linaro.org +Fixes: https://bugs.launchpad.net/qemu/+bug/1840922 +Signed-off-by: Peter Maydell +(cherry picked from commit 5e5584c89f36b302c666bc6db535fd3f7ff35ad2) +Signed-off-by: Michael Roth +--- + target/arm/translate.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/target/arm/translate.c b/target/arm/translate.c +index 7853462b21..24cb4ba075 100644 +--- a/target/arm/translate.c ++++ b/target/arm/translate.c +@@ -952,10 +952,27 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var) + store_cpu_field(var, thumb); + } + +-/* Set PC and Thumb state from var. var is marked as dead. ++/* ++ * Set PC and Thumb state from var. var is marked as dead. + * For M-profile CPUs, include logic to detect exception-return + * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC, + * and BX reg, and no others, and happens only for code in Handler mode. ++ * The Security Extension also requires us to check for the FNC_RETURN ++ * which signals a function return from non-secure state; this can happen ++ * in both Handler and Thread mode. ++ * To avoid having to do multiple comparisons in inline generated code, ++ * we make the check we do here loose, so it will match for EXC_RETURN ++ * in Thread mode. For system emulation do_v7m_exception_exit() checks ++ * for these spurious cases and returns without doing anything (giving ++ * the same behaviour as for a branch to a non-magic address). ++ * ++ * In linux-user mode it is unclear what the right behaviour for an ++ * attempted FNC_RETURN should be, because in real hardware this will go ++ * directly to Secure code (ie not the Linux kernel) which will then treat ++ * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN ++ * attempt behave the way it would on a CPU without the security extension, ++ * which is to say "like a normal branch". That means we can simply treat ++ * all branches as normal with no magic address behaviour. + */ + static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var) + { +@@ -963,10 +980,12 @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var) + * s->base.is_jmp that we need to do the rest of the work later. + */ + gen_bx(s, var); ++#ifndef CONFIG_USER_ONLY + if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) || + (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) { + s->base.is_jmp = DISAS_BX_EXCRET; + } ++#endif + } + + static inline void gen_bx_excret_final_code(DisasContext *s) +-- +2.23.0 diff --git a/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch b/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch new file mode 100644 index 0000000000000000000000000000000000000000..a46232f8ba04e1e2a956d8493dc1515fcf1f272a --- /dev/null +++ b/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch @@ -0,0 +1,40 @@ +From 38fb634853ac6547326d9f88b9a068d9fc6b4ad4 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 27 Aug 2019 13:19:31 +0100 +Subject: [PATCH] target/arm: Free TCG temps in trans_VMOV_64_sp() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function neon_store_reg32() doesn't free the TCG temp that it +is passed, so the caller must do that. We got this right in most +places but forgot to free the TCG temps in trans_VMOV_64_sp(). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20190827121931.26836-1-peter.maydell@linaro.org +(cherry picked from commit 342d27581bd3ecdb995e4fc55fcd383cf3242888) +Signed-off-by: Michael Roth +--- + target/arm/translate-vfp.inc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c +index 092eb5ec53..ef45cecbea 100644 +--- a/target/arm/translate-vfp.inc.c ++++ b/target/arm/translate-vfp.inc.c +@@ -881,8 +881,10 @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a) + /* gpreg to fpreg */ + tmp = load_reg(s, a->rt); + neon_store_reg32(tmp, a->vm); ++ tcg_temp_free_i32(tmp); + tmp = load_reg(s, a->rt2); + neon_store_reg32(tmp, a->vm + 1); ++ tcg_temp_free_i32(tmp); + } + + return true; +-- +2.23.0 diff --git a/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch b/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..41c67cf1b8024af9f48888ecd782e9927a2f166e --- /dev/null +++ b/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch @@ -0,0 +1,152 @@ +From 860035652c7866b033762f6d90f81d5ddedf855c Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 22 Apr 2020 17:08:43 +0800 +Subject: [PATCH] target/arm/cpu: Add the kvm-no-adjvtime CPU property + +kvm-no-adjvtime is a KVM specific CPU property and a first of its +kind. To accommodate it we also add kvm_arm_add_vcpu_properties() +and a KVM specific CPU properties description to the CPU features +document. + +Signed-off-by: Andrew Jones +Message-id: 20200120101023.16030-7-drjones@redhat.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index e9a2a959..cfda6cc5 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1748,6 +1748,11 @@ static void machvirt_init(MachineState *machine) + } + } + ++ if (vmc->kvm_no_adjvtime && ++ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { ++ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); ++ } ++ + if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { + object_property_set_bool(cpuobj, false, "pmu", NULL); + } +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 43a6ce91..a9d6977a 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -107,6 +107,7 @@ typedef struct { + bool claim_edge_triggered_timers; + bool smbios_old_sys_ver; + bool no_highmem_ecam; ++ bool kvm_no_adjvtime; + } VirtMachineClass; + + typedef struct { +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index bc3da9a3..39bbe7e2 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2441,6 +2441,7 @@ static void arm_max_initfn(Object *obj) + + if (kvm_enabled()) { + kvm_arm_set_cpu_features_from_host(cpu); ++ kvm_arm_add_vcpu_properties(obj); + } else { + cortex_a15_initfn(obj); + +@@ -2629,6 +2630,7 @@ static void arm_host_initfn(Object *obj) + ARMCPU *cpu = ARM_CPU(obj); + + kvm_arm_set_cpu_features_from_host(cpu); ++ kvm_arm_add_vcpu_properties(obj); + arm_cpu_post_init(obj); + } + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index dbf44b92..b30ca7c9 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -312,6 +312,7 @@ static void aarch64_max_initfn(Object *obj) + + if (kvm_enabled()) { + kvm_arm_set_cpu_features_from_host(cpu); ++ kvm_arm_add_vcpu_properties(obj); + } else { + uint64_t t; + uint32_t u; +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 21fb7ecd..327b3bc3 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -16,6 +16,8 @@ + #include "qemu-common.h" + #include "qemu/timer.h" + #include "qemu/error-report.h" ++#include "qom/object.h" ++#include "qapi/error.h" + #include "sysemu/sysemu.h" + #include "sysemu/kvm.h" + #include "sysemu/kvm_int.h" +@@ -162,6 +164,32 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) + env->features = arm_host_cpu_features.features; + } + ++static bool kvm_no_adjvtime_get(Object *obj, Error **errp) ++{ ++ return !ARM_CPU(obj)->kvm_adjvtime; ++} ++ ++static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) ++{ ++ ARM_CPU(obj)->kvm_adjvtime = !value; ++} ++ ++/* KVM VCPU properties should be prefixed with "kvm-". */ ++void kvm_arm_add_vcpu_properties(Object *obj) ++{ ++ if (!kvm_enabled()) { ++ return; ++ } ++ ++ ARM_CPU(obj)->kvm_adjvtime = true; ++ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, ++ kvm_no_adjvtime_set, &error_abort); ++ object_property_set_description(obj, "kvm-no-adjvtime", ++ "Set on to disable the adjustment of " ++ "the virtual counter. VM stopped time " ++ "will be counted.", &error_abort); ++} ++ + int kvm_arm_get_max_vm_ipa_size(MachineState *ms) + { + KVMState *s = KVM_STATE(ms->accelerator); +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 97560d4e..0de5f83e 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -230,6 +230,15 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); + */ + void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); + ++/** ++ * kvm_arm_add_vcpu_properties: ++ * @obj: The CPU object to add the properties to ++ * ++ * Add all KVM specific CPU properties to the CPU object. These ++ * are the CPU properties with "kvm-" prefixed names. ++ */ ++void kvm_arm_add_vcpu_properties(Object *obj); ++ + /** + * kvm_arm_get_max_vm_ipa_size: + * @ms: Machine state handle +@@ -294,6 +303,8 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) + cpu->host_cpu_probe_failed = true; + } + ++static inline void kvm_arm_add_vcpu_properties(Object *obj) {} ++ + static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms) + { + return -ENOENT; +-- +2.23.0 diff --git a/target-arm-kvm-Implement-virtual-time-adjustment.patch b/target-arm-kvm-Implement-virtual-time-adjustment.patch new file mode 100644 index 0000000000000000000000000000000000000000..86450c4d8f1739527a7065ec9242706605487b0e --- /dev/null +++ b/target-arm-kvm-Implement-virtual-time-adjustment.patch @@ -0,0 +1,290 @@ +From 77ee224418fac859acecd9aca4d18555ced42db6 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 21 Apr 2020 17:32:31 +0800 +Subject: [PATCH 3/4] target/arm/kvm: Implement virtual time adjustment + +When a VM is stopped (such as when it's paused) guest virtual time +should stop counting. Otherwise, when the VM is resumed it will +experience time jumps and its kernel may report soft lockups. Not +counting virtual time while the VM is stopped has the side effect +of making the guest's time appear to lag when compared with real +time, and even with time derived from the physical counter. For +this reason, this change, which is enabled by default, comes with +a KVM CPU feature allowing it to be disabled, restoring legacy +behavior. + +This patch only provides the implementation of the virtual time +adjustment. A subsequent patch will provide the CPU property +allowing the change to be enabled and disabled. + +Reported-by: Bijan Mottahedeh +Signed-off-by: Andrew Jones +Message-id: 20200120101023.16030-6-drjones@redhat.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/cpu.h | 7 ++++ + target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ + target/arm/kvm32.c | 2 + + target/arm/kvm64.c | 2 + + target/arm/kvm_arm.h | 37 ++++++++++++++++++ + target/arm/machine.c | 7 ++++ + 6 files changed, 147 insertions(+) + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 94c990cd..e19531a7 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -816,6 +816,13 @@ struct ARMCPU { + /* KVM init features for this CPU */ + uint32_t kvm_init_features[7]; + ++ /* KVM CPU state */ ++ ++ /* KVM virtual time adjustment */ ++ bool kvm_adjvtime; ++ bool kvm_vtime_dirty; ++ uint64_t kvm_vtime; ++ + /* Uniprocessor system with MP extensions */ + bool mp_is_up; + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index cc7a46df..21fb7ecd 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -336,6 +336,22 @@ static int compare_u64(const void *a, const void *b) + return 0; + } + ++/* ++ * cpreg_values are sorted in ascending order by KVM register ID ++ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find ++ * the storage for a KVM register by ID with a binary search. ++ */ ++static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) ++{ ++ uint64_t *res; ++ ++ res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, ++ sizeof(uint64_t), compare_u64); ++ assert(res); ++ ++ return &cpu->cpreg_values[res - cpu->cpreg_indexes]; ++} ++ + /* Initialize the ARMCPU cpreg list according to the kernel's + * definition of what CPU registers it knows about (and throw away + * the previous TCG-created cpreg list). +@@ -489,6 +505,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) + return ok; + } + ++void kvm_arm_cpu_pre_save(ARMCPU *cpu) ++{ ++ /* KVM virtual time adjustment */ ++ if (cpu->kvm_vtime_dirty) { ++ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; ++ } ++} ++ ++void kvm_arm_cpu_post_load(ARMCPU *cpu) ++{ ++ /* KVM virtual time adjustment */ ++ if (cpu->kvm_adjvtime) { ++ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); ++ cpu->kvm_vtime_dirty = true; ++ } ++} ++ + void kvm_arm_reset_vcpu(ARMCPU *cpu) + { + int ret; +@@ -556,6 +589,50 @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) + return 0; + } + ++void kvm_arm_get_virtual_time(CPUState *cs) ++{ ++ ARMCPU *cpu = ARM_CPU(cs); ++ struct kvm_one_reg reg = { ++ .id = KVM_REG_ARM_TIMER_CNT, ++ .addr = (uintptr_t)&cpu->kvm_vtime, ++ }; ++ int ret; ++ ++ if (cpu->kvm_vtime_dirty) { ++ return; ++ } ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); ++ if (ret) { ++ error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); ++ abort(); ++ } ++ ++ cpu->kvm_vtime_dirty = true; ++} ++ ++void kvm_arm_put_virtual_time(CPUState *cs) ++{ ++ ARMCPU *cpu = ARM_CPU(cs); ++ struct kvm_one_reg reg = { ++ .id = KVM_REG_ARM_TIMER_CNT, ++ .addr = (uintptr_t)&cpu->kvm_vtime, ++ }; ++ int ret; ++ ++ if (!cpu->kvm_vtime_dirty) { ++ return; ++ } ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); ++ if (ret) { ++ error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); ++ abort(); ++ } ++ ++ cpu->kvm_vtime_dirty = false; ++} ++ + int kvm_put_vcpu_events(ARMCPU *cpu) + { + CPUARMState *env = &cpu->env; +@@ -667,6 +744,21 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) + return MEMTXATTRS_UNSPECIFIED; + } + ++void kvm_arm_vm_state_change(void *opaque, int running, RunState state) ++{ ++ CPUState *cs = opaque; ++ ARMCPU *cpu = ARM_CPU(cs); ++ ++ if (running) { ++ if (cpu->kvm_adjvtime) { ++ kvm_arm_put_virtual_time(cs); ++ } ++ } else { ++ if (cpu->kvm_adjvtime) { ++ kvm_arm_get_virtual_time(cs); ++ } ++ } ++} + + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) + { +diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c +index 51f78f72..ee158830 100644 +--- a/target/arm/kvm32.c ++++ b/target/arm/kvm32.c +@@ -195,6 +195,8 @@ int kvm_arch_init_vcpu(CPUState *cs) + return -EINVAL; + } + ++ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); ++ + /* Determine init features for this CPU */ + memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); + if (cpu->start_powered_off) { +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index f2f0a92e..4f0bf000 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -609,6 +609,8 @@ int kvm_arch_init_vcpu(CPUState *cs) + return -EINVAL; + } + ++ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); ++ + /* Determine init features for this CPU */ + memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); + if (cpu->start_powered_off) { +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 32d97ce5..97560d4e 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -113,6 +113,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level); + */ + bool write_kvmstate_to_list(ARMCPU *cpu); + ++/** ++ * kvm_arm_cpu_pre_save: ++ * @cpu: ARMCPU ++ * ++ * Called after write_kvmstate_to_list() from cpu_pre_save() to update ++ * the cpreg list with KVM CPU state. ++ */ ++void kvm_arm_cpu_pre_save(ARMCPU *cpu); ++ ++/** ++ * kvm_arm_cpu_post_load: ++ * @cpu: ARMCPU ++ * ++ * Called from cpu_post_load() to update KVM CPU state from the cpreg list. ++ */ ++void kvm_arm_cpu_post_load(ARMCPU *cpu); ++ + /** + * kvm_arm_reset_vcpu: + * @cpu: ARMCPU +@@ -241,6 +258,24 @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); + */ + int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); + ++/** ++ * kvm_arm_get_virtual_time: ++ * @cs: CPUState ++ * ++ * Gets the VCPU's virtual counter and stores it in the KVM CPU state. ++ */ ++void kvm_arm_get_virtual_time(CPUState *cs); ++ ++/** ++ * kvm_arm_put_virtual_time: ++ * @cs: CPUState ++ * ++ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state. ++ */ ++void kvm_arm_put_virtual_time(CPUState *cs); ++ ++void kvm_arm_vm_state_change(void *opaque, int running, RunState state); ++ + int kvm_arm_vgic_probe(void); + + void kvm_arm_pmu_set_irq(CPUState *cs, int irq); +@@ -272,6 +307,8 @@ static inline int kvm_arm_vgic_probe(void) + static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} + static inline void kvm_arm_pmu_init(CPUState *cs) {} + ++static inline void kvm_arm_get_virtual_time(CPUState *cs) {} ++static inline void kvm_arm_put_virtual_time(CPUState *cs) {} + #endif + + static inline const char *gic_class_name(void) +diff --git a/target/arm/machine.c b/target/arm/machine.c +index 3fd319a3..ee3c59a6 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -644,6 +644,12 @@ static int cpu_pre_save(void *opaque) + /* This should never fail */ + abort(); + } ++ ++ /* ++ * kvm_arm_cpu_pre_save() must be called after ++ * write_kvmstate_to_list() ++ */ ++ kvm_arm_cpu_pre_save(cpu); + } else { + if (!write_cpustate_to_list(cpu, false)) { + /* This should never fail. */ +@@ -746,6 +752,7 @@ static int cpu_post_load(void *opaque, int version_id) + * we're using it. + */ + write_list_to_cpustate(cpu); ++ kvm_arm_cpu_post_load(cpu); + } else { + if (!write_list_to_cpustate(cpu)) { + return -1; +-- +2.23.0 diff --git a/target-arm-kvm-trivial-Clean-up-header-documentation.patch b/target-arm-kvm-trivial-Clean-up-header-documentation.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c28c63b1e9fa89ace5860f635f07e2d9b221bbe --- /dev/null +++ b/target-arm-kvm-trivial-Clean-up-header-documentation.patch @@ -0,0 +1,144 @@ +From c057499f90af4be8b26f57f8755aca0ddfcf9467 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 21 Apr 2020 16:52:07 +0800 +Subject: [PATCH 1/4] target/arm/kvm: trivial: Clean up header documentation + +Signed-off-by: Andrew Jones +Message-id: 20200120101023.16030-2-drjones@redhat.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +--- + target/arm/kvm_arm.h | 38 +++++++++++++++++++++++--------------- + 1 file changed, 23 insertions(+), 15 deletions(-) + +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index a9f3ccab..32d97ce5 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -61,8 +61,8 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, + int kvm_arm_init_cpreg_list(ARMCPU *cpu); + + /** +- * kvm_arm_reg_syncs_via_cpreg_list +- * regidx: KVM register index ++ * kvm_arm_reg_syncs_via_cpreg_list: ++ * @regidx: KVM register index + * + * Return true if this KVM register should be synchronized via the + * cpreg list of arbitrary system registers, false if it is synchronized +@@ -71,8 +71,8 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu); + bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); + + /** +- * kvm_arm_cpreg_level +- * regidx: KVM register index ++ * kvm_arm_cpreg_level: ++ * @regidx: KVM register index + * + * Return the level of this coprocessor/system register. Return value is + * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. +@@ -134,6 +134,8 @@ void kvm_arm_init_serror_injection(CPUState *cs); + * @cpu: ARMCPU + * + * Get VCPU related state from kvm. ++ * ++ * Returns: 0 if success else < 0 error code + */ + int kvm_get_vcpu_events(ARMCPU *cpu); + +@@ -142,6 +144,8 @@ int kvm_get_vcpu_events(ARMCPU *cpu); + * @cpu: ARMCPU + * + * Put VCPU related state to kvm. ++ * ++ * Returns: 0 if success else < 0 error code + */ + int kvm_put_vcpu_events(ARMCPU *cpu); + +@@ -191,10 +195,12 @@ typedef struct ARMHostCPUFeatures { + + /** + * kvm_arm_get_host_cpu_features: +- * @ahcc: ARMHostCPUClass to fill in ++ * @ahcf: ARMHostCPUClass to fill in + * + * Probe the capabilities of the host kernel's preferred CPU and fill + * in the ARMHostCPUClass struct accordingly. ++ * ++ * Returns true on success and false otherwise. + */ + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); + +@@ -208,26 +214,30 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); + void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); + + /** +- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the +- * IPA address space supported by KVM +- * ++ * kvm_arm_get_max_vm_ipa_size: + * @ms: Machine state handle ++ * ++ * Returns the number of bits in the IPA address space supported by KVM + */ + int kvm_arm_get_max_vm_ipa_size(MachineState *ms); + + /** +- * kvm_arm_sync_mpstate_to_kvm ++ * kvm_arm_sync_mpstate_to_kvm: + * @cpu: ARMCPU + * + * If supported set the KVM MP_STATE based on QEMU's model. ++ * ++ * Returns 0 on success and -1 on failure. + */ + int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); + + /** +- * kvm_arm_sync_mpstate_to_qemu ++ * kvm_arm_sync_mpstate_to_qemu: + * @cpu: ARMCPU + * + * If supported get the MP_STATE from KVM and store in QEMU's model. ++ * ++ * Returns 0 on success and aborts on failure. + */ + int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); + +@@ -241,7 +251,8 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); + + static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) + { +- /* This should never actually be called in the "not KVM" case, ++ /* ++ * This should never actually be called in the "not KVM" case, + * but set up the fields to indicate an error anyway. + */ + cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; +@@ -310,23 +321,20 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit); + * + * Return: TRUE if any hardware breakpoints in use. + */ +- + bool kvm_arm_hw_debug_active(CPUState *cs); + + /** + * kvm_arm_copy_hw_debug_data: +- * + * @ptr: kvm_guest_debug_arch structure + * + * Copy the architecture specific debug registers into the + * kvm_guest_debug ioctl structure. + */ + struct kvm_guest_debug_arch; +- + void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); + + /** +- * its_class_name ++ * its_class_name: + * + * Return the ITS class name to use depending on whether KVM acceleration + * and KVM CAP_SIGNAL_MSI are supported +-- +2.23.0 diff --git a/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch b/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..b8cec1bd36e2da9526a643229252ac6760eebecf --- /dev/null +++ b/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch @@ -0,0 +1,37 @@ +From 07bd62920f968da7d1d8962cc7fd3d29652d25f4 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 21 Apr 2020 17:04:13 +0800 +Subject: [PATCH 2/4] target/arm/kvm64: kvm64 cpus have timer registers + +Add the missing GENERIC_TIMER feature to kvm64 cpus. + +We don't currently use these registers when KVM is enabled, but it's +probably best we add the feature flag for consistency and potential +future use. There's also precedent, as we add the PMU feature flag to +KVM enabled guests, even though we don't use those registers either. + +This change was originally posted as a hunk of a different, never +merged patch from Bijan Mottahedeh. + +Signed-off-by: Andrew Jones +Reviewed-by: Richard Henderson +Message-id: 20200120101023.16030-4-drjones@redhat.com +Signed-off-by: Peter Maydell +--- + target/arm/kvm64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 22d19c9a..f2f0a92e 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -587,6 +587,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + set_feature(&features, ARM_FEATURE_NEON); + set_feature(&features, ARM_FEATURE_AARCH64); + set_feature(&features, ARM_FEATURE_PMU); ++ set_feature(&features, ARM_FEATURE_GENERIC_TIMER); + + ahcf->features = features; + +-- +2.23.0 diff --git a/tcp_emu-Fix-oob-access.patch b/tcp_emu-Fix-oob-access.patch index 5182f54363d585efd23f0a5c236d0e9c5153215e..807dfef08e28fe33a65fede676bbb076f5d9e393 100644 --- a/tcp_emu-Fix-oob-access.patch +++ b/tcp_emu-Fix-oob-access.patch @@ -1,6 +1,6 @@ -From 0f7224535cdfec549cd43a5ae4ccde936f50ee95 Mon Sep 17 00:00:00 2001 +From 585634894f511bc1821cef54494bf2d9abc109c9 Mon Sep 17 00:00:00 2001 From: Samuel Thibault -Date: Wed, 11 Mar 2020 17:33:46 +0800 +Date: Tue, 14 Apr 2020 18:04:33 +0800 Subject: [PATCH] tcp_emu: Fix oob access The main loop only checks for one available byte, while we sometimes @@ -10,29 +10,28 @@ need two bytes. 1 file changed, 6 insertions(+) diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index fde9207b..4608942f 100644 +index d6dd133a..9c94c03a 100644 --- a/slirp/src/tcp_subr.c +++ b/slirp/src/tcp_subr.c -@@ -895,6 +895,9 @@ tcp_emu(struct socket *so, struct mbuf *m) - break; - - case 5: -+ if (bptr == m->m_data + m->m_len - 1) -+ return 1; /* We need two bytes */ +@@ -886,6 +886,9 @@ int tcp_emu(struct socket *so, struct mbuf *m) + break; + + case 5: ++ if (bptr == m->m_data + m->m_len - 1) ++ return 1; /* We need two bytes */ + - /* - * The difference between versions 1.0 and - * 2.0 is here. For future versions of -@@ -910,6 +913,9 @@ tcp_emu(struct socket *so, struct mbuf *m) - /* This is the field containing the port - * number that RA-player is listening to. - */ -+ if (bptr == m->m_data + m->m_len - 1) -+ return 1; /* We need two bytes */ + /* + * The difference between versions 1.0 and + * 2.0 is here. For future versions of +@@ -901,6 +904,9 @@ int tcp_emu(struct socket *so, struct mbuf *m) + /* This is the field containing the port + * number that RA-player is listening to. + */ ++ if (bptr == m->m_data + m->m_len - 1) ++ return 1; /* We need two bytes */ + - lport = (((uint8_t*)bptr)[0] << 8) - + ((uint8_t *)bptr)[1]; - if (lport < 6970) --- -2.21.1 (Apple Git-122.3) - + lport = (((uint8_t *)bptr)[0] << 8) + ((uint8_t *)bptr)[1]; + if (lport < 6970) + lport += 256; /* don't know why */ +-- +2.23.0 diff --git a/tcp_emu-fix-unsafe-snprintf-usages.patch b/tcp_emu-fix-unsafe-snprintf-usages.patch index cc13154ca1449831d6a91dbacc27234af4caf0e5..2f6850a60c2fb942ecc7ef15030686d3dd94aa9c 100644 --- a/tcp_emu-fix-unsafe-snprintf-usages.patch +++ b/tcp_emu-fix-unsafe-snprintf-usages.patch @@ -1,6 +1,6 @@ -From 1db8bcc0ec91bb4374b3ffdd03da3c4ede381fb5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 11 Mar 2020 18:52:07 +0800 +From 220a52fda279038d46c25d39a372154ff9b024d2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureauls?= +Date: Tue, 14 Apr 2020 19:06:35 +0800 Subject: [PATCH] tcp_emu: fix unsafe snprintf() usages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -28,67 +28,76 @@ Signed-off-by: default avatarMarc-André Lureau Reviewed-by: Samuel Thibault's avatarSamuel Thibault Message-Id: <20200127092414.169796-7-marcandre.lureau@redhat.com> --- - slirp/src/tcp_subr.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) + slirp/src/tcp_subr.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index e898fd03..88dadc76 100644 +index 019b637a..6c1b17bd 100644 --- a/slirp/src/tcp_subr.c +++ b/slirp/src/tcp_subr.c -@@ -707,7 +707,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "ORT %d,%d,%d,%d,%d,%d\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - return 1; -@@ -740,7 +740,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - -@@ -766,7 +766,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) -- m->m_len = snprintf(m->m_data, M_ROOM(m), -+ m->m_len = slirp_fmt0(m->m_data, M_ROOM(m), - "%d", ntohs(so->so_fport)) + 1; - return 1; - -@@ -786,7 +786,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); -@@ -797,7 +797,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC SEND %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); -@@ -808,7 +808,7 @@ tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC MOVE %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); --- -2.21.1 (Apple Git-122.3) +@@ -655,8 +655,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + NTOHS(n1); + NTOHS(n2); + m_inc(m, snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1); +- m->m_len = snprintf(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); +- assert(m->m_len < M_ROOM(m)); ++ m->m_len = slirp_fmt(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); + } else { + *eol = '\r'; + } +@@ -696,7 +695,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + n4 = (laddr & 0xff); + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, M_FREEROOM(m), ++ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), + "ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, + n5, n6, x == 7 ? buff : ""); + return 1; +@@ -732,7 +731,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, M_FREEROOM(m), ++ slirp_fmt(bptr, M_FREEROOM(m), + "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", + n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); + +@@ -759,7 +758,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, + htons(lport), SS_FACCEPTONCE)) != NULL) + m->m_len = +- snprintf(m->m_data, M_ROOM(m), ++ slirp_fmt0(m->m_data, M_ROOM(m), + "%d", ntohs(so->so_fport)) + 1; + return 1; + +@@ -779,7 +778,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, M_FREEROOM(m), ++ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), + "DCC CHAT chat %lu %u%c\n", + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), 1); +@@ -791,7 +790,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, M_FREEROOM(m), ++ slirp_fmt(bptr, M_FREEROOM(m), + "DCC SEND %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); +@@ -803,7 +802,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) + } + m->m_len = bptr - m->m_data; /* Adjust length */ + m->m_len += +- snprintf(bptr, M_FREEROOM(m), ++ slirp_fmt(bptr, M_FREEROOM(m), + "DCC MOVE %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); +-- +2.23.0 diff --git a/test-numa-Adjust-aarch64-numa-test.patch b/test-numa-Adjust-aarch64-numa-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..24145937724385b1ff8dd0bd280e5e62341ad659 --- /dev/null +++ b/test-numa-Adjust-aarch64-numa-test.patch @@ -0,0 +1,58 @@ +From 3ef97cc418d1061fc0ec70098270ce2d76005cc1 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Thu, 23 Apr 2020 20:54:18 +0800 +Subject: [PATCH] test/numa: Adjust aarch64 numa test + +We have supported topology for arm/virt in previous patch, which +changes the meaning of "thread-id", so we must modify test case. + +Signed-off-by: Keqian Zhu +--- + tests/numa-test.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tests/numa-test.c b/tests/numa-test.c +index 8de8581231..71cdd7b4f7 100644 +--- a/tests/numa-test.c ++++ b/tests/numa-test.c +@@ -231,17 +231,17 @@ static void aarch64_numa_cpu(const void *data) + QObject *e; + QTestState *qts; + +- cli = make_cli(data, "-smp 2 " ++ cli = make_cli(data, "-smp 2,cores=2 " + "-numa node,nodeid=0 -numa node,nodeid=1 " +- "-numa cpu,node-id=1,thread-id=0 " +- "-numa cpu,node-id=0,thread-id=1"); ++ "-numa cpu,node-id=1,core-id=0 " ++ "-numa cpu,node-id=0,core-id=1"); + qts = qtest_init(cli); + cpus = get_cpus(qts, &resp); + g_assert(cpus); + + while ((e = qlist_pop(cpus))) { + QDict *cpu, *props; +- int64_t thread, node; ++ int64_t core, node; + + cpu = qobject_to(QDict, e); + g_assert(qdict_haskey(cpu, "props")); +@@ -249,12 +249,12 @@ static void aarch64_numa_cpu(const void *data) + + g_assert(qdict_haskey(props, "node-id")); + node = qdict_get_int(props, "node-id"); +- g_assert(qdict_haskey(props, "thread-id")); +- thread = qdict_get_int(props, "thread-id"); ++ g_assert(qdict_haskey(props, "core-id")); ++ core = qdict_get_int(props, "core-id"); + +- if (thread == 0) { ++ if (core == 0) { + g_assert_cmpint(node, ==, 1); +- } else if (thread == 1) { ++ } else if (core == 1) { + g_assert_cmpint(node, ==, 0); + } else { + g_assert(false); +-- +2.19.1 diff --git a/tests-Add-bios-tests-to-arm-virt.patch b/tests-Add-bios-tests-to-arm-virt.patch new file mode 100644 index 0000000000000000000000000000000000000000..025afb506017f9bc1c6fdb26df35c9534a8f3672 --- /dev/null +++ b/tests-Add-bios-tests-to-arm-virt.patch @@ -0,0 +1,86 @@ +From abbcc35ccb22d81d69a28dc66b5f5d94e673a25e Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:33 +0100 +Subject: [PATCH] tests: Add bios tests to arm/virt + +This adds numamem and memhp tests for arm/virt platform. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-12-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 49 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index 53a91a8067..5e177b7155 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -874,6 +874,53 @@ static void test_acpi_piix4_tcg_dimm_pxm(void) + test_acpi_tcg_dimm_pxm(MACHINE_PC); + } + ++static void test_acpi_virt_tcg_memhp(void) ++{ ++ test_data data = { ++ .machine = "virt", ++ .accel = "tcg", ++ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", ++ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", ++ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", ++ .ram_start = 0x40000000ULL, ++ .scan_len = 256ULL * 1024 * 1024, ++ }; ++ ++ data.variant = ".memhp"; ++ test_acpi_one(" -cpu cortex-a57" ++ " -m 256M,slots=3,maxmem=1G" ++ " -object memory-backend-ram,id=ram0,size=128M" ++ " -object memory-backend-ram,id=ram1,size=128M" ++ " -numa node,memdev=ram0 -numa node,memdev=ram1" ++ " -numa dist,src=0,dst=1,val=21", ++ &data); ++ ++ free_test_data(&data); ++ ++} ++ ++static void test_acpi_virt_tcg_numamem(void) ++{ ++ test_data data = { ++ .machine = "virt", ++ .accel = "tcg", ++ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", ++ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", ++ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", ++ .ram_start = 0x40000000ULL, ++ .scan_len = 128ULL * 1024 * 1024, ++ }; ++ ++ data.variant = ".numamem"; ++ test_acpi_one(" -cpu cortex-a57" ++ " -object memory-backend-ram,id=ram0,size=128M" ++ " -numa node,memdev=ram0", ++ &data); ++ ++ free_test_data(&data); ++ ++} ++ + static void test_acpi_virt_tcg(void) + { + test_data data = { +@@ -920,6 +967,8 @@ int main(int argc, char *argv[]) + qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); + } else if (strcmp(arch, "aarch64") == 0) { + qtest_add_func("acpi/virt", test_acpi_virt_tcg); ++ qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); ++ qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); + } + ret = g_test_run(); + boot_sector_cleanup(disk); +-- +2.19.1 diff --git a/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch new file mode 100644 index 0000000000000000000000000000000000000000..e739883feb04d14f33a97a2a0b6690ac6c5ccc24 --- /dev/null +++ b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch @@ -0,0 +1,44 @@ +From 27e2533e43f0ab2b8a60f1902f58f8752581ea9f Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:32 +0100 +Subject: [PATCH] tests: Update ACPI tables list for upcoming arm/virt tests + +This is in preparation to add numamem and memhp tests to +arm/virt platform. The bios-tables-test-allowed-diff.h +is updated with a list of expected ACPI tables that needs to be +present in tests/data/acpi/virt folder. + +Signed-off-by: Shameer Kolothum +Message-Id: <20190918130633.4872-11-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + tests/bios-tables-test-allowed-diff.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h +index 32a401ae35..3776dd2f3d 100644 +--- a/tests/bios-tables-test-allowed-diff.h ++++ b/tests/bios-tables-test-allowed-diff.h +@@ -1,4 +1,17 @@ + /* List of comma-separated changed AML files to ignore */ + "tests/data/acpi/virt/DSDT", ++"tests/data/acpi/virt/APIC.memhp", ++"tests/data/acpi/virt/APIC.numamem", + "tests/data/acpi/virt/DSDT.memhp", + "tests/data/acpi/virt/DSDT.numamem", ++"tests/data/acpi/virt/FACP.memhp", ++"tests/data/acpi/virt/FACP.numamem", ++"tests/data/acpi/virt/GTDT.memhp", ++"tests/data/acpi/virt/GTDT.numamem", ++"tests/data/acpi/virt/MCFG.memhp", ++"tests/data/acpi/virt/MCFG.numamem", ++"tests/data/acpi/virt/SLIT.memhp", ++"tests/data/acpi/virt/SPCR.memhp", ++"tests/data/acpi/virt/SPCR.numamem", ++"tests/data/acpi/virt/SRAT.memhp", ++"tests/data/acpi/virt/SRAT.numamem", +-- +2.19.1 diff --git a/tests-acpi-add-empty-files.patch b/tests-acpi-add-empty-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..46e51c0de0e0ba84b6edf01fb62e3005acd37697 --- /dev/null +++ b/tests-acpi-add-empty-files.patch @@ -0,0 +1,88 @@ +From c943416df54931cea8b19183fd7c4f2dbd86ec72 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sun, 29 Sep 2019 10:54:12 -0400 +Subject: [PATCH] tests/acpi: add empty files + +Needed to make tests pass. Will replace with actual files. + +Signed-off-by: Michael S. Tsirkin +--- + tests/data/acpi/virt/APIC.memhp | 0 + tests/data/acpi/virt/APIC.numamem | 0 + tests/data/acpi/virt/DSDT.memhp | 0 + tests/data/acpi/virt/DSDT.numamem | 0 + tests/data/acpi/virt/FACP.memhp | 0 + tests/data/acpi/virt/FACP.numamem | 0 + tests/data/acpi/virt/GTDT.memhp | 0 + tests/data/acpi/virt/GTDT.numamem | 0 + tests/data/acpi/virt/MCFG.memhp | 0 + tests/data/acpi/virt/MCFG.numamem | 0 + tests/data/acpi/virt/SLIT.memhp | 0 + tests/data/acpi/virt/SPCR.memhp | 0 + tests/data/acpi/virt/SPCR.numamem | 0 + tests/data/acpi/virt/SRAT.memhp | 0 + tests/data/acpi/virt/SRAT.numamem | 0 + 15 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 tests/data/acpi/virt/APIC.memhp + create mode 100644 tests/data/acpi/virt/APIC.numamem + create mode 100644 tests/data/acpi/virt/DSDT.memhp + create mode 100644 tests/data/acpi/virt/DSDT.numamem + create mode 100644 tests/data/acpi/virt/FACP.memhp + create mode 100644 tests/data/acpi/virt/FACP.numamem + create mode 100644 tests/data/acpi/virt/GTDT.memhp + create mode 100644 tests/data/acpi/virt/GTDT.numamem + create mode 100644 tests/data/acpi/virt/MCFG.memhp + create mode 100644 tests/data/acpi/virt/MCFG.numamem + create mode 100644 tests/data/acpi/virt/SLIT.memhp + create mode 100644 tests/data/acpi/virt/SPCR.memhp + create mode 100644 tests/data/acpi/virt/SPCR.numamem + create mode 100644 tests/data/acpi/virt/SRAT.memhp + create mode 100644 tests/data/acpi/virt/SRAT.numamem + +diff --git a/tests/data/acpi/virt/APIC.memhp b/tests/data/acpi/virt/APIC.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/APIC.numamem b/tests/data/acpi/virt/APIC.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/FACP.memhp b/tests/data/acpi/virt/FACP.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/FACP.numamem b/tests/data/acpi/virt/FACP.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/GTDT.memhp b/tests/data/acpi/virt/GTDT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/MCFG.memhp b/tests/data/acpi/virt/MCFG.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/MCFG.numamem b/tests/data/acpi/virt/MCFG.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/virt/SLIT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SPCR.memhp b/tests/data/acpi/virt/SPCR.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SPCR.numamem b/tests/data/acpi/virt/SPCR.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/virt/SRAT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +-- +2.19.1 diff --git a/tests-allow-empty-expected-files.patch b/tests-allow-empty-expected-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..615fb2121d3ffd93d926fe4f3e9623ffce16eb88 --- /dev/null +++ b/tests-allow-empty-expected-files.patch @@ -0,0 +1,31 @@ +From 2ab0636e0c8fcb8b5b1b222f0d5ae7f4dfc663c5 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sat, 5 Oct 2019 17:09:17 -0400 +Subject: [PATCH] tests: allow empty expected files + +An empty expected file is a handy way to seed the files +without creating merge conflicts. + +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index a356ac3489..53a91a8067 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -334,7 +334,10 @@ try_again: + g_assert(ret); + g_assert_no_error(error); + g_assert(exp_sdt.aml); +- g_assert(exp_sdt.aml_len); ++ if (!exp_sdt.aml_len) { ++ fprintf(stderr, "Warning! zero length expected file '%s'\n", ++ aml_file); ++ } + + g_array_append_val(exp_tables, exp_sdt); + } +-- +2.19.1 diff --git a/tests-bios-tables-test-disable-this-testcase.patch b/tests-bios-tables-test-disable-this-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e57c6faf8142d33077c29375682b5c915b04265 --- /dev/null +++ b/tests-bios-tables-test-disable-this-testcase.patch @@ -0,0 +1,48 @@ +From 0814ef80cdf212c68b73fc1fbad4eeece3560ef9 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Wed, 15 Apr 2020 19:52:09 +0800 +Subject: [PATCH] tests/bios-tables-test: disable this testcase + +We will change ARM virt ACPI FACP and PPTT table in order to +support CPU topology information presentation. However our +change make this testcase fail since we changed the table +totally and we cannot apply patch with rpmbuild system. + +Signed-off-by: Ying Fang +--- + tests/Makefile.include | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tests/Makefile.include b/tests/Makefile.include +index fd7fdb86..d8cf00c1 100644 +--- a/tests/Makefile.include ++++ b/tests/Makefile.include +@@ -164,7 +164,7 @@ check-qtest-i386-y += tests/ide-test$(EXESUF) + check-qtest-i386-y += tests/ahci-test$(EXESUF) + check-qtest-i386-y += tests/hd-geo-test$(EXESUF) + check-qtest-i386-y += tests/boot-order-test$(EXESUF) +-check-qtest-i386-y += tests/bios-tables-test$(EXESUF) ++# check-qtest-i386-y += tests/bios-tables-test$(EXESUF) + check-qtest-i386-$(CONFIG_SGA) += tests/boot-serial-test$(EXESUF) + check-qtest-i386-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF) + check-qtest-i386-y += tests/rtc-test$(EXESUF) +@@ -269,7 +269,7 @@ check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) + check-qtest-aarch64-y += tests/migration-test$(EXESUF) + # TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional + ifneq ($(ARCH),arm) +-check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF) ++#check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF) + endif + + check-qtest-microblazeel-y += $(check-qtest-microblaze-y) +@@ -783,7 +783,7 @@ tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o + tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o + tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y) + tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y) +-tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ ++#tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ + tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y) + tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) + tests/microbit-test$(EXESUF): tests/microbit-test.o +-- +2.23.0 diff --git a/tests-document-how-to-update-acpi-tables.patch b/tests-document-how-to-update-acpi-tables.patch new file mode 100644 index 0000000000000000000000000000000000000000..c961069b6e77c2a193b34d606466f04c7b059611 --- /dev/null +++ b/tests-document-how-to-update-acpi-tables.patch @@ -0,0 +1,53 @@ +From d9642ad522d34f0d803a87654a2c258baf1070dd Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sat, 5 Oct 2019 17:25:55 -0400 +Subject: [PATCH] tests: document how to update acpi tables + +Looks like no one understands how to do it. +Document the process. + +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index 5e177b7155..d47ee9be99 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -10,6 +10,33 @@ + * See the COPYING file in the top-level directory. + */ + ++/* ++ * How to add or update the tests: ++ * Contributor: ++ * 1. add empty files for new tables, if any, under tests/data/acpi ++ * 2. list any changed files in tests/bios-tables-test-allowed-diff.h ++ * 3. commit the above *before* making changes that affect the tables ++ * Maintainer: ++ * After 1-3 above tests will pass but ignore differences with the expected files. ++ * You will also notice that tests/bios-tables-test-allowed-diff.h lists ++ * a bunch of files. This is your hint that you need to do the below: ++ * 4. Run ++ * make check V=1 ++ * this will produce a bunch of warnings about differences ++ * beween actual and expected ACPI tables. If you have IASL installed, ++ * they will also be disassembled so you can look at the disassembled ++ * output. If not - disassemble them yourself in any way you like. ++ * Look at the differences - make sure they make sense and match what the ++ * changes you are merging are supposed to do. ++ * ++ * 5. From build directory, run: ++ * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh ++ * 6. Now commit any changes. ++ * 7. Before doing a pull request, make sure tests/bios-tables-test-allowed-diff.h ++ * is empty - this will ensure following changes to ACPI tables will ++ * be noticed. ++ */ ++ + #include "qemu/osdep.h" + #include + #include "qemu-common.h" +-- +2.19.1 diff --git a/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch b/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch new file mode 100644 index 0000000000000000000000000000000000000000..30724cedb050b52be09a0b081ffe36cd7599d268 --- /dev/null +++ b/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch @@ -0,0 +1,62 @@ +From 6705b9344f8d6f134f612c2e35e87cdda5aa6284 Mon Sep 17 00:00:00 2001 +From: Hikaru Nishida +Date: Tue, 15 Oct 2019 10:07:34 +0900 +Subject: [PATCH] ui: Fix hanging up Cocoa display on macOS 10.15 (Catalina) + +macOS API documentation says that before applicationDidFinishLaunching +is called, any events will not be processed. However, some events are +fired before it is called in macOS Catalina. This causes deadlock of +iothread_lock in handleEvent while it will be released after the +app_started_sem is posted. +This patch avoids processing events before the app_started_sem is +posted to prevent this deadlock. + +Buglink: https://bugs.launchpad.net/qemu/+bug/1847906 +Signed-off-by: Hikaru Nishida +Message-id: 20191015010734.85229-1-hikarupsp@gmail.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit dff742ad27efa474ec04accdbf422c9acfd3e30e) +Signed-off-by: Michael Roth +--- + ui/cocoa.m | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ui/cocoa.m b/ui/cocoa.m +index c2984028c5..3026ead621 100644 +--- a/ui/cocoa.m ++++ b/ui/cocoa.m +@@ -132,6 +132,7 @@ NSArray * supportedImageFileTypes; + + static QemuSemaphore display_init_sem; + static QemuSemaphore app_started_sem; ++static bool allow_events; + + // Utility functions to run specified code block with iothread lock held + typedef void (^CodeBlock)(void); +@@ -727,6 +728,16 @@ QemuCocoaView *cocoaView; + + - (bool) handleEvent:(NSEvent *)event + { ++ if(!allow_events) { ++ /* ++ * Just let OSX have all events that arrive before ++ * applicationDidFinishLaunching. ++ * This avoids a deadlock on the iothread lock, which cocoa_display_init() ++ * will not drop until after the app_started_sem is posted. (In theory ++ * there should not be any such events, but OSX Catalina now emits some.) ++ */ ++ return false; ++ } + return bool_with_iothread_lock(^{ + return [self handleEventLocked:event]; + }); +@@ -1154,6 +1165,7 @@ QemuCocoaView *cocoaView; + - (void)applicationDidFinishLaunching: (NSNotification *) note + { + COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n"); ++ allow_events = true; + /* Tell cocoa_display_init to proceed */ + qemu_sem_post(&app_started_sem); + } +-- +2.23.0 diff --git a/util-add-slirp_fmt-helpers.patch b/util-add-slirp_fmt-helpers.patch new file mode 100644 index 0000000000000000000000000000000000000000..b752f1293a0b88ef0ae01410a2fc63f9ff875df8 --- /dev/null +++ b/util-add-slirp_fmt-helpers.patch @@ -0,0 +1,124 @@ +From f3475a4a22dd84be0d2d7daa11676ac861da64bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureauls?= +Date: Tue, 14 Apr 2020 18:51:39 +0800 +Subject: [PATCH] util: add slirp_fmt() helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Various calls to snprintf() in libslirp assume that snprintf() returns +"only" the number of bytes written (excluding terminating NUL). + +https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04 + +"Upon successful completion, the snprintf() function shall return the +number of bytes that would be written to s had n been sufficiently +large excluding the terminating null byte." + +Introduce slirp_fmt() that handles several pathological cases the +way libslirp usually expect: + +- treat error as fatal (instead of silently returning -1) + +- fmt0() will always \0 end + +- return the number of bytes actually written (instead of what would +have been written, which would usually result in OOB later), including +the ending \0 for fmt0() + +- warn if truncation happened (instead of ignoring) + +Other less common cases can still be handled with strcpy/snprintf() etc. +Signed-off-by: default avatarMarc-André Lureau +Reviewed-by: Samuel Thibault's avatarSamuel Thibault +Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com> +--- + slirp/src/util.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ + slirp/src/util.h | 3 +++ + 2 files changed, 66 insertions(+) + +diff --git a/slirp/src/util.c b/slirp/src/util.c +index e5960871..dcae899e 100644 +--- a/slirp/src/util.c ++++ b/slirp/src/util.c +@@ -364,3 +364,66 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str) + } + *q = '\0'; + } ++ ++static int slirp_vsnprintf(char *str, size_t size, ++ const char *format, va_list args) ++{ ++ int rv = vsnprintf(str, size, format, args); ++ ++ if (rv < 0) { ++ g_error("vsnprintf() failed: %s", g_strerror(errno)); ++ } ++ ++ return rv; ++} ++ ++/* ++ * A snprintf()-like function that: ++ * - returns the number of bytes written (excluding optional \0-ending) ++ * - dies on error ++ * - warn on truncation ++ */ ++int slirp_fmt(char *str, size_t size, const char *format, ...) ++{ ++ va_list args; ++ int rv; ++ ++ va_start(args, format); ++ rv = slirp_vsnprintf(str, size, format, args); ++ va_end(args); ++ ++ if (rv > size) { ++ g_critical("vsnprintf() truncation"); ++ } ++ ++ return MIN(rv, size); ++} ++ ++/* ++ * A snprintf()-like function that: ++ * - always \0-end (unless size == 0) ++ * - returns the number of bytes actually written, including \0 ending ++ * - dies on error ++ * - warn on truncation ++ */ ++int slirp_fmt0(char *str, size_t size, const char *format, ...) ++{ ++ va_list args; ++ int rv; ++ ++ va_start(args, format); ++ rv = slirp_vsnprintf(str, size, format, args); ++ va_end(args); ++ ++ if (rv >= size) { ++ g_critical("vsnprintf() truncation"); ++ if (size > 0) ++ str[size - 1] = '\0'; ++ rv = size; ++ } else { ++ rv += 1; /* include \0 */ ++ } ++ ++ return rv; ++} ++ +diff --git a/slirp/src/util.h b/slirp/src/util.h +index 3c6223ce..0558dfc2 100644 +--- a/slirp/src/util.h ++++ b/slirp/src/util.h +@@ -177,4 +177,7 @@ static inline int slirp_socket_set_fast_reuse(int fd) + + void slirp_pstrcpy(char *buf, int buf_size, const char *str); + ++int slirp_fmt(char *str, size_t size, const char *format, ...); ++int slirp_fmt0(char *str, size_t size, const char *format, ...); ++ + #endif +-- +2.23.0 diff --git a/util-hbitmap-strict-hbitmap_reset.patch b/util-hbitmap-strict-hbitmap_reset.patch new file mode 100644 index 0000000000000000000000000000000000000000..b7f568f1bc6d21ae6923a552c2536414d5d33fdd --- /dev/null +++ b/util-hbitmap-strict-hbitmap_reset.patch @@ -0,0 +1,77 @@ +From fcd7cba6acb7344aca70f5f8ec16626e817b35a5 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Tue, 6 Aug 2019 18:26:11 +0300 +Subject: [PATCH] util/hbitmap: strict hbitmap_reset + +hbitmap_reset has an unobvious property: it rounds requested region up. +It may provoke bugs, like in recently fixed write-blocking mode of +mirror: user calls reset on unaligned region, not keeping in mind that +there are possible unrelated dirty bytes, covered by rounded-up region +and information of this unrelated "dirtiness" will be lost. + +Make hbitmap_reset strict: assert that arguments are aligned, allowing +only one exception when @start + @count == hb->orig_size. It's needed +to comfort users of hbitmap_next_dirty_area, which cares about +hb->orig_size. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Max Reitz +Message-Id: <20190806152611.280389-1-vsementsov@virtuozzo.com> +[Maintainer edit: Max's suggestions from on-list. --js] +[Maintainer edit: Eric's suggestion for aligned macro. --js] +Signed-off-by: John Snow +(cherry picked from commit 48557b138383aaf69c2617ca9a88bfb394fc50ec) +*prereq for fed33bd175f663cc8c13f8a490a4f35a19756cfe +Signed-off-by: Michael Roth +--- + include/qemu/hbitmap.h | 5 +++++ + tests/test-hbitmap.c | 2 +- + util/hbitmap.c | 4 ++++ + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h +index 4afbe6292e..1bf944ca3d 100644 +--- a/include/qemu/hbitmap.h ++++ b/include/qemu/hbitmap.h +@@ -132,6 +132,11 @@ void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count); + * @count: Number of bits to reset. + * + * Reset a consecutive range of bits in an HBitmap. ++ * @start and @count must be aligned to bitmap granularity. The only exception ++ * is resetting the tail of the bitmap: @count may be equal to hb->orig_size - ++ * @start, in this case @count may be not aligned. The sum of @start + @count is ++ * allowed to be greater than hb->orig_size, but only if @start < hb->orig_size ++ * and @start + @count = ALIGN_UP(hb->orig_size, granularity). + */ + void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count); + +diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c +index 592d8219db..2be56d1597 100644 +--- a/tests/test-hbitmap.c ++++ b/tests/test-hbitmap.c +@@ -423,7 +423,7 @@ static void test_hbitmap_granularity(TestHBitmapData *data, + hbitmap_test_check(data, 0); + hbitmap_test_set(data, 0, 3); + g_assert_cmpint(hbitmap_count(data->hb), ==, 4); +- hbitmap_test_reset(data, 0, 1); ++ hbitmap_test_reset(data, 0, 2); + g_assert_cmpint(hbitmap_count(data->hb), ==, 2); + } + +diff --git a/util/hbitmap.c b/util/hbitmap.c +index bcc0acdc6a..71c6ba2c52 100644 +--- a/util/hbitmap.c ++++ b/util/hbitmap.c +@@ -476,6 +476,10 @@ void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count) + /* Compute range in the last layer. */ + uint64_t first; + uint64_t last = start + count - 1; ++ uint64_t gran = 1ULL << hb->granularity; ++ ++ assert(QEMU_IS_ALIGNED(start, gran)); ++ assert(QEMU_IS_ALIGNED(count, gran) || (start + count == hb->orig_size)); + + trace_hbitmap_reset(hb, start, count, + start >> hb->granularity, last >> hb->granularity); +-- +2.23.0 diff --git a/util-iov-improve-qemu_iovec_is_zero.patch b/util-iov-improve-qemu_iovec_is_zero.patch new file mode 100644 index 0000000000000000000000000000000000000000..0cca67b8b1ed17eb873514c177eb6e371ae21f17 --- /dev/null +++ b/util-iov-improve-qemu_iovec_is_zero.patch @@ -0,0 +1,102 @@ +From b3b76fc643912d2c86b13caff30a1151f2958702 Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Tue, 4 Jun 2019 19:15:04 +0300 +Subject: [PATCH] util/iov: improve qemu_iovec_is_zero + +We'll need to check a part of qiov soon, so implement it now. + +Optimization with align down to 4 * sizeof(long) is dropped due to: +1. It is strange: it aligns length of the buffer, but where is a + guarantee that buffer pointer is aligned itself? +2. buffer_is_zero() is a better place for optimizations and it has + them. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Acked-by: Stefan Hajnoczi +Message-id: 20190604161514.262241-3-vsementsov@virtuozzo.com +Message-Id: <20190604161514.262241-3-vsementsov@virtuozzo.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit f76889e7b947d896db51be8a4d9c941c2f70365a) +*prereq for 292d06b9 +Signed-off-by: Michael Roth +--- + block/io.c | 2 +- + include/qemu/iov.h | 2 +- + util/iov.c | 31 +++++++++++++++++++------------ + 3 files changed, 21 insertions(+), 14 deletions(-) + +diff --git a/block/io.c b/block/io.c +index 06305c6ea6..dccf687acc 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -1715,7 +1715,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, + + if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && + !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes && +- qemu_iovec_is_zero(qiov)) { ++ qemu_iovec_is_zero(qiov, 0, qiov->size)) { + flags |= BDRV_REQ_ZERO_WRITE; + if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { + flags |= BDRV_REQ_MAY_UNMAP; +diff --git a/include/qemu/iov.h b/include/qemu/iov.h +index f3787a0cf7..29957c8a72 100644 +--- a/include/qemu/iov.h ++++ b/include/qemu/iov.h +@@ -212,7 +212,7 @@ void qemu_iovec_concat(QEMUIOVector *dst, + size_t qemu_iovec_concat_iov(QEMUIOVector *dst, + struct iovec *src_iov, unsigned int src_cnt, + size_t soffset, size_t sbytes); +-bool qemu_iovec_is_zero(QEMUIOVector *qiov); ++bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes); + void qemu_iovec_destroy(QEMUIOVector *qiov); + void qemu_iovec_reset(QEMUIOVector *qiov); + size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, +diff --git a/util/iov.c b/util/iov.c +index 366ff9cdd1..9ac0261853 100644 +--- a/util/iov.c ++++ b/util/iov.c +@@ -451,23 +451,30 @@ void qemu_iovec_init_extended( + } + + /* +- * Check if the contents of the iovecs are all zero ++ * Check if the contents of subrange of qiov data is all zeroes. + */ +-bool qemu_iovec_is_zero(QEMUIOVector *qiov) ++bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t offset, size_t bytes) + { +- int i; +- for (i = 0; i < qiov->niov; i++) { +- size_t offs = QEMU_ALIGN_DOWN(qiov->iov[i].iov_len, 4 * sizeof(long)); +- uint8_t *ptr = qiov->iov[i].iov_base; +- if (offs && !buffer_is_zero(qiov->iov[i].iov_base, offs)) { ++ struct iovec *iov; ++ size_t current_offset; ++ ++ assert(offset + bytes <= qiov->size); ++ ++ iov = iov_skip_offset(qiov->iov, offset, ¤t_offset); ++ ++ while (bytes) { ++ uint8_t *base = (uint8_t *)iov->iov_base + current_offset; ++ size_t len = MIN(iov->iov_len - current_offset, bytes); ++ ++ if (!buffer_is_zero(base, len)) { + return false; + } +- for (; offs < qiov->iov[i].iov_len; offs++) { +- if (ptr[offs]) { +- return false; +- } +- } ++ ++ current_offset = 0; ++ bytes -= len; ++ iov++; + } ++ + return true; + } + +-- +2.23.0 diff --git a/util-iov-introduce-qemu_iovec_init_extended.patch b/util-iov-introduce-qemu_iovec_init_extended.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a488a63413b69816576ff8394f1e282c292e7d7 --- /dev/null +++ b/util-iov-introduce-qemu_iovec_init_extended.patch @@ -0,0 +1,177 @@ +From cff024fe856ab36db3056ba4cb1d7cfa4c39795d Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Tue, 4 Jun 2019 19:15:03 +0300 +Subject: [PATCH] util/iov: introduce qemu_iovec_init_extended + +Introduce new initialization API, to create requests with padding. Will +be used in the following patch. New API uses qemu_iovec_init_buf if +resulting io vector has only one element, to avoid extra allocations. +So, we need to update qemu_iovec_destroy to support destroying such +QIOVs. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Acked-by: Stefan Hajnoczi +Message-id: 20190604161514.262241-2-vsementsov@virtuozzo.com +Message-Id: <20190604161514.262241-2-vsementsov@virtuozzo.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit d953169d4840f312d3b9a54952f4a7ccfcb3b311) +*prereq for 292d06b9 +Signed-off-by: Michael Roth +--- + include/qemu/iov.h | 7 +++ + util/iov.c | 112 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 114 insertions(+), 5 deletions(-) + +diff --git a/include/qemu/iov.h b/include/qemu/iov.h +index 48b45987b7..f3787a0cf7 100644 +--- a/include/qemu/iov.h ++++ b/include/qemu/iov.h +@@ -199,6 +199,13 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov) + + void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); + void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); ++void qemu_iovec_init_extended( ++ QEMUIOVector *qiov, ++ void *head_buf, size_t head_len, ++ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len, ++ void *tail_buf, size_t tail_len); ++void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, ++ size_t offset, size_t len); + void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); + void qemu_iovec_concat(QEMUIOVector *dst, + QEMUIOVector *src, size_t soffset, size_t sbytes); +diff --git a/util/iov.c b/util/iov.c +index 74e6ca8ed7..366ff9cdd1 100644 +--- a/util/iov.c ++++ b/util/iov.c +@@ -353,6 +353,103 @@ void qemu_iovec_concat(QEMUIOVector *dst, + qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); + } + ++/* ++ * qiov_find_iov ++ * ++ * Return pointer to iovec structure, where byte at @offset in original vector ++ * @iov exactly is. ++ * Set @remaining_offset to be offset inside that iovec to the same byte. ++ */ ++static struct iovec *iov_skip_offset(struct iovec *iov, size_t offset, ++ size_t *remaining_offset) ++{ ++ while (offset > 0 && offset >= iov->iov_len) { ++ offset -= iov->iov_len; ++ iov++; ++ } ++ *remaining_offset = offset; ++ ++ return iov; ++} ++ ++/* ++ * qiov_slice ++ * ++ * Find subarray of iovec's, containing requested range. @head would ++ * be offset in first iov (returned by the function), @tail would be ++ * count of extra bytes in last iovec (returned iov + @niov - 1). ++ */ ++static struct iovec *qiov_slice(QEMUIOVector *qiov, ++ size_t offset, size_t len, ++ size_t *head, size_t *tail, int *niov) ++{ ++ struct iovec *iov, *end_iov; ++ ++ assert(offset + len <= qiov->size); ++ ++ iov = iov_skip_offset(qiov->iov, offset, head); ++ end_iov = iov_skip_offset(iov, *head + len, tail); ++ ++ if (*tail > 0) { ++ assert(*tail < end_iov->iov_len); ++ *tail = end_iov->iov_len - *tail; ++ end_iov++; ++ } ++ ++ *niov = end_iov - iov; ++ ++ return iov; ++} ++ ++/* ++ * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov, ++ * and @tail_buf buffer into new qiov. ++ */ ++void qemu_iovec_init_extended( ++ QEMUIOVector *qiov, ++ void *head_buf, size_t head_len, ++ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len, ++ void *tail_buf, size_t tail_len) ++{ ++ size_t mid_head, mid_tail; ++ int total_niov, mid_niov = 0; ++ struct iovec *p, *mid_iov; ++ ++ if (mid_len) { ++ mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len, ++ &mid_head, &mid_tail, &mid_niov); ++ } ++ ++ total_niov = !!head_len + mid_niov + !!tail_len; ++ if (total_niov == 1) { ++ qemu_iovec_init_buf(qiov, NULL, 0); ++ p = &qiov->local_iov; ++ } else { ++ qiov->niov = qiov->nalloc = total_niov; ++ qiov->size = head_len + mid_len + tail_len; ++ p = qiov->iov = g_new(struct iovec, qiov->niov); ++ } ++ ++ if (head_len) { ++ p->iov_base = head_buf; ++ p->iov_len = head_len; ++ p++; ++ } ++ ++ if (mid_len) { ++ memcpy(p, mid_iov, mid_niov * sizeof(*p)); ++ p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head; ++ p[0].iov_len -= mid_head; ++ p[mid_niov - 1].iov_len -= mid_tail; ++ p += mid_niov; ++ } ++ ++ if (tail_len) { ++ p->iov_base = tail_buf; ++ p->iov_len = tail_len; ++ } ++} ++ + /* + * Check if the contents of the iovecs are all zero + */ +@@ -374,14 +471,19 @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov) + return true; + } + ++void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, ++ size_t offset, size_t len) ++{ ++ qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0); ++} ++ + void qemu_iovec_destroy(QEMUIOVector *qiov) + { +- assert(qiov->nalloc != -1); ++ if (qiov->nalloc != -1) { ++ g_free(qiov->iov); ++ } + +- qemu_iovec_reset(qiov); +- g_free(qiov->iov); +- qiov->nalloc = 0; +- qiov->iov = NULL; ++ memset(qiov, 0, sizeof(*qiov)); + } + + void qemu_iovec_reset(QEMUIOVector *qiov) +-- +2.23.0 diff --git a/vhost-user-save-features-if-the-char-dev-is-closed.patch b/vhost-user-save-features-if-the-char-dev-is-closed.patch new file mode 100644 index 0000000000000000000000000000000000000000..9a0d04f4d7d98fd97e84bfba35f99d4871605b37 --- /dev/null +++ b/vhost-user-save-features-if-the-char-dev-is-closed.patch @@ -0,0 +1,42 @@ +From 7b404cae7fa2850d476c29258f03b8e77a5b4bd0 Mon Sep 17 00:00:00 2001 +From: Adrian Moreno +Date: Tue, 24 Sep 2019 18:20:44 +0200 +Subject: [PATCH] vhost-user: save features if the char dev is closed + +That way the state can be correctly restored when the device is opened +again. This might happen if the backend is restarted. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1738768 +Reported-by: Pei Zhang +Fixes: 6ab79a20af3a ("do not call vhost_net_cleanup() on running net from char user event") +Cc: ddstreet@canonical.com +Cc: Michael S. Tsirkin +Cc: qemu-stable@nongnu.org +Signed-off-by: Adrian Moreno +Message-Id: <20190924162044.11414-1-amorenoz@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit c6beefd674fff8d41b90365dfccad32e53a5abcb) +Signed-off-by: Michael Roth +--- + net/vhost-user.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/vhost-user.c b/net/vhost-user.c +index 51921de443..014199d600 100644 +--- a/net/vhost-user.c ++++ b/net/vhost-user.c +@@ -235,6 +235,10 @@ static void chr_closed_bh(void *opaque) + + s = DO_UPCAST(NetVhostUserState, nc, ncs[0]); + ++ if (s->vhost_net) { ++ s->acked_features = vhost_net_get_acked_features(s->vhost_net); ++ } ++ + qmp_set_link(name, false, &err); + + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, +-- +2.23.0 diff --git a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch b/vhost-user-scsi-prevent-using-uninitialized-vqs.patch index 9c4f92316d4da5e9e53ddc17e9915427e3cd9c36..d1bf2a087bf4fcbedf2a8c0fbb8b62188737d1e7 100644 --- a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch +++ b/vhost-user-scsi-prevent-using-uninitialized-vqs.patch @@ -1,7 +1,7 @@ -From 19d56f560879081de411f359417eaaa2998c9e3a Mon Sep 17 00:00:00 2001 +From 4d8f2885b3f1219c3df2cf1a00dc0c55b23ee715 Mon Sep 17 00:00:00 2001 From: Raphael Norwitz -Date: Tue, 11 Jun 2019 17:35:17 -0700 -Subject: [PATCH 5/5] vhost-user-scsi: prevent using uninitialized vqs +Date: Tue, 14 Apr 2020 21:39:05 +0800 +Subject: [PATCH] vhost-user-scsi: prevent using uninitialized vqs Of the 3 virtqueues, seabios only sets cmd, leaving ctrl and event without a physical address. This can cause @@ -26,18 +26,17 @@ Signed-off-by: Stefan Hajnoczi 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c -index 8b1e687..241631f 100644 +index fcee67d5..affc2431 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c -@@ -90,7 +90,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) +@@ -91,7 +91,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) } - + vsc->dev.nvqs = 2 + vs->conf.num_queues; - vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs); + vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; - --- -1.8.3.1 - + vqs = vsc->dev.vqs; +-- +2.23.0 diff --git a/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch b/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c2a3f2a424bd30ff95b8fcb53ae23c324d43153 --- /dev/null +++ b/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch @@ -0,0 +1,80 @@ +From 01be50603be4f17af4318a7a3fe58dcc6dab1b31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 16 Aug 2019 19:15:03 +0200 +Subject: [PATCH] virtio-blk: Cancel the pending BH when the dataplane is reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When 'system_reset' is called, the main loop clear the memory +region cache before the BH has a chance to execute. Later when +the deferred function is called, some assumptions that were +made when scheduling them are no longer true when they actually +execute. + +This is what happens using a virtio-blk device (fresh RHEL7.8 install): + + $ (sleep 12.3; echo system_reset; sleep 12.3; echo system_reset; sleep 1; echo q) \ + | qemu-system-x86_64 -m 4G -smp 8 -boot menu=on \ + -device virtio-blk-pci,id=image1,drive=drive_image1 \ + -drive file=/var/lib/libvirt/images/rhel78.qcow2,if=none,id=drive_image1,format=qcow2,cache=none \ + -device virtio-net-pci,netdev=net0,id=nic0,mac=52:54:00:c4:e7:84 \ + -netdev tap,id=net0,script=/bin/true,downscript=/bin/true,vhost=on \ + -monitor stdio -serial null -nographic + (qemu) system_reset + (qemu) system_reset + (qemu) qemu-system-x86_64: hw/virtio/virtio.c:225: vring_get_region_caches: Assertion `caches != NULL' failed. + Aborted + + (gdb) bt + Thread 1 (Thread 0x7f109c17b680 (LWP 10939)): + #0 0x00005604083296d1 in vring_get_region_caches (vq=0x56040a24bdd0) at hw/virtio/virtio.c:227 + #1 0x000056040832972b in vring_avail_flags (vq=0x56040a24bdd0) at hw/virtio/virtio.c:235 + #2 0x000056040832d13d in virtio_should_notify (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1648 + #3 0x000056040832d1f8 in virtio_notify_irqfd (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1662 + #4 0x00005604082d213d in notify_guest_bh (opaque=0x56040a243ec0) at hw/block/dataplane/virtio-blk.c:75 + #5 0x000056040883dc35 in aio_bh_call (bh=0x56040a243f10) at util/async.c:90 + #6 0x000056040883dccd in aio_bh_poll (ctx=0x560409161980) at util/async.c:118 + #7 0x0000560408842af7 in aio_dispatch (ctx=0x560409161980) at util/aio-posix.c:460 + #8 0x000056040883e068 in aio_ctx_dispatch (source=0x560409161980, callback=0x0, user_data=0x0) at util/async.c:261 + #9 0x00007f10a8fca06d in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 + #10 0x0000560408841445 in glib_pollfds_poll () at util/main-loop.c:215 + #11 0x00005604088414bf in os_host_main_loop_wait (timeout=0) at util/main-loop.c:238 + #12 0x00005604088415c4 in main_loop_wait (nonblocking=0) at util/main-loop.c:514 + #13 0x0000560408416b1e in main_loop () at vl.c:1923 + #14 0x000056040841e0e8 in main (argc=20, argv=0x7ffc2c3f9c58, envp=0x7ffc2c3f9d00) at vl.c:4578 + +Fix this by cancelling the BH when the virtio dataplane is stopped. + +[This is version of the patch was modified as discussed with Philippe on +the mailing list thread. +--Stefan] + +Reported-by: Yihuang Yu +Suggested-by: Stefan Hajnoczi +Fixes: https://bugs.launchpad.net/qemu/+bug/1839428 +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20190816171503.24761-1-philmd@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit ebb6ff25cd888a52a64a9adc3692541c6d1d9a42) +Signed-off-by: Michael Roth +--- + hw/block/dataplane/virtio-blk.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 158c78f852..5fea76df85 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -297,6 +297,9 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) + virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); + } + ++ qemu_bh_cancel(s->bh); ++ notify_guest_bh(s); /* final chance to notify guest */ ++ + /* Clean up guest notifier (irq) */ + k->set_guest_notifiers(qbus->parent, nvqs, false); + +-- +2.23.0 diff --git a/virtio-net-prevent-offloads-reset-on-migration.patch b/virtio-net-prevent-offloads-reset-on-migration.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab8fbe26115279359c6a3928e93bf134ca88a2cb --- /dev/null +++ b/virtio-net-prevent-offloads-reset-on-migration.patch @@ -0,0 +1,122 @@ +From 4887acf574a573137660aa98d9d422ece0a41a5a Mon Sep 17 00:00:00 2001 +From: Mikhail Sennikovsky +Date: Fri, 11 Oct 2019 15:58:04 +0200 +Subject: [PATCH] virtio-net: prevent offloads reset on migration + +Currently offloads disabled by guest via the VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET +command are not preserved on VM migration. +Instead all offloads reported by guest features (via VIRTIO_PCI_GUEST_FEATURES) +get enabled. +What happens is: first the VirtIONet::curr_guest_offloads gets restored and offloads +are getting set correctly: + + #0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=0, tso6=0, ecn=0, ufo=0) at net/net.c:474 + #1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720 + #2 virtio_net_post_load_device (opaque=0x555557701ca0, version_id=11) at hw/net/virtio-net.c:2334 + #3 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577c80 , opaque=0x555557701ca0, version_id=11) + at migration/vmstate.c:168 + #4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2197 + #5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036 + #6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 , opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143 + #7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829 + #8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211 + #9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395 + #10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467 + #11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449 + +However later on the features are getting restored, and offloads get reset to +everything supported by features: + + #0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=1, tso6=1, ecn=0, ufo=0) at net/net.c:474 + #1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720 + #2 virtio_net_set_features (vdev=0x555557701ca0, features=5104441767) at hw/net/virtio-net.c:773 + #3 virtio_set_features_nocheck (vdev=0x555557701ca0, val=5104441767) at hw/virtio/virtio.c:2052 + #4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2220 + #5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036 + #6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 , opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143 + #7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829 + #8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211 + #9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395 + #10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467 + #11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449 + +Fix this by preserving the state in saved_guest_offloads field and +pushing out offload initialization to the new post load hook. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Mikhail Sennikovsky +Signed-off-by: Jason Wang +(cherry picked from commit 7788c3f2e21e35902d45809b236791383bbb613e) +Signed-off-by: Michael Roth +--- + hw/net/virtio-net.c | 27 ++++++++++++++++++++++++--- + include/hw/virtio/virtio-net.h | 2 ++ + 2 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index b9e1cd71cf..6adb0fe252 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2330,9 +2330,13 @@ static int virtio_net_post_load_device(void *opaque, int version_id) + n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); + } + +- if (peer_has_vnet_hdr(n)) { +- virtio_net_apply_guest_offloads(n); +- } ++ /* ++ * curr_guest_offloads will be later overwritten by the ++ * virtio_set_features_nocheck call done from the virtio_load. ++ * Here we make sure it is preserved and restored accordingly ++ * in the virtio_net_post_load_virtio callback. ++ */ ++ n->saved_guest_offloads = n->curr_guest_offloads; + + virtio_net_set_queues(n); + +@@ -2367,6 +2371,22 @@ static int virtio_net_post_load_device(void *opaque, int version_id) + return 0; + } + ++static int virtio_net_post_load_virtio(VirtIODevice *vdev) ++{ ++ VirtIONet *n = VIRTIO_NET(vdev); ++ /* ++ * The actual needed state is now in saved_guest_offloads, ++ * see virtio_net_post_load_device for detail. ++ * Restore it back and apply the desired offloads. ++ */ ++ n->curr_guest_offloads = n->saved_guest_offloads; ++ if (peer_has_vnet_hdr(n)) { ++ virtio_net_apply_guest_offloads(n); ++ } ++ ++ return 0; ++} ++ + /* tx_waiting field of a VirtIONetQueue */ + static const VMStateDescription vmstate_virtio_net_queue_tx_waiting = { + .name = "virtio-net-queue-tx_waiting", +@@ -2909,6 +2929,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) + vdc->guest_notifier_mask = virtio_net_guest_notifier_mask; + vdc->guest_notifier_pending = virtio_net_guest_notifier_pending; + vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); ++ vdc->post_load = virtio_net_post_load_virtio; + vdc->vmsd = &vmstate_virtio_net_device; + } + +diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h +index b96f0c643f..07a9319f4b 100644 +--- a/include/hw/virtio/virtio-net.h ++++ b/include/hw/virtio/virtio-net.h +@@ -182,6 +182,8 @@ struct VirtIONet { + char *netclient_name; + char *netclient_type; + uint64_t curr_guest_offloads; ++ /* used on saved state restore phase to preserve the curr_guest_offloads */ ++ uint64_t saved_guest_offloads; + AnnounceTimer announce_timer; + bool needs_vnet_hdr_swap; + bool mtu_bypass_backend; +-- +2.23.0 diff --git a/virtio-new-post_load-hook.patch b/virtio-new-post_load-hook.patch new file mode 100644 index 0000000000000000000000000000000000000000..974f286c6730c66cc3cb0a64b046bea341dd262b --- /dev/null +++ b/virtio-new-post_load-hook.patch @@ -0,0 +1,63 @@ +From 8010d3fce008dd13f155bc0babfe236ea44a2712 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Fri, 11 Oct 2019 15:58:03 +0200 +Subject: [PATCH] virtio: new post_load hook + +Post load hook in virtio vmsd is called early while device is processed, +and when VirtIODevice core isn't fully initialized. Most device +specific code isn't ready to deal with a device in such state, and +behaves weirdly. + +Add a new post_load hook in a device class instead. Devices should use +this unless they specifically want to verify the migration stream as +it's processed, e.g. for bounds checking. + +Cc: qemu-stable@nongnu.org +Suggested-by: "Dr. David Alan Gilbert" +Cc: Mikhail Sennikovsky +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +(cherry picked from commit 1dd713837cac8ec5a97d3b8492d72ce5ac94803c) +Signed-off-by: Michael Roth +--- + hw/virtio/virtio.c | 7 +++++++ + include/hw/virtio/virtio.h | 6 ++++++ + 2 files changed, 13 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index a94ea18a9c..7c3822c3a0 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2287,6 +2287,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) + } + rcu_read_unlock(); + ++ if (vdc->post_load) { ++ ret = vdc->post_load(vdev); ++ if (ret) { ++ return ret; ++ } ++ } ++ + return 0; + } + +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index b189788cb2..f9f62370e9 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -158,6 +158,12 @@ typedef struct VirtioDeviceClass { + */ + void (*save)(VirtIODevice *vdev, QEMUFile *f); + int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); ++ /* Post load hook in vmsd is called early while device is processed, and ++ * when VirtIODevice isn't fully initialized. Devices should use this instead, ++ * unless they specifically want to verify the migration stream as it's ++ * processed, e.g. for bounds checking. ++ */ ++ int (*post_load)(VirtIODevice *vdev); + const VMStateDescription *vmsd; + } VirtioDeviceClass; + +-- +2.23.0 diff --git a/vpc-Return-0-from-vpc_co_create-on-success.patch b/vpc-Return-0-from-vpc_co_create-on-success.patch new file mode 100644 index 0000000000000000000000000000000000000000..46fbd90d1bd39f5549ce5d0185d58bbd437a82aa --- /dev/null +++ b/vpc-Return-0-from-vpc_co_create-on-success.patch @@ -0,0 +1,49 @@ +From 97c478c355fee96eb2b740313f50561e69b6f305 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 2 Sep 2019 21:33:16 +0200 +Subject: [PATCH] vpc: Return 0 from vpc_co_create() on success + +blockdev_create_run() directly uses .bdrv_co_create()'s return value as +the job's return value. Jobs must return 0 on success, not just any +nonnegative value. Therefore, using blockdev-create for VPC images may +currently fail as the vpc driver may return a positive integer. + +Because there is no point in returning a positive integer anywhere in +the block layer (all non-negative integers are generally treated as +complete success), we probably do not want to add more such cases. +Therefore, fix this problem by making the vpc driver always return 0 in +case of success. + +Suggested-by: Kevin Wolf +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 1a37e3124407b5a145d44478d3ecbdb89c63789f) +Signed-off-by: Michael Roth +--- + block/vpc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/vpc.c b/block/vpc.c +index d4776ee8a5..3a88e28e2b 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -885,6 +885,7 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf, + goto fail; + } + ++ ret = 0; + fail: + return ret; + } +@@ -908,7 +909,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, + return ret; + } + +- return ret; ++ return 0; + } + + static int calculate_rounded_image_size(BlockdevCreateOptionsVpc *vpc_opts, +-- +2.23.0 diff --git a/vtimer-compat-cross-version-migration-from-v4.0.1.patch b/vtimer-compat-cross-version-migration-from-v4.0.1.patch new file mode 100644 index 0000000000000000000000000000000000000000..f452948fd29818c9551899e5044de1e3b33bc235 --- /dev/null +++ b/vtimer-compat-cross-version-migration-from-v4.0.1.patch @@ -0,0 +1,41 @@ +From aec34c33730c36b34e4442548885463f57100e13 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Fri, 8 May 2020 11:25:28 +0800 +Subject: [PATCH] vtimer: compat cross version migration from v4.0.1 + +vtimer feature was added to qemu v4.0.1 to record timer tick when vcpu +is stopped. However this feature is discared and the new virtual time +adjustment is introduced. + +This patch add the missing vtimer parameter to ARMCPUState in order +to compat cross version migration fromm v4.0.1 openEuler 2003 lts release. + +Singed-off-by: Ying Fang + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 219c222b..2609113d 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -261,6 +261,8 @@ typedef struct CPUARMState { + uint64_t elr_el[4]; /* AArch64 exception link regs */ + uint64_t sp_el[4]; /* AArch64 banked stack pointers */ + ++ uint64_t vtimer; /* Timer tick when vcpu is stopped */ ++ + /* System control coprocessor (cp15) */ + struct { + uint32_t c0_cpuid; +diff --git a/target/arm/machine.c b/target/arm/machine.c +index ee3c59a6..ec28b839 100644 +--- a/target/arm/machine.c ++++ b/target/arm/machine.c +@@ -814,6 +814,7 @@ const VMStateDescription vmstate_arm_cpu = { + VMSTATE_UINT32(env.exception.syndrome, ARMCPU), + VMSTATE_UINT32(env.exception.fsr, ARMCPU), + VMSTATE_UINT64(env.exception.vaddress, ARMCPU), ++ VMSTATE_UINT64(env.vtimer, ARMCPU), + VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU), + VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU), + { +-- +2.23.0 diff --git a/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch b/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc17f48b7a395bafffaf7ef9763d04bff110af0a --- /dev/null +++ b/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch @@ -0,0 +1,60 @@ +From 725dfa851f8e1de8653f41a4bd38c7f98757eb40 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 2 Sep 2019 08:02:22 -0400 +Subject: [PATCH] x86: do not advertise die-id in query-hotpluggbale-cpus if + '-smp dies' is not set + +Commit 176d2cda0 (i386/cpu: Consolidate die-id validity in smp context) added +new 'die-id' topology property to CPUs and exposed it via QMP command +query-hotpluggable-cpus, which broke -device/device_add cpu-foo for existing +users that do not support die-id/dies yet. That's would be fine if it happened +to new machine type only but it also happened to old machine types, +which breaks migration from old QEMU to the new one, for example following CLI: + + OLD-QEMU -M pc-i440fx-4.0 -smp 1,max_cpus=2 \ + -device qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id +is not able to start with new QEMU, complaining about invalid die-id. + +After discovering regression, the patch + "pc: Don't make die-id mandatory unless necessary" +makes die-id optional so old CLI would work. + +However it's not enough as new QEMU still exposes die-id via query-hotpluggbale-cpus +QMP command, so the users that started old machine type on new QEMU, using all +properties (including die-id) received from QMP command (as required), won't be +able to start old QEMU using the same properties since it doesn't support die-id. + +Fix it by hiding die-id in query-hotpluggbale-cpus for all machine types in case +'-smp dies' is not provided on CLI or -smp dies = 1', in which case smp_dies == 1 +and APIC ID is calculated in default way (as it was before DIE support) so we won't +need compat code as in both cases the topology provided to guest via CPUID is the same. + +Signed-off-by: Igor Mammedov +Message-Id: <20190902120222.6179-1-imammedo@redhat.com> +Reviewed-by: Eduardo Habkost +Signed-off-by: Eduardo Habkost +(cherry picked from commit c6c1bb89fb46f3b88f832e654cf5a6f7941aac51) +Signed-off-by: Michael Roth +--- + hw/i386/pc.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 947f81070f..d011733ff7 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -2887,8 +2887,10 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms) + ms->smp.threads, &topo); + ms->possible_cpus->cpus[i].props.has_socket_id = true; + ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id; +- ms->possible_cpus->cpus[i].props.has_die_id = true; +- ms->possible_cpus->cpus[i].props.die_id = topo.die_id; ++ if (pcms->smp_dies > 1) { ++ ms->possible_cpus->cpus[i].props.has_die_id = true; ++ ms->possible_cpus->cpus[i].props.die_id = topo.die_id; ++ } + ms->possible_cpus->cpus[i].props.has_core_id = true; + ms->possible_cpus->cpus[i].props.core_id = topo.core_id; + ms->possible_cpus->cpus[i].props.has_thread_id = true; +-- +2.23.0