!54 rebase openEuler-20.03-LTS branch to master

Merge pull request !54 from FangYing/master
This commit is contained in:
openeuler-ci-bot 2020-06-05 10:46:19 +08:00 committed by Gitee
commit a4372444dd
138 changed files with 13211 additions and 798 deletions

View File

@ -1,8 +1,11 @@
From f3c1fc4dce1582ccc1754899d5149d233e8629ff Mon Sep 17 00:00:00 2001 From e3a7ec839fa4f823666d726989c375dcf73348a4 Mon Sep 17 00:00:00 2001
From: Eric Auger <eric.auger@redhat.com> From: Ying Fang <fangying1@huawei.com>
Date: Thu, 3 Oct 2019 17:46:40 +0200 Date: Wed, 15 Apr 2020 16:14:50 +0800
Subject: [PATCH 3/3] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for Subject: [PATCH] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus >
smp_cpus > 256 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 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 for ARM. The actual capability to instantiate more than 256 vcpus
@ -21,26 +24,27 @@ Message-id: 20191003154640.22451-4-eric.auger@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd) (cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd)
[yu: Use the legacy smp_cpus instead of ms->smp.cpus, as we don't have [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 ¦struct CpuTopology in MachineState at that time. See commit
edeeec911702 for details.] ¦edeeec911702 for details.]
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com> Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
--- ---
target/arm/kvm.c | 10 +++++++++- target/arm/kvm.c | 11 ++++++++++-
1 file changed, 9 insertions(+), 1 deletion(-) 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index f60185ad..383423c4 100644 index 50e86f8b..cc7a46df 100644
--- a/target/arm/kvm.c --- a/target/arm/kvm.c
+++ b/target/arm/kvm.c +++ b/target/arm/kvm.c
@@ -174,6 +174,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) @@ -173,6 +173,8 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
int kvm_arch_init(MachineState *ms, KVMState *s) int kvm_arch_init(MachineState *ms, KVMState *s)
{ {
+ int ret = 0; + int ret = 0;
+ unsigned int smp_cpus = ms->smp.cpus;
/* For ARM interrupt delivery is always asynchronous, /* For ARM interrupt delivery is always asynchronous,
* whether we are using an in-kernel VGIC or not. * whether we are using an in-kernel VGIC or not.
*/ */
@@ -187,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s) @@ -186,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
@ -57,5 +61,4 @@ index f60185ad..383423c4 100644
unsigned long kvm_arch_vcpu_id(CPUState *cpu) unsigned long kvm_arch_vcpu_id(CPUState *cpu)
-- --
2.19.1 2.23.0

View File

@ -1,6 +1,6 @@
From d2fd6d1a5200b9a58863839d21d291cd4f76ac31 Mon Sep 17 00:00:00 2001 From 4646a24045cf53f2cc5e0ef1974da88ef50ef676 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com> From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 15:47:27 +0800 Date: Wed, 27 May 2020 11:54:31 +0800
Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped
The vtimer kick still increases even if the vcpu is stopped when VM has The vtimer kick still increases even if the vcpu is stopped when VM has
@ -17,10 +17,10 @@ Signed-off-by: Ying Fang <fangying1@huawei.com>
3 files changed, 61 insertions(+) 3 files changed, 61 insertions(+)
diff --git a/cpus.c b/cpus.c diff --git a/cpus.c b/cpus.c
index e83f72b4..f6ec48a2 100644 index 927a00aa..b9aa51f8 100644
--- a/cpus.c --- a/cpus.c
+++ b/cpus.c +++ b/cpus.c
@@ -1063,6 +1063,28 @@ void cpu_synchronize_all_pre_loadvm(void) @@ -1066,6 +1066,28 @@ void cpu_synchronize_all_pre_loadvm(void)
} }
} }
@ -49,7 +49,7 @@ index e83f72b4..f6ec48a2 100644
static int do_vm_stop(RunState state, bool send_stop) static int do_vm_stop(RunState state, bool send_stop)
{ {
int ret = 0; int ret = 0;
@@ -1070,6 +1092,11 @@ static int do_vm_stop(RunState state, bool send_stop) @@ -1073,6 +1095,11 @@ static int do_vm_stop(RunState state, bool send_stop)
if (runstate_is_running()) { if (runstate_is_running()) {
cpu_disable_ticks(); cpu_disable_ticks();
pause_all_vcpus(); pause_all_vcpus();
@ -61,7 +61,7 @@ index e83f72b4..f6ec48a2 100644
runstate_set(state); runstate_set(state);
vm_state_notify(0, state); vm_state_notify(0, state);
if (send_stop) { if (send_stop) {
@@ -1909,11 +1936,42 @@ void cpu_resume(CPUState *cpu) @@ -1918,11 +1945,42 @@ void cpu_resume(CPUState *cpu)
qemu_cpu_kick(cpu); qemu_cpu_kick(cpu);
} }
@ -105,23 +105,23 @@ index e83f72b4..f6ec48a2 100644
cpu_resume(cpu); cpu_resume(cpu);
} }
diff --git a/target/arm/cpu.h b/target/arm/cpu.h diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d4d28369..e107e395 100644 index 86eb79cd..aec6a214 100644
--- a/target/arm/cpu.h --- a/target/arm/cpu.h
+++ b/target/arm/cpu.h +++ b/target/arm/cpu.h
@@ -270,6 +270,8 @@ typedef struct CPUARMState { @@ -262,6 +262,8 @@ typedef struct CPUARMState {
uint64_t elr_el[4]; /* AArch64 exception link regs */
uint64_t sp_el[4]; /* AArch64 banked stack pointers */ uint64_t sp_el[4]; /* AArch64 banked stack pointers */
+ uint64_t vtimer; /* Timer tick when vcpu stop */ + uint64_t vtimer; /* Timer tick when vcpu stop */
+ +
/* System control coprocessor (cp15) */ /* System control coprocessor (cp15) */
struct { struct {
uint32_t c0_cpuid; uint32_t c0_cpuid;
diff --git a/target/arm/machine.c b/target/arm/machine.c diff --git a/target/arm/machine.c b/target/arm/machine.c
index b2925496..d64a0057 100644 index ee3c59a6..ec28b839 100644
--- a/target/arm/machine.c --- a/target/arm/machine.c
+++ b/target/arm/machine.c +++ b/target/arm/machine.c
@@ -792,6 +792,7 @@ const VMStateDescription vmstate_arm_cpu = { @@ -814,6 +814,7 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT32(env.exception.syndrome, ARMCPU), VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
VMSTATE_UINT32(env.exception.fsr, ARMCPU), VMSTATE_UINT32(env.exception.fsr, ARMCPU),
VMSTATE_UINT64(env.exception.vaddress, ARMCPU), VMSTATE_UINT64(env.exception.vaddress, ARMCPU),

View File

@ -0,0 +1,88 @@
From 73a5bf472921068e6db10e7e325b7ac46f111834 Mon Sep 17 00:00:00 2001
From: John Snow <jsnow@redhat.com>
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 <shaju.abraham@nutanix.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Message-id: 20190729223605.7163-1-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit 8ec41c4265714255d5a138f8b538faf3583dcff6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,37 @@
From ced290d644a00e18e70046194d042bcaa2703b65 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Wed, 27 May 2020 11:16:53 +0800
Subject: [PATCH] Revert: "vtimer: compat cross version migration from v4.0.1"
This reverts commit patch:
vtimer-compat-cross-version-migration-from-v4.0.1.patch
Signed-off-by: Ying Fang <fangying1@huawei.com>
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2609113d..86eb79cd 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -261,7 +261,6 @@ 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 {
diff --git a/target/arm/machine.c b/target/arm/machine.c
index ec28b839..ee3c59a6 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -814,7 +814,6 @@ 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

View File

@ -0,0 +1,27 @@
From 843f593280b93e03bb7b0d0001da7488d61f13f6 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
---
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

View File

@ -0,0 +1,63 @@
From 135119d2e82e99adc67346572c761fbe54d73e4a Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,128 @@
From 107c267ebe5b8c461268a4ff8384ad2f2b9e8ce0 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,41 @@
From 3cd6df0b9e7d7b544673ce9a63b405e236d8265b Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,204 @@
From 05d22b55133db1a2526cfe305102e075e883b5e2 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,95 @@
From 0288d98f0ef4d17a73cf2bad1b928cd7c044e318 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,108 @@
From a3097eed8b642dc6fe891112340821e869b90cc2 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -1,8 +1,7 @@
From a2bae876b7f694b12073bac8ad6668e4d975ad88 Mon Sep 17 00:00:00 2001 From 929d29ec7bf9dd6ec3802bea2148a041ff30d59b Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com> From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 10 Apr 2020 16:08:19 +0000 Date: Tue, 14 Apr 2020 21:17:09 +0800
Subject: [PATCH 1/2] aio-wait: delegate polling of main AioContext if BQL not Subject: [PATCH] aio-wait: delegate polling of main AioContext if BQL not held
held
Any thread that is not a iothread returns NULL for qemu_get_current_aio_context(). Any thread that is not a iothread returns NULL for qemu_get_current_aio_context().
As a result, it would also return true for 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 there and to avoid a circular reference between main-loop.h
and block/aio.h. and block/aio.h.
upstream_url: https://patchwork.kernel.org/patch/11482099/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200407140746.8041-5-pbonzini@redhat.com> Message-Id: <20200407140746.8041-5-pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
@ -31,7 +28,7 @@ Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2 files changed, 32 insertions(+), 19 deletions(-) 2 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h 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 --- a/include/block/aio-wait.h
+++ b/include/block/aio-wait.h +++ b/include/block/aio-wait.h
@@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
@ -67,12 +64,12 @@ 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 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 --- a/include/block/aio.h
+++ b/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; QLIST_HEAD(, AioHandler) aio_handlers;
/* Used to avoid unnecessary event_notifier_set calls in aio_notify; /* Used to avoid unnecessary event_notifier_set calls in aio_notify;
@ -95,7 +92,7 @@ index 0ca25dfe..c527893b 100644
* *
* Bit 0 is reserved for GSource usage of the AioContext, and is 1 * 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. * 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); AioContext *qemu_get_current_aio_context(void);
@ -116,5 +113,4 @@ index 0ca25dfe..c527893b 100644
* aio_context_setup: * aio_context_setup:
* @ctx: the aio context * @ctx: the aio context
-- --
2.25.2 2.23.0

View File

@ -0,0 +1,42 @@
From d8e0b51447d8c64788cd7f9b0fa75c4ccb06f8eb Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,66 @@
From 6d287b3f1d961cc4adda1c6a452f41db84466f5a Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,219 @@
From cde57fcae2ed16a10e1ef7f2da0ec368883988ba Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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

View File

@ -0,0 +1,61 @@
From 31873c4c0454fb17654f57adece2bc396415f8bf Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,66 @@
From 7cfb37c50209208f853c6fbd0df6673a95e03ef9 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,100 @@
From d38d1d4e859450535ddc6bf0c7a59f6217b1403c Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,124 @@
From bf47ef282bfe8b0a98e1f87d8708051ffa7192a1 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,159 @@
From 11f9628ceff019259ff12ce469deafbf50eb3075 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,92 @@
From e3a1af72fca5bbcc840fba44d512bbe69ec55ca9 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
Date: Tue, 12 May 2020 15:05:06 +0800
Subject: [PATCH] arm/virt: Support CPU cold plug
This adds CPU cold plug support to arm virt machine board.
CPU cold plug means adding CPU by using "-device xx-arm-cpu"
when we bring up Qemu.
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
---
hw/arm/virt.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 112a6ae7cb..4c7279392f 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2093,25 +2093,12 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
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;
@@ -2137,6 +2124,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo);
}
+ /* Some hotplug capability checks */
+ if (cs->cpu_index >= ms->smp.cpus) {
+ if (!vms->acpi_dev) {
+ error_setg(errp, "CPU cold/hot plug is disabled: "
+ "missing acpi device.");
+ return;
+ }
+ if (!vms->cpu_hotplug_enabled) {
+ error_setg(errp, "CPU cold/hot plug is disabled: "
+ "should use AArch64 CPU and GICv3.");
+ return;
+ }
+ }
+
/* if 'address' properties socket-id/core-id/thread-id are not set, set them
* so that machine_query_hotpluggable_cpus would show correct values
*/
@@ -2237,7 +2238,8 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
ARMGICv3CommonClass *agcc;
Error *local_err = NULL;
- if (dev->hotplugged) {
+ /* For CPU that is cold/hot plugged */
+ if (ncpu >= ms->smp.cpus) {
/* Realize GIC related parts of CPU */
assert(vms->gic_version == 3);
gicv3 = ARM_GICV3_COMMON(vms->gic);
@@ -2250,10 +2252,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
cpu_hotplug_register_reset(ncpu);
cpu_hotplug_reset_manually(ncpu);
cpu_synchronize_post_reset(cs);
+ }
- if (kvm_enabled()) {
- resume_all_vcpus();
- }
+ if (dev->hotplugged && kvm_enabled()) {
+ resume_all_vcpus();
}
if (vms->acpi_dev) {
--
2.19.1

View File

@ -0,0 +1,65 @@
From 91fed8840b004ec7bc91969afa10f03e13f311c4 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
---
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

View File

@ -0,0 +1,121 @@
From 2fdece10dac6161cb6c1f0f05247391aa3269eed Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
---
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

View File

@ -0,0 +1,123 @@
From 92124743f4560c490780a229f53ea5881f706383 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,91 @@
From ac2071c3791b67fc7af78b8ceb320c01ca1b5df7 Mon Sep 17 00:00:00 2001
From: BALATON Zoltan <balaton@eik.bme.hu>
Date: Mon, 6 Apr 2020 22:34:26 +0200
Subject: [PATCH] ati-vga: Fix checks in ati_2d_blt() to avoid crash
In some corner cases (that never happen during normal operation but a
malicious guest could program wrong values) pixman functions were
called with parameters that result in a crash. Fix this and add more
checks to disallow such cases.
Reported-by: Ziming Zhang <ezrakiez@gmail.com>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Message-id: 20200406204029.19559747D5D@zero.eik.bme.hu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 42e82311eb..23a8ae0cd8 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -53,12 +53,20 @@ void ati_2d_blt(ATIVGAState *s)
s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds),
surface_bits_per_pixel(ds),
(s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
- int dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
- s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width);
- int dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
- s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height);
+ unsigned dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
+ s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width);
+ unsigned dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
+ s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height);
int bpp = ati_bpp_from_datatype(s);
+ if (!bpp) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n");
+ return;
+ }
int dst_stride = DEFAULT_CNTL ? s->regs.dst_pitch : s->regs.default_pitch;
+ if (!dst_stride) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n");
+ return;
+ }
uint8_t *dst_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
s->regs.dst_offset : s->regs.default_offset);
@@ -82,12 +90,16 @@ void ati_2d_blt(ATIVGAState *s)
switch (s->regs.dp_mix & GMC_ROP3_MASK) {
case ROP3_SRCCOPY:
{
- int src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
- s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
- int src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
- s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height);
+ unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
+ s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
+ unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
+ s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height);
int src_stride = DEFAULT_CNTL ?
s->regs.src_pitch : s->regs.default_pitch;
+ if (!src_stride) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n");
+ return;
+ }
uint8_t *src_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
s->regs.src_offset : s->regs.default_offset);
@@ -137,8 +149,10 @@ void ati_2d_blt(ATIVGAState *s)
dst_y * surface_stride(ds),
s->regs.dst_height * surface_stride(ds));
}
- s->regs.dst_x += s->regs.dst_width;
- s->regs.dst_y += s->regs.dst_height;
+ s->regs.dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
+ dst_x + s->regs.dst_width : dst_x);
+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
+ dst_y + s->regs.dst_height : dst_y);
break;
}
case ROP3_PATCOPY:
@@ -179,7 +193,8 @@ void ati_2d_blt(ATIVGAState *s)
dst_y * surface_stride(ds),
s->regs.dst_height * surface_stride(ds));
}
- s->regs.dst_y += s->regs.dst_height;
+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
+ dst_y + s->regs.dst_height : dst_y);
break;
}
default:
--
2.23.0

View File

@ -0,0 +1,24 @@
From 2892a4b1f7dfc75e06d0ce770d44a062b6334eb0 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
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 <fangying1@huawei.com>
---
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

View File

@ -0,0 +1,59 @@
From d9b88f7e0d56feb4d7daa2506e2756fc48e975a1 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
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 <mreitz@redhat.com>
Message-id: 20191101152510.11719-3-mreitz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit c28107e9e55b11cd35cf3dc2505e3e69d10dcf13)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,131 @@
From 590cff8230749794ba09b38f3ea4eb6b0f2f73b5 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
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 <mreitz@redhat.com>
Message-id: 20191101152510.11719-2-mreitz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 304d9d7f034ff7f5e1e66a65b7f720f63a72c57e)
Conflicts:
block/io.c
*drop context dependency on 1acc3466a2
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,95 @@
From 088f1e8fd9e790bc5766bd43af134230abcff6dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
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 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131
#7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, 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 <xutian@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,69 @@
From 7db05c8a732fbdc986a40aadf0de6dd23057d044 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
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 <mreitz@redhat.com>
Message-id: 20191101152510.11719-4-mreitz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 292d06b925b2787ee6f2430996b95651cae42fce)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,165 @@
From 6f1a94035b02d3676a897ea5fa4cda4c62128228 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
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 <pbonzini@redhat.com>
Fixes: 50ba5b2d994853b38fed10e0841b119da0f8b8e5
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
Tested-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b2c6f23f4a9f6d8f1b648705cd46d3713b78d6a2)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,481 @@
From 2e2ad02f2cecf419eaad0df982ceb5b41170cc7e Mon Sep 17 00:00:00 2001
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
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 <vsementsov@virtuozzo.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com
Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4)
*prereq for 292d06b9
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,41 @@
From 0694c489cd240620fee5675e8d24c7ce02d1d67d Mon Sep 17 00:00:00 2001
From: Peter Lieven <pl@kamp.de>
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 <pl@kamp.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,343 @@
From 3d018ff3bdd8aec260254036b600cfa8d694ced4 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nirsof@gmail.com>
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 <nsoffer@redhat.com>
Message-id: 20190827010528.8818-2-nsoffer@redhat.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 3a20013fbb26d2a1bd11ef148eefdb1508783787)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,66 @@
From 84f22c728520792f1010074e0d5ac2ec8e2e372c Mon Sep 17 00:00:00 2001
From: Maxim Levitsky <mlevitsk@redhat.com>
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 <mlevitsk@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20190915203655.21638-2-mlevitsk@redhat.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 38e7d54bdc518b5a05a922467304bcace2396945)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,124 @@
From 7a8aa6c734bb1c2927ad0cc1d10bcacb53cf4ae3 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
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 <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Tested-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 05f4aced658a02b02d3e89a6c7a2281008fcf26c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,61 @@
From 86b0f4022bb43b16979ba5300e8d40a1e6d44b79 Mon Sep 17 00:00:00 2001
From: Sergio Lopez <slp@redhat.com>
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 <slp@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20190911100316.32282-1-mreitz@redhat.com
Reviewed-by: Sergio Lopez <slp@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,794 @@
From f9ab92373813cfccd31f29c0d963232f65cb5f88 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Fri, 22 May 2020 12:22:26 +0800
Subject: [PATCH] bt: use size_t type for length parameters instead of int
From: Prasad J Pandit <pjp@fedoraproject.org>
The length parameter values are not negative, thus use an unsigned
type 'size_t' for them. Many routines pass 'len' values to memcpy(3)
calls. If it was negative, it could lead to memory corruption issues.
Add check to avoid it.
Reported-by: Arash TC <tohidi.arash@gmail.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
diff --git a/bt-host.c b/bt-host.c
index 2f8f631..b73a44d 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -43,7 +43,7 @@ struct bt_host_hci_s {
};
static void bt_host_send(struct HCIInfo *hci,
- int type, const uint8_t *data, int len)
+ int type, const uint8_t *data, size_t len)
{
struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
uint8_t pkt = type;
@@ -63,17 +63,17 @@ static void bt_host_send(struct HCIInfo *hci,
}
}
-static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
+static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, size_t len)
{
bt_host_send(hci, HCI_COMMAND_PKT, data, len);
}
-static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len)
+static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, size_t len)
{
bt_host_send(hci, HCI_ACLDATA_PKT, data, len);
}
-static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len)
+static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, size_t len)
{
bt_host_send(hci, HCI_SCODATA_PKT, data, len);
}
diff --git a/bt-vhci.c b/bt-vhci.c
index 886e146..32ef1c5 100644
--- a/bt-vhci.c
+++ b/bt-vhci.c
@@ -89,7 +89,7 @@ static void vhci_read(void *opaque)
}
static void vhci_host_send(void *opaque,
- int type, const uint8_t *data, int len)
+ int type, const uint8_t *data, size_t len)
{
struct bt_vhci_s *s = (struct bt_vhci_s *) opaque;
#if 0
@@ -112,6 +112,7 @@ static void vhci_host_send(void *opaque,
static uint8_t buf[4096];
buf[0] = type;
+ assert(len < sizeof(buf));
memcpy(buf + 1, data, len);
while (write(s->fd, buf, len + 1) < 0)
@@ -124,13 +125,13 @@ static void vhci_host_send(void *opaque,
}
static void vhci_out_hci_packet_event(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
vhci_host_send(opaque, HCI_EVENT_PKT, data, len);
}
static void vhci_out_hci_packet_acl(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
vhci_host_send(opaque, HCI_ACLDATA_PKT, data, len);
}
diff --git a/hw/bt/core.c b/hw/bt/core.c
index dfb196e..f548b3d 100644
--- a/hw/bt/core.c
+++ b/hw/bt/core.c
@@ -44,7 +44,7 @@ static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link)
}
static void bt_dummy_lmp_acl_resp(struct bt_link_s *link,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
error_report("%s: stray ACL response PDU, fixme", __func__);
exit(-1);
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
index 3d60654..f7a74c0 100644
--- a/hw/bt/hci-csr.c
+++ b/hw/bt/hci-csr.c
@@ -103,7 +103,7 @@ static inline void csrhci_fifo_wake(struct csrhci_s *s)
}
#define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
-static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
+static uint8_t *csrhci_out_packet(struct csrhci_s *s, size_t len)
{
int off = s->out_start + s->out_len;
@@ -112,14 +112,14 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
if (off < FIFO_LEN) {
if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) {
- error_report("%s: can't alloc %i bytes", __func__, len);
+ error_report("%s: can't alloc %zu bytes", __func__, len);
exit(-1);
}
return s->outfifo + off;
}
if (s->out_len > s->out_size) {
- error_report("%s: can't alloc %i bytes", __func__, len);
+ error_report("%s: can't alloc %zu bytes", __func__, len);
exit(-1);
}
@@ -127,7 +127,7 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
}
static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
- int type, int len)
+ int type, size_t len)
{
uint8_t *ret = csrhci_out_packetz(s, len + 2);
@@ -138,7 +138,7 @@ static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
}
static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
- int evt, int len)
+ int evt, size_t len)
{
uint8_t *ret = csrhci_out_packetz(s,
len + 1 + sizeof(struct hci_event_hdr));
@@ -151,7 +151,7 @@ static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
}
static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf,
- uint8_t *data, int len)
+ uint8_t *data, size_t len)
{
int offset;
uint8_t *rpkt;
@@ -320,18 +320,18 @@ static int csrhci_write(struct Chardev *chr,
struct csrhci_s *s = (struct csrhci_s *)chr;
int total = 0;
- if (!s->enable)
+ if (!s->enable || len <= 0)
return 0;
for (;;) {
int cnt = MIN(len, s->in_needed - s->in_len);
- if (cnt) {
- memcpy(s->inpkt + s->in_len, buf, cnt);
- s->in_len += cnt;
- buf += cnt;
- len -= cnt;
- total += cnt;
- }
+ assert(cnt > 0);
+
+ memcpy(s->inpkt + s->in_len, buf, cnt);
+ s->in_len += cnt;
+ buf += cnt;
+ len -= cnt;
+ total += cnt;
if (s->in_len < s->in_needed) {
break;
@@ -363,7 +363,7 @@ static int csrhci_write(struct Chardev *chr,
}
static void csrhci_out_hci_packet_event(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
struct csrhci_s *s = (struct csrhci_s *) opaque;
uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */
@@ -375,7 +375,7 @@ static void csrhci_out_hci_packet_event(void *opaque,
}
static void csrhci_out_hci_packet_acl(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
struct csrhci_s *s = (struct csrhci_s *) opaque;
uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */
diff --git a/hw/bt/hci.c b/hw/bt/hci.c
index c7958f6..9c4f957 100644
--- a/hw/bt/hci.c
+++ b/hw/bt/hci.c
@@ -31,7 +31,7 @@
struct bt_hci_s {
uint8_t *(*evt_packet)(void *opaque);
- void (*evt_submit)(void *opaque, int len);
+ void (*evt_submit)(void *opaque, size_t len);
void *opaque;
uint8_t evt_buf[256];
@@ -61,7 +61,7 @@ struct bt_hci_s {
struct bt_hci_master_link_s {
struct bt_link_s *link;
void (*lmp_acl_data)(struct bt_link_s *link,
- const uint8_t *data, int start, int len);
+ const uint8_t *data, int start, size_t len);
QEMUTimer *acl_mode_timer;
} handle[HCI_HANDLES_MAX];
uint32_t role_bmp;
@@ -433,7 +433,7 @@ static const uint8_t bt_event_reserved_mask[8] = {
};
-static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
+static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, size_t len)
{
}
@@ -451,13 +451,13 @@ struct HCIInfo null_hci = {
static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
- int evt, int len)
+ int evt, size_t len)
{
uint8_t *packet, mask;
int mask_byte;
if (len > 255) {
- error_report("%s: HCI event params too long (%ib)", __func__, len);
+ error_report("%s: HCI event params too long (%zub)", __func__, len);
exit(-1);
}
@@ -474,7 +474,7 @@ static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
}
static inline void bt_hci_event(struct bt_hci_s *hci, int evt,
- void *params, int len)
+ void *params, size_t len)
{
uint8_t *packet = bt_hci_event_start(hci, evt, len);
@@ -499,7 +499,7 @@ static inline void bt_hci_event_status(struct bt_hci_s *hci, int status)
}
static inline void bt_hci_event_complete(struct bt_hci_s *hci,
- void *ret, int len)
+ void *ret, size_t len)
{
uint8_t *packet = bt_hci_event_start(hci, EVT_CMD_COMPLETE,
len + EVT_CMD_COMPLETE_SIZE);
@@ -1476,7 +1476,7 @@ static inline void bt_hci_event_num_comp_pkts(struct bt_hci_s *hci,
}
static void bt_submit_hci(struct HCIInfo *info,
- const uint8_t *data, int length)
+ const uint8_t *data, size_t length)
{
struct bt_hci_s *hci = hci_from_info(info);
uint16_t cmd;
@@ -1970,7 +1970,7 @@ static void bt_submit_hci(struct HCIInfo *info,
break;
short_hci:
- error_report("%s: HCI packet too short (%iB)", __func__, length);
+ error_report("%s: HCI packet too short (%zuB)", __func__, length);
bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
break;
}
@@ -1981,7 +1981,7 @@ static void bt_submit_hci(struct HCIInfo *info,
* know that a packet contained the last fragment of the SDU when the next
* SDU starts. */
static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
struct hci_acl_hdr *pkt = (void *) hci->acl_buf;
@@ -1989,7 +1989,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
/* TODO: avoid memcpy'ing */
if (len + HCI_ACL_HDR_SIZE > sizeof(hci->acl_buf)) {
- error_report("%s: can't take ACL packets %i bytes long",
+ error_report("%s: can't take ACL packets %zu bytes long",
__func__, len);
return;
}
@@ -2003,7 +2003,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
}
static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
@@ -2012,14 +2012,14 @@ static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
}
static void bt_hci_lmp_acl_data_host(struct bt_link_s *link,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
bt_hci_lmp_acl_data(hci_from_device(link->host),
link->handle, data, start, len);
}
static void bt_submit_acl(struct HCIInfo *info,
- const uint8_t *data, int length)
+ const uint8_t *data, size_t length)
{
struct bt_hci_s *hci = hci_from_info(info);
uint16_t handle;
@@ -2027,7 +2027,7 @@ static void bt_submit_acl(struct HCIInfo *info,
struct bt_link_s *link;
if (length < HCI_ACL_HDR_SIZE) {
- error_report("%s: ACL packet too short (%iB)", __func__, length);
+ error_report("%s: ACL packet too short (%zuB)", __func__, length);
return;
}
@@ -2045,7 +2045,7 @@ static void bt_submit_acl(struct HCIInfo *info,
handle &= ~HCI_HANDLE_OFFSET;
if (datalen > length) {
- error_report("%s: ACL packet too short (%iB < %iB)",
+ error_report("%s: ACL packet too short (%zuB < %iB)",
__func__, length, datalen);
return;
}
@@ -2087,7 +2087,7 @@ static void bt_submit_acl(struct HCIInfo *info,
}
static void bt_submit_sco(struct HCIInfo *info,
- const uint8_t *data, int length)
+ const uint8_t *data, size_t length)
{
struct bt_hci_s *hci = hci_from_info(info);
uint16_t handle;
@@ -2106,7 +2106,7 @@ static void bt_submit_sco(struct HCIInfo *info,
}
if (datalen > length) {
- error_report("%s: SCO packet too short (%iB < %iB)",
+ error_report("%s: SCO packet too short (%zuB < %iB)",
__func__, length, datalen);
return;
}
@@ -2127,7 +2127,7 @@ static uint8_t *bt_hci_evt_packet(void *opaque)
return s->evt_buf;
}
-static void bt_hci_evt_submit(void *opaque, int len)
+static void bt_hci_evt_submit(void *opaque, size_t len)
{
/* TODO: notify upper layer */
struct bt_hci_s *s = opaque;
diff --git a/hw/bt/hid.c b/hw/bt/hid.c
index 066ca99..fe15434 100644
--- a/hw/bt/hid.c
+++ b/hw/bt/hid.c
@@ -95,7 +95,7 @@ struct bt_hid_device_s {
int data_type;
int intr_state;
struct {
- int len;
+ size_t len;
uint8_t buffer[1024];
} dataother, datain, dataout, feature, intrdataout;
enum {
@@ -168,7 +168,7 @@ static void bt_hid_disconnect(struct bt_hid_device_s *s)
}
static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
uint8_t *pkt, hdr = (BT_DATA << 4) | type;
int plen;
@@ -189,7 +189,7 @@ static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
}
static void bt_hid_control_transaction(struct bt_hid_device_s *s,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
uint8_t type, parameter;
int rlen, ret = -1;
@@ -361,7 +361,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
bt_hid_send_handshake(s, ret);
}
-static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
+static void bt_hid_control_sdu(void *opaque, const uint8_t *data, size_t len)
{
struct bt_hid_device_s *hid = opaque;
@@ -387,7 +387,7 @@ static void bt_hid_datain(HIDState *hs)
hid->datain.buffer, hid->datain.len);
}
-static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len)
+static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, size_t len)
{
struct bt_hid_device_s *hid = opaque;
diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c
index d67098a..2f70a03 100644
--- a/hw/bt/l2cap.c
+++ b/hw/bt/l2cap.c
@@ -31,10 +31,10 @@ struct l2cap_instance_s {
int role;
uint8_t frame_in[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
- int frame_in_len;
+ uint32_t frame_in_len;
uint8_t frame_out[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
- int frame_out_len;
+ uint32_t frame_out_len;
/* Signalling channel timers. They exist per-request but we can make
* sure we have no more than one outstanding request at any time. */
@@ -48,7 +48,7 @@ struct l2cap_instance_s {
struct bt_l2cap_conn_params_s params;
void (*frame_in)(struct l2cap_chan_s *chan, uint16_t cid,
- const l2cap_hdr *hdr, int len);
+ const l2cap_hdr *hdr, size_t len);
int mps;
int min_mtu;
@@ -67,7 +67,7 @@ struct l2cap_instance_s {
/* Only flow-controlled, connection-oriented channels */
uint8_t sdu[65536]; /* TODO: dynamically allocate */
- int len_cur, len_total;
+ uint32_t len_cur, len_total;
int rexmit;
int monitor_timeout;
QEMUTimer *monitor_timer;
@@ -139,7 +139,7 @@ static const uint16_t l2cap_fcs16_table[256] = {
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
};
-static uint16_t l2cap_fcs16(const uint8_t *message, int len)
+static uint16_t l2cap_fcs16(const uint8_t *message, size_t len)
{
uint16_t fcs = 0x0000;
@@ -185,7 +185,7 @@ static void l2cap_monitor_timer_update(struct l2cap_chan_s *ch)
}
static void l2cap_command_reject(struct l2cap_instance_s *l2cap, int id,
- uint16_t reason, const void *data, int plen)
+ uint16_t reason, const void *data, size_t plen)
{
uint8_t *pkt;
l2cap_cmd_hdr *hdr;
@@ -246,7 +246,7 @@ static void l2cap_connection_response(struct l2cap_instance_s *l2cap,
}
static void l2cap_configuration_request(struct l2cap_instance_s *l2cap,
- int dcid, int flag, const uint8_t *data, int len)
+ int dcid, int flag, const uint8_t *data, size_t len)
{
uint8_t *pkt;
l2cap_cmd_hdr *hdr;
@@ -274,7 +274,7 @@ static void l2cap_configuration_request(struct l2cap_instance_s *l2cap,
}
static void l2cap_configuration_response(struct l2cap_instance_s *l2cap,
- int scid, int flag, int result, const uint8_t *data, int len)
+ int scid, int flag, int result, const uint8_t *data, size_t len)
{
uint8_t *pkt;
l2cap_cmd_hdr *hdr;
@@ -321,7 +321,7 @@ static void l2cap_disconnection_response(struct l2cap_instance_s *l2cap,
}
static void l2cap_echo_response(struct l2cap_instance_s *l2cap,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
uint8_t *pkt;
l2cap_cmd_hdr *hdr;
@@ -342,7 +342,7 @@ static void l2cap_echo_response(struct l2cap_instance_s *l2cap,
}
static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type,
- int result, const uint8_t *data, int len)
+ int result, const uint8_t *data, size_t len)
{
uint8_t *pkt;
l2cap_cmd_hdr *hdr;
@@ -365,16 +365,18 @@ static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type,
l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
}
-static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len);
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm,
+ size_t len);
static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms);
#if 0
-static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len);
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm,
+ size_t len);
static void l2cap_iframe_submit(struct bt_l2cap_conn_params_s *parm);
#endif
static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
- const l2cap_hdr *hdr, int len);
+ const l2cap_hdr *hdr, size_t len);
static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
- const l2cap_hdr *hdr, int len);
+ const l2cap_hdr *hdr, size_t len);
static int l2cap_cid_new(struct l2cap_instance_s *l2cap)
{
@@ -498,7 +500,7 @@ static void l2cap_channel_config_req_event(struct l2cap_instance_s *l2cap,
static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
struct l2cap_chan_s *ch, int flag,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
l2cap_conf_opt *opt;
l2cap_conf_opt_qos *qos;
@@ -683,7 +685,7 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
}
static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap,
- int flag, int cid, const uint8_t *data, int len)
+ int flag, int cid, const uint8_t *data, size_t len)
{
struct l2cap_chan_s *ch;
@@ -715,7 +717,7 @@ static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap,
}
static int l2cap_channel_config_rsp_msg(struct l2cap_instance_s *l2cap,
- int result, int flag, int cid, const uint8_t *data, int len)
+ int result, int flag, int cid, const uint8_t *data, size_t len)
{
struct l2cap_chan_s *ch;
@@ -783,7 +785,7 @@ static void l2cap_info(struct l2cap_instance_s *l2cap, int type)
}
static void l2cap_command(struct l2cap_instance_s *l2cap, int code, int id,
- const uint8_t *params, int len)
+ const uint8_t *params, size_t len)
{
int err;
@@ -938,7 +940,7 @@ static void l2cap_rexmit_enable(struct l2cap_chan_s *ch, int enable)
}
/* Command frame SDU */
-static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len)
+static void l2cap_cframe_in(void *opaque, const uint8_t *data, size_t len)
{
struct l2cap_instance_s *l2cap = opaque;
const l2cap_cmd_hdr *hdr;
@@ -966,7 +968,7 @@ static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len)
}
/* Group frame SDU */
-static void l2cap_gframe_in(void *opaque, const uint8_t *data, int len)
+static void l2cap_gframe_in(void *opaque, const uint8_t *data, size_t len)
{
}
@@ -977,7 +979,7 @@ static void l2cap_sframe_in(struct l2cap_chan_s *ch, uint16_t ctrl)
/* Basic L2CAP mode Information frame */
static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
- const l2cap_hdr *hdr, int len)
+ const l2cap_hdr *hdr, size_t len)
{
/* We have a full SDU, no further processing */
ch->params.sdu_in(ch->params.opaque, hdr->data, len);
@@ -985,7 +987,7 @@ static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
/* Flow Control and Retransmission mode frame */
static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
- const l2cap_hdr *hdr, int len)
+ const l2cap_hdr *hdr, size_t len)
{
uint16_t fcs = lduw_le_p(hdr->data + len - 2);
@@ -1076,7 +1078,7 @@ static void l2cap_frame_in(struct l2cap_instance_s *l2cap,
/* "Recombination" */
static void l2cap_pdu_in(struct l2cap_instance_s *l2cap,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
const l2cap_hdr *hdr = (void *) l2cap->frame_in;
@@ -1123,7 +1125,7 @@ static inline void l2cap_pdu_submit(struct l2cap_instance_s *l2cap)
(l2cap->link, l2cap->frame_out, 1, l2cap->frame_out_len);
}
-static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len)
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, size_t len)
{
struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
@@ -1146,7 +1148,7 @@ static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms)
#if 0
/* Stub: Only used if an emulated device requests outgoing flow control */
-static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len)
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, size_t len)
{
struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
@@ -1291,7 +1293,7 @@ static void l2cap_lmp_disconnect_slave(struct bt_link_s *link)
}
static void l2cap_lmp_acl_data_slave(struct bt_link_s *link,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
struct slave_l2cap_instance_s *l2cap =
(struct slave_l2cap_instance_s *) link;
@@ -1304,7 +1306,7 @@ static void l2cap_lmp_acl_data_slave(struct bt_link_s *link,
/* Stub */
static void l2cap_lmp_acl_data_host(struct bt_link_s *link,
- const uint8_t *data, int start, int len)
+ const uint8_t *data, int start, size_t len)
{
struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host;
struct l2cap_instance_s *l2cap =
diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c
index 2860d76..6bfb174 100644
--- a/hw/bt/sdp.c
+++ b/hw/bt/sdp.c
@@ -496,7 +496,7 @@ static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp,
return end + 2;
}
-static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
+static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, size_t len)
{
struct bt_l2cap_sdp_state_s *sdp = opaque;
enum bt_sdp_cmd pdu_id;
@@ -506,7 +506,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
int rsp_len = 0;
if (len < 5) {
- error_report("%s: short SDP PDU (%iB).", __func__, len);
+ error_report("%s: short SDP PDU (%zuB).", __func__, len);
return;
}
@@ -517,7 +517,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
len -= 5;
if (len != plen) {
- error_report("%s: wrong SDP PDU length (%iB != %iB).",
+ error_report("%s: wrong SDP PDU length (%iB != %zuB).",
__func__, plen, len);
err = SDP_INVALID_PDU_SIZE;
goto respond;
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 670ba32..240a901 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -265,7 +265,7 @@ static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
}
static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
int off = fifo->dstart + fifo->dlen;
uint8_t *buf;
@@ -274,13 +274,13 @@ static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
if (off <= DFIFO_LEN_MASK) {
if (off + len > DFIFO_LEN_MASK + 1 &&
(fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len);
+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len);
exit(-1);
}
buf = fifo->data + off;
} else {
if (fifo->dlen > fifo->dsize) {
- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len);
+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len);
exit(-1);
}
buf = fifo->data + off - fifo->dsize;
@@ -319,7 +319,7 @@ static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
struct usb_hci_out_fifo_s *fifo,
- void (*send)(struct HCIInfo *, const uint8_t *, int),
+ void (*send)(struct HCIInfo *, const uint8_t *, size_t),
int (*complete)(const uint8_t *, int),
USBPacket *p)
{
@@ -478,7 +478,7 @@ static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
}
static void usb_bt_out_hci_packet_event(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
struct USBBtState *s = (struct USBBtState *) opaque;
@@ -489,7 +489,7 @@ static void usb_bt_out_hci_packet_event(void *opaque,
}
static void usb_bt_out_hci_packet_acl(void *opaque,
- const uint8_t *data, int len)
+ const uint8_t *data, size_t len)
{
struct USBBtState *s = (struct USBBtState *) opaque;
diff --git a/include/hw/bt.h b/include/hw/bt.h
index b5e11d4..bc362aa 100644
--- a/include/hw/bt.h
+++ b/include/hw/bt.h
@@ -94,9 +94,9 @@ struct bt_device_s {
void (*lmp_disconnect_master)(struct bt_link_s *link);
void (*lmp_disconnect_slave)(struct bt_link_s *link);
void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data,
- int start, int len);
+ int start, size_t len);
void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data,
- int start, int len);
+ int start, size_t len);
void (*lmp_mode_change)(struct bt_link_s *link);
void (*handle_destroy)(struct bt_device_s *device);
@@ -148,12 +148,12 @@ struct bt_l2cap_device_s {
struct bt_l2cap_conn_params_s {
/* Input */
- uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, int len);
+ uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, size_t len);
void (*sdu_submit)(struct bt_l2cap_conn_params_s *chan);
int remote_mtu;
/* Output */
void *opaque;
- void (*sdu_in)(void *opaque, const uint8_t *data, int len);
+ void (*sdu_in)(void *opaque, const uint8_t *data, size_t len);
void (*close)(void *opaque);
};
diff --git a/include/sysemu/bt.h b/include/sysemu/bt.h
index 2fd8c0f..df8fb63 100644
--- a/include/sysemu/bt.h
+++ b/include/sysemu/bt.h
@@ -5,12 +5,12 @@
typedef struct HCIInfo {
int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr);
- void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len);
- void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len);
- void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len);
+ void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
+ void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
+ void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
void *opaque;
- void (*evt_recv)(void *opaque, const uint8_t *data, int len);
- void (*acl_recv)(void *opaque, const uint8_t *data, int len);
+ void (*evt_recv)(void *opaque, const uint8_t *data, size_t len);
+ void (*acl_recv)(void *opaque, const uint8_t *data, size_t len);
} HCIInfo;
/* bt-host.c */
--
1.8.3.1

View File

@ -0,0 +1,44 @@
From b9e4a4ff6f3292927adb1463777c86cd4063a6ef Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
---
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

View File

@ -0,0 +1,50 @@
From e9bb3d942e268a19e03fc5d404586d2ed1564282 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
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 <kwolf@redhat.com>
Tested-by: Michael Weiser <michael.weiser@gmx.de>
Reviewed-by: Michael Weiser <michael.weiser@gmx.de>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 944f3d5dd216fcd8cb007eddd4f82dced0a15b3d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -3,6 +3,8 @@ From: Xu Yandong <xuyandong2@huawei.com>
Date: Wed, 28 Aug 2019 01:36:21 -0400 Date: Wed, 28 Aug 2019 01:36:21 -0400
Subject: [PATCH] cpu: add Kunpeng-920 cpu support Subject: [PATCH] cpu: add Kunpeng-920 cpu support
Add the Kunpeng-920 CPU model.
Signed-off-by: Xu Yandong <xuyandong2@huawei.com> Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
--- ---
hw/arm/virt.c | 1 + hw/arm/virt.c | 1 +
@ -62,4 +64,3 @@ index 228906f2..5581d5e1 100644
}; };
-- --
2.19.1 2.19.1

View File

@ -1,8 +1,11 @@
From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001 From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build> From: Xu Yandong <xuyandong2@huawei.com>
Date: Tue, 3 Sep 2019 16:27:39 +0800 Date: Tue, 3 Sep 2019 16:27:39 +0800
Subject: [PATCH] cpu: parse +/- feature to avoid failure Subject: [PATCH] cpu: parse +/- feature to avoid failure
To avoid cpu feature parse failuer, +/- feature is added.
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
--- ---
target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++ target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+) 1 file changed, 38 insertions(+)

View File

@ -0,0 +1,79 @@
From fbde196c30e4797a51bda046ba514b187963d4ba Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
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 <jsnow@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 20190729213416.1972-1-pbonzini@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,107 @@
From 9c1752703fb8a5b70985cf4c9caabc3388c5953b Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Message-Id: <20190918130633.4872-10-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,50 @@
From c0b35d87de345bd3b59a44c604b247a0497f2fc0 Mon Sep 17 00:00:00 2001
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
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 <vsementsov@virtuozzo.com>
Message-id: 20191011090711.19940-2-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit fed33bd175f663cc8c13f8a490a4f35a19756cfe)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,478 @@
From b12d9edd0079d4ee136c25e95333918b0c6d3cd9 Mon Sep 17 00:00:00 2001
From: Samuel Ortiz <sameo@linux.intel.com>
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 <sameo@linux.intel.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Message-Id: <20190918130633.4872-4-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
---
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

View File

@ -0,0 +1,46 @@
From 7a08983315bf4d624966a89112259e2b4949de91 Mon Sep 17 00:00:00 2001
From: Samuel Ortiz <sameo@linux.intel.com>
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 <sameo@linux.intel.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-3-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,196 @@
From 6cd7281c73ca462b2f27969f1e28f1afd3ebe82d Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-2-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,72 @@
From e6b1fd7bfbfe116e9d5df590f7069336c1eb1983 Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-8-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,167 @@
From 0b77f242b180f1ae40b9752999cef4894113df8e Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,115 @@
From de86ba0ff72a51b0c1cdbebf790869aea73ae9d3 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,47 @@
From 220816989c1e3d490d293b8d7ac85dbc41a4c321 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
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 <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190920174039.3916-1-peter.maydell@linaro.org
(cherry picked from commit ece628fcf69cbbd4b3efb6fbd203af07609467a2)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -1,54 +1,57 @@
From 773b25c55c7428b64d21b23a6b08fc629a665ca5 Mon Sep 17 00:00:00 2001 From b70d020dba72283d7b16a77c377512c84aab5f81 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com> From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 09:54:43 +0800 Date: Mon, 20 Apr 2020 10:38:12 +0800
Subject: [PATCH] hw/arm: expose host CPU frequency info to guest 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 On ARM64 platform, cpu frequency is retrieved via ACPI CPPC.
CPPC registers and ACPI _CPC objects. 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 The default frequency is set to host cpu nominal frequency,
will not support CPPC in future. On Hi1620 we are fetching the value which is obtained from the host CPPC sysfs. Other performance
from Host CPPC sys file. 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 Performance counters are also not emulated and they simply
guest initiating performance scaling. return 1 if read, and guest should fallback to use desired
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 value as the current performance. performance value as the current performance.
Signed-off-by: Heyi Guo <guoheyi@huawei.com> Guest kernel version above 4.18 is required to make it work.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
This series is backported from:
https://patchwork.kernel.org/cover/11379943/
Signed-off-by: Ying Fang <fangying1@huawei.com>
--- ---
default-configs/aarch64-softmmu.mak | 1 + default-configs/aarch64-softmmu.mak | 1 +
hw/acpi/Makefile.objs | 1 + hw/acpi/Makefile.objs | 1 +
hw/acpi/aml-build.c | 22 +++ 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-acpi-build.c | 78 +++++++-
hw/arm/virt.c | 13 ++ hw/arm/virt.c | 13 ++
hw/char/Kconfig | 4 + hw/char/Kconfig | 4 +
include/hw/acpi/acpi-defs.h | 38 ++++ include/hw/acpi/acpi-defs.h | 38 ++++
include/hw/acpi/aml-build.h | 3 + include/hw/acpi/aml-build.h | 3 +
include/hw/arm/virt.h | 1 + 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 create mode 100644 hw/acpi/cpufreq.c
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak 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 --- a/default-configs/aarch64-softmmu.mak
+++ b/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_ZYNQMP_ARM=y
CONFIG_XLNX_VERSAL=y CONFIG_XLNX_VERSAL=y
CONFIG_ARM_SMMUV3=y CONFIG_SBSA_REF=y
+CONFIG_CPUFREQ=y +CONFIG_CPUFREQ=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs 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 --- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-y += acpi_interface.o @@ -13,6 +13,7 @@ common-obj-y += bios-linker-loader.o
common-obj-y += bios-linker-loader.o common-obj-y += aml-build.o utils.o
common-obj-y += aml-build.o common-obj-$(CONFIG_ACPI_PCI) += pci.o
common-obj-$(CONFIG_TPM) += tpm.o common-obj-$(CONFIG_TPM) += tpm.o
+common-obj-$(CONFIG_CPUFREQ) += cpufreq.o +common-obj-$(CONFIG_CPUFREQ) += cpufreq.o
@ -89,10 +92,10 @@ index 555c24f2..73f97751 100644
int hi, lo; int hi, lo;
diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c
new file mode 100644 new file mode 100644
index 00000000..c123a22b index 00000000..d02a25a6
--- /dev/null --- /dev/null
+++ b/hw/acpi/cpufreq.c +++ b/hw/acpi/cpufreq.c
@@ -0,0 +1,278 @@ @@ -0,0 +1,287 @@
+/* +/*
+ * ACPI CPPC register device + * ACPI CPPC register device
+ * + *
@ -124,6 +127,7 @@ index 00000000..c123a22b
+#include "hw/acpi/acpi-defs.h" +#include "hw/acpi/acpi-defs.h"
+#include "qemu/cutils.h" +#include "qemu/cutils.h"
+#include "qemu/error-report.h" +#include "qemu/error-report.h"
+#include "hw/boards.h"
+ +
+#define TYPE_CPUFREQ "cpufreq" +#define TYPE_CPUFREQ "cpufreq"
+#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ) +#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ)
@ -189,6 +193,9 @@ index 00000000..c123a22b
+ uint64_t r; + uint64_t r;
+ uint64_t n; + 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 >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ warn_report("cpufreq_read: offset 0x%lx out of range", offset); + warn_report("cpufreq_read: offset 0x%lx out of range", offset);
+ return 0; + return 0;
@ -258,6 +265,8 @@ index 00000000..c123a22b
+ uint64_t value, unsigned size) + uint64_t value, unsigned size)
+{ +{
+ uint64_t n; + 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 >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ error_printf("cpufreq_write: offset 0x%lx out of range", offset); + error_printf("cpufreq_write: offset 0x%lx out of range", offset);
@ -339,6 +348,9 @@ index 00000000..c123a22b
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ CpuhzState *s = CPUFREQ(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; + s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE;
+ if (s->reg_size > MAX_SUPPORT_SPACE) { + if (s->reg_size > MAX_SUPPORT_SPACE) {
+ error_report("Required space 0x%x excesses the max support 0x%x", + error_report("Required space 0x%x excesses the max support 0x%x",
@ -372,7 +384,7 @@ index 00000000..c123a22b
+type_init(cpufreq_register_types) +type_init(cpufreq_register_types)
+ +
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c 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 --- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c
@@ -45,11 +45,73 @@ @@ -45,11 +45,73 @@
@ -469,7 +481,7 @@ index bf9c0bc2..33a8e2e3 100644
aml_append(scope, dev); 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. * the RTC ACPI device at all when using UEFI.
*/ */
scope = aml_scope("\\_SB"); scope = aml_scope("\\_SB");
@ -479,10 +491,10 @@ index bf9c0bc2..33a8e2e3 100644
(irqmap[VIRT_UART] + ARM_SPI_BASE)); (irqmap[VIRT_UART] + ARM_SPI_BASE));
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c 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 --- a/hw/arm/virt.c
+++ b/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_SECURE_UART] = { 0x09040000, 0x00001000 },
[VIRT_SMMU] = { 0x09050000, 0x00020000 }, [VIRT_SMMU] = { 0x09050000, 0x00020000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 },
@ -490,7 +502,7 @@ index ce2664a3..ec6f00ab 100644
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
[VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, [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); g_free(nodename);
} }
@ -507,7 +519,7 @@ index ce2664a3..ec6f00ab 100644
static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
{ {
char *nodename; 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_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0));
@ -517,10 +529,10 @@ index ce2664a3..ec6f00ab 100644
create_secure_ram(vms, secure_sysmem); create_secure_ram(vms, secure_sysmem);
create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
diff --git a/hw/char/Kconfig b/hw/char/Kconfig diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6360c9ff..8cc3ae2a 100644 index 40e7a8b8..2f61bf53 100644
--- a/hw/char/Kconfig --- a/hw/char/Kconfig
+++ b/hw/char/Kconfig +++ b/hw/char/Kconfig
@@ -40,3 +40,7 @@ config SCLPCONSOLE @@ -46,3 +46,7 @@ config SCLPCONSOLE
config TERMINAL3270 config TERMINAL3270
bool bool
@ -529,10 +541,10 @@ index 6360c9ff..8cc3ae2a 100644
+ bool + bool
+ default y + default y
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h 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 --- a/include/hw/acpi/acpi-defs.h
+++ b/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; } QEMU_PACKED;
typedef struct AcpiIortRC AcpiIortRC; typedef struct AcpiIortRC AcpiIortRC;
@ -590,7 +602,7 @@ index 1a563ad7..375335ab 100644
/* Block AML object primitives */ /* Block AML object primitives */
Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); 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 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 --- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h
@@ -66,6 +66,7 @@ enum { @@ -66,6 +66,7 @@ enum {
@ -603,4 +615,3 @@ index 507517c6..8465f9bd 100644
VIRT_FW_CFG, VIRT_FW_CFG,
-- --
2.19.1 2.19.1

View File

@ -0,0 +1,130 @@
From e14fadc66d488ad10a10a2076721b72cc239ded9 Mon Sep 17 00:00:00 2001
From: Eric Auger <eric.auger@redhat.com>
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 <eric.auger@redhat.com>
Signed-off-by: Kwangwoo Lee <kwangwoo.lee@sk.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-5-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,252 @@
From ce813d8daa2e01df52509f4bb52b9ab774408706 Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Message-Id: <20190918130633.4872-6-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
---
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

View File

@ -0,0 +1,170 @@
From 3a0af1446395e74476a763ca12713b28c099a144 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -1,6 +1,6 @@
From 123b4eb3cb7b9b4e3e0705a9b5f974b37d3b8431 Mon Sep 17 00:00:00 2001 From 73fc4af05ebe12d77915e6b3c85c48f5e0c432f3 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com> From: Ying Fang <fangying1@huawei.com>
Date: Mon, 5 Aug 2019 15:04:31 +0800 Date: Wed, 22 Apr 2020 19:23:27 +0800
Subject: [PATCH] hw/arm/virt: Introduce cpu topology support 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 Add topology support for guest vcpu by cpu-map in dtb when the guest is booted
@ -11,13 +11,13 @@ Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
(picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by (picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by
Andrew Jones <drjones@redhat.com>) Andrew Jones <drjones@redhat.com>)
--- ---
device_tree.c | 32 +++++++++++++++++++++++ device_tree.c | 32 ++++++++++++++++++++++
hw/acpi/aml-build.c | 50 ++++++++++++++++++++++++++++++++++++ hw/acpi/aml-build.c | 53 ++++++++++++++++++++++++++++++++++++
hw/arm/virt-acpi-build.c | 4 +++ 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/hw/acpi/aml-build.h | 2 ++
include/sysemu/device_tree.h | 1 + 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 diff --git a/device_tree.c b/device_tree.c
index f8b46b3c..03906a14 100644 index f8b46b3c..03906a14 100644
@ -63,7 +63,7 @@ index f8b46b3c..03906a14 100644
{ {
const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); 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 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 --- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c
@@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
@ -74,7 +74,7 @@ index 73f97751..9d39ad10 100644
static GArray *build_alloc_array(void) 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); g_array_append_vals(array, val->data, val->len);
} }
@ -97,6 +97,9 @@ index 73f97751..9d39ad10 100644
+{ +{
+ int pptt_start = table_data->len; + int pptt_start = table_data->len;
+ int uid = 0, cpus = 0, socket; + 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)); + acpi_data_push(table_data, sizeof(AcpiTableHeader));
+ +
@ -131,10 +134,10 @@ index 73f97751..9d39ad10 100644
static void static void
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c 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 --- a/hw/arm/virt-acpi-build.c
+++ b/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); acpi_add_table(table_offsets, tables_blob);
build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt);
@ -146,10 +149,10 @@ index 33a8e2e3..18653e6d 100644
build_madt(tables_blob, tables->linker, vms); build_madt(tables_blob, tables->linker, vms);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c 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 --- a/hw/arm/virt.c
+++ b/hw/arm/virt.c +++ b/hw/arm/virt.c
@@ -42,6 +42,7 @@ @@ -44,6 +44,7 @@
#include "net/net.h" #include "net/net.h"
#include "sysemu/device_tree.h" #include "sysemu/device_tree.h"
#include "sysemu/numa.h" #include "sysemu/numa.h"
@ -157,7 +160,17 @@ index 57a78b16..16700a2e 100644
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "hw/loader.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); ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
} }
@ -220,5 +233,4 @@ index c16fd69b..d62fc873 100644
#define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \
do { \ do { \
-- --
2.19.1 2.23.0

View File

@ -0,0 +1,402 @@
From 5d1be90750551f1debf5767d7a6e2b9c50054c05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
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é <philmd@redhat.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20191209090306.20433-1-philmd@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
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

View File

@ -0,0 +1,75 @@
From 8d287871fd4e1b4654fe9e5011b80614cb44f6d8 Mon Sep 17 00:00:00 2001
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
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 <shameerali.kolothum.thodi@huawei.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20190918130633.4872-7-shameerali.kolothum.thodi@huawei.com>
Acked-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
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

View File

@ -0,0 +1,25 @@
From fbcb4ffa8648d0aa5be01c11816423a483f245ae Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Tue, 26 May 2020 22:39:23 +0800
Subject: [PATCH] hw/arm/virt: add missing compat for kvm-no-adjvtime
Machine compatibility for kvm-no-adjvtime is missed,
let's add it for virt machine 4.0
Signed-off-by: Ying Fang <fangying1@huawei.com>
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 4c727939..133d36a4 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2492,6 +2492,7 @@ static void virt_machine_4_0_options(MachineClass *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;
+ vmc->kvm_no_adjvtime = true;
}
DEFINE_VIRT_MACHINE(4, 0)
--
2.23.0

View File

@ -1,6 +1,6 @@
From 8db6d888e3eb131900111506b93f6101413df5b4 Mon Sep 17 00:00:00 2001 From 5a0ed254f99ca37498bd81994b906b6984b5ffa9 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com> From: Ying Fang <fangying1@huawei.com>
Date: Mon, 5 Aug 2019 15:30:05 +0800 Date: Wed, 22 Apr 2020 19:25:00 +0800
Subject: [PATCH] hw/arm64: add vcpu cache info support Subject: [PATCH] hw/arm64: add vcpu cache info support
Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. 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 <zhang.zhanghailiang@huawei.com> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Honghao <honghao5@huawei.com> Signed-off-by: Honghao <honghao5@huawei.com>
--- ---
hw/acpi/aml-build.c | 124 ++++++++++++++++++++++++++++++++++++ hw/acpi/aml-build.c | 126 ++++++++++++++++++++++++++++++++++++
hw/arm/virt.c | 76 +++++++++++++++++++++- hw/arm/virt.c | 80 ++++++++++++++++++++++-
include/hw/acpi/aml-build.h | 46 +++++++++++++ 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 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 --- a/hw/acpi/aml-build.c
+++ b/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) * ACPI 6.2 Processor Properties Topology Table (PPTT)
*/ */
@ -115,6 +115,8 @@ index 9d39ad10..99209c0a 100644
+ int pptt_start = table_data->len; + int pptt_start = table_data->len;
+ int uid = 0, cpus = 0, socket; + int uid = 0, cpus = 0, socket;
+ struct offset_status offset; + 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)); + acpi_data_push(table_data, sizeof(AcpiTableHeader));
+ +
@ -147,7 +149,7 @@ index 9d39ad10..99209c0a 100644
static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, static void build_cpu_hierarchy(GArray *tbl, uint32_t flags,
uint32_t parent, uint32_t id) 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", (void *)(table_data->data + pptt_start), "PPTT",
table_data->len - pptt_start, 1, NULL, NULL); table_data->len - pptt_start, 1, NULL, NULL);
} }
@ -156,16 +158,18 @@ index 9d39ad10..99209c0a 100644
#define ACPI_NAMESEG_LEN 4 #define ACPI_NAMESEG_LEN 4
diff --git a/hw/arm/virt.c b/hw/arm/virt.c 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 --- a/hw/arm/virt.c
+++ b/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); GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
} }
+static void fdt_add_l3cache_nodes(const VirtMachineState *vms) +static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
+{ +{
+ int i; + int i;
+ const MachineState *ms = MACHINE(qdev_get_machine());
+ unsigned int smp_cores = ms->smp.cores;
+ unsigned int sockets = vms->smp_cpus / smp_cores; + unsigned int sockets = vms->smp_cpus / smp_cores;
+ +
+ /* If current is not equal to max */ + /* If current is not equal to max */
@ -191,6 +195,8 @@ index 16700a2e..96f56e2e 100644
+static void fdt_add_l2cache_nodes(const VirtMachineState *vms) +static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
+{ +{
+ int i, j; + 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; + signed int sockets = vms->smp_cpus / smp_cores;
+ +
+ /* If current is not equal to max */ + /* If current is not equal to max */
@ -237,7 +243,7 @@ index 16700a2e..96f56e2e 100644
static void fdt_add_cpu_nodes(const VirtMachineState *vms) static void fdt_add_cpu_nodes(const VirtMachineState *vms)
{ {
int cpu; 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", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
@ -247,7 +253,7 @@ index 16700a2e..96f56e2e 100644
for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(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", qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id",
ms->possible_cpus->cpus[cs->cpu_index].props.node_id); ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
} }
@ -315,4 +321,3 @@ index bfb0b100..0be3453a 100644
* *
-- --
2.23.0 2.23.0

View File

@ -0,0 +1,45 @@
From aae0faa5d3bee91c66dc4c1543190f55a242771e Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
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 <mst@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,170 @@
From 6bbfb186c8d66b745aeb08143d3198fcedc52d6c Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,89 @@
From ed78352a59ea7acf7520d4d47a96b9911bae7fc3 Mon Sep 17 00:00:00 2001
From: Alexander Popov <alex.popov@linux.com>
Date: Mon, 23 Dec 2019 20:51:16 +0300
Subject: [PATCH] ide: Fix incorrect handling of some PRDTs in ide_dma_cb()
The commit a718978ed58a from July 2015 introduced the assertion which
implies that the size of successful DMA transfers handled in ide_dma_cb()
should be multiple of 512 (the size of a sector). But guest systems can
initiate DMA transfers that don't fit this requirement.
For fixing that let's check the number of bytes prepared for the transfer
by the prepare_buf() handler. The code in ide_dma_cb() must behave
according to the Programming Interface for Bus Master IDE Controller
(Revision 1.0 5/16/94):
1. If PRDs specified a smaller size than the IDE transfer
size, then the Interrupt and Active bits in the Controller
status register are not set (Error Condition).
2. If the size of the physical memory regions was equal to
the IDE device transfer size, the Interrupt bit in the
Controller status register is set to 1, Active bit is set to 0.
3. If PRDs specified a larger size than the IDE transfer size,
the Interrupt and Active bits in the Controller status register
are both set to 1.
Signed-off-by: Alexander Popov <alex.popov@linux.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 20191223175117.508990-2-alex.popov@linux.com
Signed-off-by: John Snow <jsnow@redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 754ff4dc34..80000eb766 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -849,6 +849,7 @@ static void ide_dma_cb(void *opaque, int ret)
int64_t sector_num;
uint64_t offset;
bool stay_active = false;
+ int32_t prep_size = 0;
if (ret == -EINVAL) {
ide_dma_error(s);
@@ -863,13 +864,15 @@ static void ide_dma_cb(void *opaque, int ret)
}
}
- n = s->io_buffer_size >> 9;
- if (n > s->nsector) {
- /* The PRDs were longer than needed for this request. Shorten them so
- * we don't get a negative remainder. The Active bit must remain set
- * after the request completes. */
+ if (s->io_buffer_size > s->nsector * 512) {
+ /*
+ * The PRDs were longer than needed for this request.
+ * The Active bit must remain set after the request completes.
+ */
n = s->nsector;
stay_active = true;
+ } else {
+ n = s->io_buffer_size >> 9;
}
sector_num = ide_get_sector(s);
@@ -892,9 +895,20 @@ static void ide_dma_cb(void *opaque, int ret)
n = s->nsector;
s->io_buffer_index = 0;
s->io_buffer_size = n * 512;
- if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) {
- /* The PRDs were too short. Reset the Active bit, but don't raise an
- * interrupt. */
+ prep_size = s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size);
+ /* prepare_buf() must succeed and respect the limit */
+ assert(prep_size >= 0 && prep_size <= n * 512);
+
+ /*
+ * Now prep_size stores the number of bytes in the sglist, and
+ * s->io_buffer_size stores the number of bytes described by the PRDs.
+ */
+
+ if (prep_size < n * 512) {
+ /*
+ * The PRDs are too short for this request. Error condition!
+ * Reset the Active bit and don't raise the interrupt.
+ */
s->status = READY_STAT | SEEK_STAT;
dma_buf_commit(s, 0);
goto eot;
--
2.23.0

View File

@ -0,0 +1,357 @@
From 0a75312c069d89be94bcaa688429d8f60a0c528b Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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, &regl, 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, &reg, 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, &reg, 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, &regl, 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

View File

@ -0,0 +1,50 @@
From a7391f391336024986a5997e3beae8882c983ed0 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,197 @@
From de97ff4a01008ad98f7d69adc4b84843fff3ce19 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,45 @@
From f45964c7e0df4ef17457a9ea92bfd255064139e1 Mon Sep 17 00:00:00 2001
From: Keqian Zhu <zhukeqian1@huawei.com>
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 <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
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

View File

@ -0,0 +1,40 @@
From 63b07dfe20a0d4971b0929d27359f478ba2d816b Mon Sep 17 00:00:00 2001
From: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date: Fri, 22 May 2020 10:52:55 +0800
Subject: [PATCH] ip_reass: Fix use after free
Using ip_deq after m_free might read pointers from an allocation reuse.
This would be difficult to exploit, but that is still related with
CVE-2019-14378 which generates fragmented IP packets that would trigger this
issue and at least produce a DoS.
Signed-off-by: Samuel Thibault's avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c
index 8c75d91..c07d7d4 100644
--- a/slirp/src/ip_input.c
+++ b/slirp/src/ip_input.c
@@ -292,6 +292,7 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
*/
while (q != (struct ipasfrag *)&fp->frag_link &&
ip->ip_off + ip->ip_len > q->ipf_off) {
+ struct ipasfrag *prev;
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
if (i < q->ipf_len) {
q->ipf_len -= i;
@@ -299,9 +300,10 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
m_adj(dtom(slirp, q), i);
break;
}
+ prev = q;
q = q->ipf_next;
- m_free(dtom(slirp, q->ipf_prev));
- ip_deq(q->ipf_prev);
+ ip_deq(prev);
+ m_free(dtom(slirp, prev));
}
insert:
--
1.8.3.1

View File

@ -0,0 +1,42 @@
From 28a9a3558a427493049723fff390add7026653eb Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes.berg@intel.com>
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 <johannes.berg@intel.com>
Message-Id: <20190903200422.11693-1-johannes@sipsolutions.net>
Reviewed-by: Tiwei Bie <tiwei.bie@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 8726b70b449896f1211f869ec4f608904f027207)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -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 <yuzenghui@huawei.com> From: Zenghui Yu <yuzenghui@huawei.com>
Date: Fri, 3 Jan 2020 17:16:55 +0800 Date: Tue, 14 Apr 2020 21:52:42 +0800
Subject: [PATCH 1/3] linux headers: update against "KVM/ARM: Fix >256 vcpus" Subject: [PATCH] linux headers: update against "KVM/ARM: Fix >256 vcpus"
This is part of upstream commit f363d039e883 ("linux headers: update This is part of upstream commit f363d039e883 ("linux headers: update
against v5.4-rc1"), authored by Eric Auger <eric.auger@redhat.com>. against v5.4-rc1"), authored by Eric Auger <eric.auger@redhat.com>.
@ -30,10 +30,10 @@ index e1f8b745..137a2730 100644
#define KVM_ARM_IRQ_VCPU_MASK 0xff #define KVM_ARM_IRQ_VCPU_MASK 0xff
#define KVM_ARM_IRQ_NUM_SHIFT 0 #define KVM_ARM_IRQ_NUM_SHIFT 0
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h 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 --- a/linux-headers/asm-arm64/kvm.h
+++ b/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 #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
/* KVM_IRQ_LINE irq field index values */ /* KVM_IRQ_LINE irq field index values */
@ -46,17 +46,16 @@ index e6a98c14..dfd3a028 100644
#define KVM_ARM_IRQ_VCPU_MASK 0xff #define KVM_ARM_IRQ_VCPU_MASK 0xff
#define KVM_ARM_IRQ_NUM_SHIFT 0 #define KVM_ARM_IRQ_NUM_SHIFT 0
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h 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 --- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h
@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt { @@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_VM_IPA_SIZE 165 #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_HYPERV_CPUID 167
+#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 +#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168
#ifdef KVM_CAP_IRQ_ROUTING #define KVM_CAP_PPC_IRQ_XIVE 169
#define KVM_CAP_ARM_SVE 170
-- --
2.19.1 2.23.0

View File

@ -0,0 +1,181 @@
From 0c83403e6e3ab21a01941be4ec57b02388eeb9c4 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Fri, 22 May 2020 18:56:09 +0800
Subject: [PATCH] log: Add some logs on VM runtime path
Add logs on VM runtime path, to make it easier to do trouble shooting.
Signed-off-by: Ying Fang <fangying1@huawei.com>
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index f6d2223..b4b0ed2 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -32,6 +32,7 @@
#include "qemu/range.h"
#include "hw/virtio/virtio-bus.h"
#include "qapi/visitor.h"
+#include "qemu/log.h"
#define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev))
@@ -1659,7 +1660,9 @@ static void virtio_pci_device_unplugged(DeviceState *d)
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
bool modern = virtio_pci_modern(proxy);
bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ qemu_log("unplug device name: %s\n", !vdev ? "NULL" : vdev->name);
virtio_pci_stop_ioeventfd(proxy);
if (modern) {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 7c3822c..79c2dcf 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1172,7 +1172,14 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
k->set_status(vdev, val);
}
vdev->status = val;
-
+ if (val) {
+ qemu_log("%s device status is %d that means %s\n",
+ vdev->name, val,
+ (val & VIRTIO_CONFIG_S_DRIVER_OK) ? "DRIVER OK" :
+ (val & VIRTIO_CONFIG_S_DRIVER) ? "DRIVER" :
+ (val & VIRTIO_CONFIG_S_ACKNOWLEDGE) ? "ACKNOWLEDGE" :
+ (val & VIRTIO_CONFIG_S_FAILED) ? "FAILED" : "UNKNOWN");
+ }
return 0;
}
@@ -1614,8 +1621,11 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
break;
}
- if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
+ if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE) {
+ qemu_log("unacceptable queue_size (%d) or num (%d)\n",
+ queue_size, i);
abort();
+ }
vdev->vq[i].vring.num = queue_size;
vdev->vq[i].vring.num_default = queue_size;
diff --git a/monitor/monitor.c b/monitor/monitor.c
index 3ef2817..6f726e8 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -28,6 +28,7 @@
#include "qapi/qapi-emit-events.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qjson.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "sysemu/qtest.h"
@@ -254,6 +255,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict)
{
Monitor *mon;
MonitorQMP *qmp_mon;
+ QString *json;
trace_monitor_protocol_event_emit(event, qdict);
QTAILQ_FOREACH(mon, &mon_list, entry) {
@@ -264,6 +266,13 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict)
qmp_mon = container_of(mon, MonitorQMP, common);
if (qmp_mon->commands != &qmp_cap_negotiation_commands) {
qmp_send_response(qmp_mon, qdict);
+ json = qobject_to_json(QOBJECT(qdict));
+ if (json) {
+ if (!strstr(json->string, "RTC_CHANGE")) {
+ qemu_log("%s\n", qstring_get_str(json));
+ }
+ qobject_unref(json);
+ }
}
}
}
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index e2c366e..6dfdad5 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -17,7 +17,9 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qstring.h"
#include "sysemu/sysemu.h"
+#include "qemu/log.h"
static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
Error **errp)
@@ -83,6 +85,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
const char *command;
QDict *args, *dict;
QmpCommand *cmd;
+ QString *json;
QObject *ret = NULL;
dict = qmp_dispatch_check_obj(request, allow_oob, errp);
@@ -128,6 +131,19 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
qobject_ref(args);
}
+ json = qobject_to_json(QOBJECT(args));
+ if (json) {
+ if ((strcmp(command, "query-block-jobs") != 0)
+ && (strcmp(command, "query-migrate") != 0)
+ && (strcmp(command, "query-blockstats") != 0)
+ && (strcmp(command, "query-balloon") != 0)
+ && (strcmp(command, "set_password") != 0)) {
+ qemu_log("qmp_cmd_name: %s, arguments: %s\n",
+ command, qstring_get_str(json));
+ }
+ qobject_unref(json);
+ }
+
cmd->fn(args, &ret, &local_err);
if (local_err) {
error_propagate(errp, local_err);
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 58222c2..c6c1d3f 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -34,6 +34,7 @@
#include "qemu/qemu-print.h"
#include "sysemu/block-backend.h"
#include "migration/misc.h"
+#include "qemu/log.h"
/*
* Aliases were a bad idea from the start. Let's keep them
@@ -586,6 +587,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
if (path != NULL) {
bus = qbus_find(path, errp);
if (!bus) {
+ error_setg(errp, "can not find bus for %s", driver);
return NULL;
}
if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
@@ -627,6 +629,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
/* set properties */
if (qemu_opt_foreach(opts, set_property, dev, &err)) {
+ error_setg(errp, "the bus %s -driver %s set property failed",
+ bus ? bus->name : "None", driver);
goto err_del_dev;
}
@@ -636,6 +640,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
dev->opts = NULL;
goto err_del_dev;
}
+ qemu_log("add qdev %s:%s success\n", driver,
+ qemu_opts_id(opts) ? qemu_opts_id(opts) : "none");
return dev;
err_del_dev:
--
1.8.3.1

View File

@ -0,0 +1,60 @@
From c5c9b1362d1652a9d0f79f6d9ae2f80d4b5fe432 Mon Sep 17 00:00:00 2001
From: Michael Roth <mdroth@linux.vnet.ibm.com>
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 <lersek@redhat.com>
Cc: Bruce Rogers <brogers@suse.com>
Cc: qemu-stable@nongnu.org # v4.1.0
Reported-by: Bruce Rogers <brogers@suse.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Message-Id: <20190912231202.12327-2-mdroth@linux.vnet.ibm.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
(cherry picked from commit 45c61c6c23918e3b05ed9ecac5b2328ebae5f774)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -1,85 +0,0 @@
From b9f43f0cca03586a31b53e47ade72e77db01cb4c Mon Sep 17 00:00:00 2001
From: King Wang <king.wang@huawei.com>
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<king.wang@huawei.com>
Message-Id: <20190712065241.11784-1-king.wang@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
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

View File

@ -0,0 +1,80 @@
From 79d722679731233ccb1aa775d896a4bf21e13d44 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Wed, 27 May 2020 10:02:06 +0800
Subject: [PATCH] migration: Compat virtual timer adjust for v4.0.1 and v4.1.0
Vtimer adjust is used in openEuler qemu-4.0.1, however kvm_adjvtime
is introduced in openEuler qemu-4.1.0. To maintain the compatibility
and enable cross version migration, let's enable vtimer adjust only
if kvm_adjvtime is not enabled, otherwise there may be conflicts
between vtimer adjust and kvm_adjvtime.
After this modification:
1: openEuler qemu-4.0.1 use vtimer as the default virtual timer
2: openEuler qemu-4.1.0 use kvm_adjvtime as the defaut virtual timer
Migration from openEuler qemu-4.0.1 to openEuler qemu-4.1.0 will
be ok, but migration path from upstream qemu-4.0.1 to openEuler
qemu-4..0.1 will be broken.
Since openEuler qemu-4.1.0, kvm_adjvtime is used as the default
virtual timer. So please upgrade to openEuler qemu-4.1.0 and
use the virt-4.1 machine.
Signed-off-by: Ying Fang <fangying1@huawei.com>
diff --git a/cpus.c b/cpus.c
index b9aa51f8..6a28bdef 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1067,6 +1067,12 @@ void cpu_synchronize_all_pre_loadvm(void)
}
#ifdef __aarch64__
+static bool kvm_adjvtime_enabled(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ return cpu->kvm_adjvtime == true;
+}
+
static void get_vcpu_timer_tick(CPUState *cs)
{
CPUARMState *env = &ARM_CPU(cs)->env;
@@ -1096,7 +1102,13 @@ static int do_vm_stop(RunState state, bool send_stop)
cpu_disable_ticks();
pause_all_vcpus();
#ifdef __aarch64__
- if (first_cpu) {
+ /* vtimer adjust is used in openEuler qemu-4.0.1, however kvm_adjvtime
+ * is introduced in openEuler qemu-4.1.0. To maintain the compatibility
+ * and enable cross version migration, let's enable vtimer adjust only
+ * if kvm_adjvtime is not enabled, otherwise there may be conflicts
+ * between vtimer adjust and kvm_adjvtime.
+ */
+ if (first_cpu && !kvm_adjvtime_enabled(first_cpu)) {
get_vcpu_timer_tick(first_cpu);
}
#endif
@@ -1946,6 +1958,7 @@ void cpu_resume(CPUState *cpu)
}
#ifdef __aarch64__
+
static void set_vcpu_timer_tick(CPUState *cs)
{
CPUARMState *env = &ARM_CPU(cs)->env;
@@ -1977,7 +1990,10 @@ void resume_all_vcpus(void)
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
#ifdef __aarch64__
- if (first_cpu) {
+ /* Enable vtimer adjust only if kvm_adjvtime is not enabled, otherwise
+ * there may be conflicts between vtimer adjust and kvm_adjvtime.
+ */
+ if (first_cpu && !kvm_adjvtime_enabled(first_cpu)) {
set_vcpu_timer_tick(first_cpu);
}
#endif
--
2.23.0

View File

@ -0,0 +1,100 @@
From 8c3794d709eefdae777477bef7ff3511d55bf418 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
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 <quintela@redhat.com>
Message-Id: <20190814020218.1868-3-quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
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

View File

@ -0,0 +1,57 @@
From 5e99e1329fa52dce8ab784a960e64a3e19b429aa Mon Sep 17 00:00:00 2001
From: Zhimin Feng <fengzhimin1@huawei.com>
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 <euler.robot@huawei.com>
Signed-off-by: Zhimin Feng <fengzhimin1@huawei.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
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

View File

@ -0,0 +1,50 @@
From 7572495245a437da717e6829a9ce852cc3f229c9 Mon Sep 17 00:00:00 2001
From: Zheng Chuan <zhengchuan@huawei.com>
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 <ivanren@tencent.com>
Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1564464816-21804-2-git-send-email-ivanren@tencent.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
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

View File

@ -0,0 +1,127 @@
From bc5780480db9e38699df0b4697e60a9f36258dc4 Mon Sep 17 00:00:00 2001
From: Ivan Ren <ivanren@tencent.com>
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 <ivanren@tencent.com>
Message-Id: <1564464816-21804-3-git-send-email-ivanren@tencent.com>
Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
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

View File

@ -0,0 +1,125 @@
From af2aa4f553565ae6b2248204c154748f38ec4746 Mon Sep 17 00:00:00 2001
From: Ivan Ren <ivanren@tencent.com>
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 <ivanren@tencent.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Suggested-by: Wei Yang <richardw.yang@linux.intel.com>
Message-Id: <1564741121-1840-1-git-send-email-ivanren@tencent.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
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

View File

@ -0,0 +1,64 @@
From 34d797aa134a33c1d67ca85d9d9f996d58162276 Mon Sep 17 00:00:00 2001
From: Jiahui Cen <cenjiahui@huawei.com>
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=<optimized out>, line=<optimized out>) at util/qemu-thread-posix.c:64
#5 0x000055eb1bb4564a in multifd_send_terminate_threads (err=<optimized out>) 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 <cenjiahui@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
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

View File

@ -0,0 +1,62 @@
From 6a08ee257a95d9f2514bd995e90ddf46d3f78b41 Mon Sep 17 00:00:00 2001
From: Zheng Chuan <zhengchuan@huawei.com>
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=<optimized out>) 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=<optimized out>) 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=<optimized out>, argv=<optimized out>, envp=<optimized out>) 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 <fengzhimin1@huawei.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
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

View File

@ -0,0 +1,75 @@
From d9a847f0982fcca6f63031215065c346fcc27bbc Mon Sep 17 00:00:00 2001
From: Zheng Chuan <zhengchuan@huawei.com>
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=<optimized out>) 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=<optimized out>) at migration/socket
.c:166
#7 0x00005563fdbc25cd in qio_net_listener_channel_func (ioc=<optimized out>, condition=<optimized out>, opaque=<optimized out>) 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=<optimized out>, argv=<optimized out>, envp=<optimized out>) 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 <cenjiahui@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
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

View File

@ -0,0 +1,294 @@
From 71f3e496c128b46f803cc4776154b02a5e505cb2 Mon Sep 17 00:00:00 2001
From: Zheng Chuan <zhengchuan@huawei.com>
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 <cenjiahui@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
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

View File

@ -0,0 +1,69 @@
From 05d1fbd2390d441e5acb606dba3d308d506a8eb1 Mon Sep 17 00:00:00 2001
From: Pan Nengyuan <pannengyuan@huawei.com>
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 <euler.robot@huawei.com>
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
---
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

View File

@ -0,0 +1,54 @@
From 4d456b243a41a8e91535b2820fd6ed4f6fb4a194 Mon Sep 17 00:00:00 2001
From: Pan Nengyuan <pannengyuan@huawei.com>
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 <euler.robot@huawei.com>
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
---
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

View File

@ -0,0 +1,43 @@
From 8ae2e3b8be812bcbdeb6151c685026bcaedd4a4b Mon Sep 17 00:00:00 2001
From: Pan Nengyuan <pannengyuan@huawei.com>
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 <euler.robot@huawei.com>
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
---
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

View File

@ -0,0 +1,35 @@
From e93040851d683f1f7750acfa0e862b4405678f24 Mon Sep 17 00:00:00 2001
From: Zheng Chuan <zhengchuan@huawei.com>
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 <ivanren@tencent.com>
Suggested-by: Wei Yang <richardw.yang@linux.intel.com>
Message-Id: <1564464816-21804-4-git-send-email-ivanren@tencent.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
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

View File

@ -0,0 +1,52 @@
From e092a17d3825a8f2c93cb429aaa5d857b579b64c Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
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 <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit d2da5e288a2e71e82866c8fdefd41b5727300124)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -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 <kuhn.chenqun@huawei.com> From: Chen Qun <kuhn.chenqun@huawei.com>
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 Subject: [PATCH] moniter: fix memleak in monitor_fdset_dup_fd_find_remove
When remove dup_fd in monitor_fdset_dup_fd_find_remove function, When remove dup_fd in monitor_fdset_dup_fd_find_remove function,
@ -25,14 +25,14 @@ Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com> Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
(cherry picked from commit a661614de18c89f58cad3fc1bb8aab44e820183a) (cherry picked from commit a661614de18c89f58cad3fc1bb8aab44e820183a)
--- ---
monitor.c | 1 + monitor/misc.c | 1 +
1 file changed, 1 insertion(+) 1 file changed, 1 insertion(+)
diff --git a/monitor.c b/monitor.c diff --git a/monitor/misc.c b/monitor/misc.c
index 4807bbe..b5b15b5 100644 index 00338c00..0d6369ba 100644
--- a/monitor.c --- a/monitor/misc.c
+++ b/monitor.c +++ b/monitor/misc.c
@@ -2596,6 +2596,7 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) @@ -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 (mon_fdset_fd_dup->fd == dup_fd) {
if (remove) { if (remove) {
QLIST_REMOVE(mon_fdset_fd_dup, next); QLIST_REMOVE(mon_fdset_fd_dup, next);
@ -41,5 +41,4 @@ index 4807bbe..b5b15b5 100644
monitor_fdset_cleanup(mon_fdset); monitor_fdset_cleanup(mon_fdset);
} }
-- --
1.8.3.1 2.23.0

View File

@ -1,60 +0,0 @@
From 32c6cb39cbadd6fc2026ff6311fcf58549f71d49 Mon Sep 17 00:00:00 2001
From: Pan Nengyuan <pannengyuan@huawei.com>
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 <eblake@redhat.com>
Message-Id: <20200206173832.130004-1-eblake@redhat.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
(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

View File

@ -0,0 +1,102 @@
From 7ebcd375ade505358c1c45542de22f188c599bdd Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
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 <ehabkost@redhat.com>
Message-Id: <20190816170750.23910-1-ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry picked from commit fea374e7c8079563bca7c8fac895c6a880f76adc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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 <ehabkost@redhat.com>
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+
+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

View File

@ -0,0 +1,39 @@
From 57fdf4a13ff16d9d48a43f02a5e7b42e3d264f83 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
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 <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,35 @@
From 405deba14f6b61b9c557484b46e863308c8cf373 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
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 <mreitz@redhat.com>
Message-id: 20191028161841.1198-2-mreitz@redhat.com
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 24552feb6ae2f615b76c2b95394af43901f75046)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,71 @@
From 416a692e51b8b582407e30046ddcffbbe52ecf77 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
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 <michael.weiser@gmx.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Tested-by: Michael Weiser <michael.weiser@gmx.de>
Reviewed-by: Michael Weiser <michael.weiser@gmx.de>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 5e9785505210e2477e590e61b1ab100d0ec22b01)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -0,0 +1,58 @@
From c9ffb12754b1575babfef45168b6e1b1af80a95f Mon Sep 17 00:00:00 2001
From: Alberto Garcia <berto@igalia.com>
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 <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
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

View File

@ -1,75 +0,0 @@
From 3283dde4b5b5cce0f96f48d536bebff66d97ce0b Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
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 <pjp@fedoraproject.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(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

View File

@ -1,60 +0,0 @@
From 6f5d8671225dc77190647f18a27a0d156d4ca97a Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
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 <rschiron@redhat.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(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

398
qemu.spec
View File

@ -1,6 +1,6 @@
Name: qemu Name: qemu
Version: 4.0.1 Version: 4.1.0
Release: 11 Release: 13
Epoch: 2 Epoch: 2
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY License: GPLv2 and BSD and MIT and CC-BY
@ -10,60 +10,170 @@ Source1: 80-kvm.rules
Source2: 99-qemu-guest-agent.rules Source2: 99-qemu-guest-agent.rules
Source3: bridge.conf Source3: bridge.conf
Patch0001: qxl-check-release-info-object.patch Patch0001: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch
Patch0002: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch Patch0002: pl031-support-rtc-timer-property-for-pl031.patch
Patch0003: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch Patch0003: vhost-cancel-migration-when-vhost-user-restarted.patch
Patch0004: pl031-support-rtc-timer-property-for-pl031.patch Patch0004: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch
Patch0005: vhost-cancel-migration-when-vhost-user-restarted.patch Patch0005: bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch
Patch0006: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch Patch0006: hw-arm-expose-host-CPU-frequency-info-to-guest.patch
Patch0007: hw-arm-expose-host-CPU-frequency-info-to-guest.patch Patch0007: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch
Patch0008: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch Patch0008: tests-bios-tables-test-disable-this-testcase.patch
Patch0009: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch Patch0009: hw-arm-virt-Introduce-cpu-topology-support.patch
Patch0010: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch Patch0010: hw-arm64-add-vcpu-cache-info-support.patch
Patch0011: hw-arm-virt-Introduce-cpu-topology-support.patch Patch0011: xhci-Fix-memory-leak-in-xhci_address_slot.patch
Patch0012: hw-arm64-add-vcpu-cache-info-support.patch Patch0012: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch
Patch0013: xhci-Fix-memory-leak-in-xhci_address_slot.patch Patch0013: ehci-fix-queue-dev-null-ptr-dereference.patch
Patch0014: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch Patch0014: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch
Patch0015: ehci-fix-queue-dev-null-ptr-dereference.patch Patch0015: vhost-user-scsi-prevent-using-uninitialized-vqs.patch
Patch0016: memory-unref-the-memory-region-in-simplify-flatview.patch Patch0016: cpu-add-Kunpeng-920-cpu-support.patch
Patch0017: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch Patch0017: cpu-parse-feature-to-avoid-failure.patch
Patch0018: vhost-user-scsi-prevent-using-uninitialized-vqs.patch Patch0018: cpu-add-Cortex-A72-processor-kvm-target-support.patch
Patch0019: cpu-add-Kunpeng-920-cpu-support.patch Patch0019: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch
Patch0020: cpu-parse-feature-to-avoid-failure.patch Patch0020: vnc-fix-memory-leak-when-vnc-disconnect.patch
Patch0021: cpu-add-Cortex-A72-processor-kvm-target-support.patch Patch0021: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch
Patch0022: vnc-fix-memory-leak-when-vnc-disconnect.patch Patch0022: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch
Patch0023: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch Patch0023: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch
Patch0024: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch Patch0024: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch
Patch0025: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch Patch0025: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch
Patch0026: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp_.patch Patch0026: arm-translate-a64-fix-uninitialized-variable-warning.patch
Patch0027: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch Patch0027: nbd-fix-uninitialized-variable-warning.patch
Patch0028: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch Patch0028: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch
Patch0029: arm-translate-a64-fix-uninitialized-variable-warning.patch Patch0029: block-fix-memleaks-in-bdrv_refresh_filename.patch
Patch0030: nbd-fix-uninitialized-variable-warning.patch Patch0030: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch
Patch0031: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch Patch0031: tcp_emu-Fix-oob-access.patch
Patch0032: block-fix-memleaks-in-bdrv_refresh_filename.patch Patch0032: slirp-use-correct-size-while-emulating-IRC-commands.patch
Patch0033: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch Patch0033: slirp-use-correct-size-while-emulating-commands.patch
Patch0034: tcp_emu-Fix-oob-access.patch Patch0034: util-add-slirp_fmt-helpers.patch
Patch0035: slirp-use-correct-size-while-emulating-IRC-commands.patch Patch0035: tcp_emu-fix-unsafe-snprintf-usages.patch
Patch0036: slirp-use-correct-size-while-emulating-commands.patch Patch0036: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch
Patch0037: tcp_emu-fix-unsafe-snprintf-usages.patch Patch0037: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch
Patch0038: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch Patch0038: memory-Align-MemoryRegionSections-fields.patch
Patch0039: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch Patch0039: memory-Provide-an-equality-function-for-MemoryRegion.patch
Patch0040: vhost-Fix-memory-region-section-comparison.patch Patch0040: vhost-Fix-memory-region-section-comparison.patch
Patch0041: memory-Align-MemoryRegionSections-fields.patch Patch0041: file-posix-Handle-undetectable-alignment.patch
Patch0042: memory-Provide-an-equality-function-for-MemoryRegion.patch Patch0042: block-backup-fix-max_transfer-handling-for-copy_rang.patch
Patch0043: file-posix-Handle-undetectable-alignment.patch Patch0043: block-backup-fix-backup_cow_with_offload-for-last-cl.patch
Patch0044: block-backup-fix-max_transfer-handling-for-copy_rang.patch Patch0044: qcow2-Limit-total-allocation-range-to-INT_MAX.patch
Patch0045: block-backup-fix-backup_cow_with_offload-for-last-cl.patch Patch0045: mirror-Do-not-dereference-invalid-pointers.patch
Patch0046: qcow2-Limit-total-allocation-range-to-INT_MAX.patch Patch0046: COLO-compare-Fix-incorrect-if-logic.patch
Patch0047: mirror-Do-not-dereference-invalid-pointers.patch Patch0047: qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch
Patch0048: COLO-compare-Fix-incorrect-if-logic.patch Patch0048: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch
Patch0049: qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch Patch0049: pcie-Compat-with-devices-which-do-not-support-Link-W.patch
Patch0050: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch Patch0050: aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch
Patch0051: pcie-Compat-with-devices-which-do-not-support-Link-W.patch Patch0051: async-use-explicit-memory-barriers.patch
Patch0052: aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch Patch0052: dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch
Patch0053: async-use-explicit-memory-barriers.patch Patch0053: Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch
Patch0054: nbd-Fix-regression-with-multiple-meta-contexts.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
Patch0152: arm-virt-Support-CPU-cold-plug.patch
Patch0153: ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch
Patch0154: ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch
Patch0155: slirp-tftp-restrict-relative-path-access.patch
Patch0156: ip_reass-Fix-use-after-free.patch
Patch0157: bt-use-size_t-type-for-length-parameters-instead-of-.patch
Patch0158: log-Add-some-logs-on-VM-runtime-path.patch
Patch0159: Revert-vtimer-compat-cross-version-migration-from-v4.patch
Patch0160: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch
Patch0161: hw-arm-virt-add-missing-compat-for-kvm-no-adjvtime.patch
Patch0162: migration-Compat-virtual-timer-adjust-for-v4.0.1-and.patch
Patch0163: vtimer-Drop-vtimer-virtual-timer-adjust.patch
Patch0164: target-arm-Add-the-kvm_adjvtime-vcpu-property-for-Co.patch
BuildRequires: flex BuildRequires: flex
BuildRequires: bison BuildRequires: bison
@ -250,7 +360,9 @@ install -D -m 0644 %{_sourcedir}/99-qemu-guest-agent.rules %{buildroot}%{_udevdi
mkdir -p %{buildroot}%{_localstatedir}/log mkdir -p %{buildroot}%{_localstatedir}/log
touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log
# For qemu docs package
%global qemudocdir %{_docdir}/%{name} %global qemudocdir %{_docdir}/%{name}
rm -rf %{buildroot}%{qemudocdir}/specs
install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE
chmod -x %{buildroot}%{_mandir}/man1/* chmod -x %{buildroot}%{_mandir}/man1/*
@ -265,6 +377,9 @@ rm -rf %{buildroot}%{_datadir}/%{name}/multiboot.bin
rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin
rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin
%endif %endif
%ifarch x86_64
rm -rf %{buildroot}%{_datadir}/%{name}/vgabios-ati.bin
%endif
rm -rf %{buildroot}%{_datadir}/%{name}/openbios-* rm -rf %{buildroot}%{_datadir}/%{name}/openbios-*
rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin
rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin
@ -280,6 +395,11 @@ rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid
rm -rf %{buildroot}%{_datadir}/%{name}/spapr-* rm -rf %{buildroot}%{_datadir}/%{name}/spapr-*
rm -rf %{buildroot}%{_datadir}/%{name}/u-boot* rm -rf %{buildroot}%{_datadir}/%{name}/u-boot*
rm -rf %{buildroot}%{_bindir}/ivshmem* 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}/* \ for f in %{buildroot}%{_bindir}/* %{buildroot}%{_libdir}/* \
%{buildroot}%{_libexecdir}/*; do %{buildroot}%{_libexecdir}/*; do
@ -399,96 +519,146 @@ getent passwd qemu >/dev/null || \
%endif %endif
%changelog %changelog
* Thu Apr 9 2020 backport nbd fix from qemu upstream * Fri May 29 Huawei Technologies Co., Ltd <fangying1@huawei.com>
- nbd: Fix regression with multiple meta contexts - target/arm: Add the kvm_adjvtime vcpu property for Cortex-A72
* Sat Apr 11 4 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com> * Wed May 27 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- Revert: "vtimer: compat cross version migration from v4.0.1"
- ARM64: record vtimer tick when cpu is stopped
- hw/arm/virt: add missing compat for kvm-no-adjvtime
- migration: Compat virtual timer adjust for v4.0.1 and v4.1.0
- vtimer: Drop vtimer virtual timer adjust
* Fri May 22 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- ip_reass: Fix use after free
- bt: use size_t type for length parameters instead of int
- log: Add some logs on VM runtime path
* Fri May 15 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- ide: Fix incorrect handling of some PRDTs in ide_dma_cb()
- ati-vga: Fix checks in ati_2d_blt() to avoid crash
- slirp: tftp: restrict relative path access
* Tue May 12 2020 Huawei Technologies Co., Ltd. <zhukeqian1@huawei.com>
- arm/virt: Support CPU cold plug
* Sat May 9 2020 Huawei Technologies Co., Ltd. <pannengyuan@huawei.com>
- 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. <zhengchuan@huawei.com>
- vtimer: compat cross version migration from v4.0.1
* Fri Apr 24 2020 Huawei Technologies Co., Ltd. <zhengchuan@huawei.com>
- migration: backport migration patches from upstream
* Fri Apr 24 2020 Huawei Technologies Co., Ltd. <zhukeqian1@huawei.com>
- arm/virt: Add CPU hotplug support
* Wed Apr 22 2020 Huawei Technologies Co., Ltd. <zhukeqian1@huawei.com>
- backport patch to enable arm/virt memory hotplug
* Wed Apr 22 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- backport patch to enable target/arm/kvm Adjust virtual time
* Fri Apr 17 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- backport patch bundles from qemu stable v4.1.1
* Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- aio-wait: delegate polling of main AioContext if BQL not held - aio-wait: delegate polling of main AioContext if BQL not held
- async: use explicit memory barriers - async: use explicit memory barriers
* Wed Mar 18 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- pcie: Add pcie-root-port fast plug/unplug feature - 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. <zhang.zhanghailiang@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- Put linuxboot_dma.bin and pvh.bin in x86 package - qcow2-bitmap: Fix uint64_t left-shift overflow
* Mon Mar 16 2020 backport some bug fix patches from upstream * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- Patch from number 0040 to 0049 are picked from stable-4.1.1 - COLO-compare: Fix incorrect `if` logic
* Mon Mar 16 2020 Huawei Technologies Co., Ltd. <kuhn.chenqun@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- moniter: fix memleak in monitor_fdset_dup_fd_find_remove - 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. <fangying1@huawei.com>
- file-posix: Handle undetectable alignment
* Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- 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. <fangying1@huawei.com>
- block/iscsi: use MIN() between mx_sb_len and sb_len_wr - 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 * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- tcp_emu: Fix oob access
- slirp: use correct size while emulating IRC commands
- slirp: use correct size while emulating commands
- tcp_emu: fix unsafe snprintf() usages - tcp_emu: fix unsafe snprintf() usages
- util: add slirp_fmt() helpers
* Mon Mar 9 2020 backport from qemu upstream - 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) - iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711)
* Thu Feb 6 2020 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- spec: remove fno-inline option for configure - 9pfs: local: Fix possible memory leak in local_link()
- scsi-disk: define props in scsi_block_disk to avoid memleaks
* Thu Jan 16 2020 Huawei Technologies Co., Ltd. <pannengyuan@huawei.com> - 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 - block: fix memleaks in bdrv_refresh_filename
* Mon Jan 13 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- 9pfs: Fix a possible memory leak in local_link - linux headers: update against "KVM/ARM: Fix >256 vcpus"
- scsi-disk: disk define props in scsi_block to avoid memleaks - intc/arm_gic: Support IRQ injection for more than 256 vcpus
- arm/translate-a64: fix uninitialized variable warning - ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus >
- nbd: fix uninitialized variable warning
- xhci: Fix memory leak in xhci_kick_epctx when poweroff
* Mon Jan 6 2020 backport from qemu upstream * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- linux headers: update against "KVM/ARM: Fix >256 vcp - vnc: fix memory leak when vnc disconnect
- 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 Dec 12 2019 backport from qemu upstream v4.0.1 release * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- tpm: Exit in reset when backend indicates failure - pcie: disable the PCI_EXP_LINKSTA_DLLA cap for pcie-root-port by default
- tpm_emulator: Translate TPM error codes to strings
* Thu Oct 17 2019 backport from qemu upstream * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- vnc-fix-memory-leak-when-vnc-disconnect.patch - 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 * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- ehci-fix-queue-dev-null-ptr-dereference.patch - vhost-user-scsi: prevent using uninitialized vqs
- 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
* Fri Aug 30 2019 Huawei Technologies Co., Ltd. <fangying1@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- util/async: hold AioContext ref to prevent use-after-free
* Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- xhci: Fix memory leak in xhci_address_slot - xhci: Fix memory leak in xhci_address_slot
- xhci: Fix memory leak in xhci_kick_epctx - xhci: Fix memory leak in xhci_kick_epctx
- ehci: fix queue->dev null ptr dereference
* Wed Aug 7 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com> * Thu Apr 16 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- tests/bios-tables-test: disable this testcase
- hw/arm/virt: Introduce cpu topology support - hw/arm/virt: Introduce cpu topology support
- hw/arm64: add vcpu cache info support - hw/arm64: add vcpu cache info support
* Tue Aug 6 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com> * Wed Apr 15 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- Update release version to 4.0.0-2
* Mon Aug 5 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com>
- enable make check
- smbios: Add missing member of type 4 for smbios 3.0 - smbios: Add missing member of type 4 for smbios 3.0
* Mon Aug 5 2019 fix CVE-2019-13164 * Wed Apr 15 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- qemu-bridge-helper: restrict interface name to IFNAMSIZ - bios-tables-test: prepare to change ARM virt ACPI DSDT
- qemu-bridge-helper: move repeating code in parse_acl_file - arm64: Add the cpufreq device to show cpufreq info to guest
* Tue Jul 30 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com * Wed Apr 15 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- qcow2: fix memory leak in qcow2_read_extensions - 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. <fangying1@huawei.com> * Wed Apr 15 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- vhost: cancel migration when vhost-user restarted - pl011: reset read FIFIO when UARTTIMSC=0 & UARTICR=0xff
- pl031: support rtc-timer property for pl031 - pl031: support rtc-timer property for pl031
- pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff - vhost: cancel migration when vhost-user restarted
- ARM64: record vtimer tick when cpu is stopped
* Tue Jul 23 2019 openEuler Buildteam <buildteam@openeuler.org> - version-release * Mon Apr 13 2020 openEuler Buildteam <buildteam@openeuler.org> - version-release
- Package init - Package init

Some files were not shown because too many files have changed in this diff Show More