!916 sync PR 905/906/909
From: @JiaboFeng Reviewed-by: @imxcc Signed-off-by: @imxcc
This commit is contained in:
commit
f1cdf125a6
BIN
BinDir.tar.gz
BIN
BinDir.tar.gz
Binary file not shown.
27
Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch
Normal file
27
Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 59f038d21c1901245ba0be417f6285cec465d6c1 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 11:24:32 +0800
|
||||
Subject: [PATCH] Currently, while kvm and qemu can not handle some kvm exit,
|
||||
qemu will do vm_stop, which will make vm in pause state. This action make vm
|
||||
unrecoverable, so send guest panic to libvirt instead.
|
||||
|
||||
---
|
||||
accel/kvm/kvm-all.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index e39a810a4e..33f4c6d547 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -2993,7 +2993,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||
|
||||
if (ret < 0) {
|
||||
cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
|
||||
- vm_stop(RUN_STATE_INTERNAL_ERROR);
|
||||
+ qemu_system_guest_panicked(cpu_get_crash_info(cpu));
|
||||
}
|
||||
|
||||
qatomic_set(&cpu->exit_request, 0);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
147
accel-kvm-Extract-common-KVM-vCPU-creation-parking-c.patch
Normal file
147
accel-kvm-Extract-common-KVM-vCPU-creation-parking-c.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From 6999ced63ca3bb05a1cbc4a667bd9fd27eeaeaee Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 9 Sep 2023 00:04:04 +0000
|
||||
Subject: [PATCH] accel/kvm: Extract common KVM vCPU {creation,parking} code
|
||||
|
||||
KVM vCPU creation is done once during the initialization of the VM when Qemu
|
||||
threads are spawned. This is common to all the architectures. If the architecture
|
||||
supports vCPU hot-{un}plug then this KVM vCPU creation could be deferred to
|
||||
later point as well. Some architectures might in any case create KVM vCPUs for
|
||||
the yet-to-be plugged vCPUs (i.e. QoM Object & thread does not exists) during VM
|
||||
init time and park them.
|
||||
|
||||
Hot-unplug of vCPU results in destruction of the vCPU objects in QOM but
|
||||
the KVM vCPU objects in the Host KVM are not destroyed and their representative
|
||||
KVM vCPU objects in Qemu are parked.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 61 ++++++++++++++++++++++++++++++++++----------
|
||||
include/sysemu/kvm.h | 2 ++
|
||||
2 files changed, 49 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index d900df93a4..6d503aa614 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -136,6 +136,7 @@ static QemuMutex kml_slots_lock;
|
||||
#define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock)
|
||||
|
||||
static void kvm_slot_init_dirty_bitmap(KVMSlot *mem);
|
||||
+static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id);
|
||||
|
||||
static inline void kvm_resample_fd_remove(int gsi)
|
||||
{
|
||||
@@ -324,11 +325,51 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+void kvm_park_vcpu(CPUState *cpu)
|
||||
+{
|
||||
+ unsigned long vcpu_id = cpu->cpu_index;
|
||||
+ struct KVMParkedVcpu *vcpu;
|
||||
+
|
||||
+ vcpu = g_malloc0(sizeof(*vcpu));
|
||||
+ vcpu->vcpu_id = vcpu_id;
|
||||
+ vcpu->kvm_fd = cpu->kvm_fd;
|
||||
+ QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
|
||||
+}
|
||||
+
|
||||
+int kvm_create_vcpu(CPUState *cpu)
|
||||
+{
|
||||
+ unsigned long vcpu_id = cpu->cpu_index;
|
||||
+ KVMState *s = kvm_state;
|
||||
+ int ret;
|
||||
+
|
||||
+ DPRINTF("kvm_create_vcpu\n");
|
||||
+
|
||||
+ /* check if the KVM vCPU already exist but is parked */
|
||||
+ ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu));
|
||||
+ if (ret > 0) {
|
||||
+ goto found;
|
||||
+ }
|
||||
+
|
||||
+ /* create a new KVM vcpu */
|
||||
+ ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+found:
|
||||
+ cpu->vcpu_dirty = true;
|
||||
+ cpu->kvm_fd = ret;
|
||||
+ cpu->kvm_state = s;
|
||||
+ cpu->dirty_pages = 0;
|
||||
+ cpu->throttle_us_per_full = 0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int do_kvm_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
- struct KVMParkedVcpu *vcpu = NULL;
|
||||
int ret = 0;
|
||||
|
||||
DPRINTF("kvm_destroy_vcpu\n");
|
||||
@@ -357,10 +398,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
- vcpu = g_malloc0(sizeof(*vcpu));
|
||||
- vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
|
||||
- vcpu->kvm_fd = cpu->kvm_fd;
|
||||
- QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
|
||||
+ kvm_park_vcpu(cpu);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -388,7 +426,7 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
}
|
||||
}
|
||||
|
||||
- return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
@@ -399,19 +437,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
|
||||
trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
|
||||
- ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu));
|
||||
+ ret = kvm_create_vcpu(cpu);
|
||||
if (ret < 0) {
|
||||
- error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)",
|
||||
+ error_setg_errno(errp, -ret,
|
||||
+ "kvm_init_vcpu: kvm_create_vcpu failed (%lu)",
|
||||
kvm_arch_vcpu_id(cpu));
|
||||
goto err;
|
||||
}
|
||||
|
||||
- cpu->kvm_fd = ret;
|
||||
- cpu->kvm_state = s;
|
||||
- cpu->vcpu_dirty = true;
|
||||
- cpu->dirty_pages = 0;
|
||||
- cpu->throttle_us_per_full = 0;
|
||||
-
|
||||
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
|
||||
if (mmap_size < 0) {
|
||||
ret = mmap_size;
|
||||
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||
index b46d6203b4..e534411ddc 100644
|
||||
--- a/include/sysemu/kvm.h
|
||||
+++ b/include/sysemu/kvm.h
|
||||
@@ -434,6 +434,8 @@ void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
|
||||
|
||||
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
|
||||
hwaddr *phys_addr);
|
||||
+int kvm_create_vcpu(CPUState *cpu);
|
||||
+void kvm_park_vcpu(CPUState *cpu);
|
||||
|
||||
#endif /* NEED_CPU_H */
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
32
accel-kvm-Use-correct-id-for-parked-vcpu.patch
Normal file
32
accel-kvm-Use-correct-id-for-parked-vcpu.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 9de26d69c52db67f48619ad20b8cb9d8ee71e42c Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 15:42:57 +0800
|
||||
Subject: [PATCH] accel/kvm: Use correct id for parked vcpu
|
||||
|
||||
kvm_arch_vcpu_id is correct for all platform.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 6d503aa614..75a3075c14 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -327,11 +327,10 @@ err:
|
||||
|
||||
void kvm_park_vcpu(CPUState *cpu)
|
||||
{
|
||||
- unsigned long vcpu_id = cpu->cpu_index;
|
||||
struct KVMParkedVcpu *vcpu;
|
||||
|
||||
vcpu = g_malloc0(sizeof(*vcpu));
|
||||
- vcpu->vcpu_id = vcpu_id;
|
||||
+ vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
|
||||
vcpu->kvm_fd = cpu->kvm_fd;
|
||||
QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
72
acpi-cpu-Add-cpu_cppc-building-support.patch
Normal file
72
acpi-cpu-Add-cpu_cppc-building-support.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From c75a0102a1bb00190b07b06ede8b1f9fa0bdaa3c Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 2 Apr 2024 16:52:10 +0800
|
||||
Subject: [PATCH] acpi/cpu: Add cpu_cppc building support
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 8 +++++++-
|
||||
hw/i386/acpi-build.c | 2 +-
|
||||
include/hw/acpi/cpu.h | 6 +++++-
|
||||
3 files changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index cf0c7e8538..c8c11e51c6 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -342,7 +342,9 @@ const VMStateDescription vmstate_cpu_hotplug = {
|
||||
#define CPU_FW_EJECT_EVENT "CEJF"
|
||||
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
- build_madt_cpu_fn build_madt_cpu, hwaddr base_addr,
|
||||
+ build_madt_cpu_fn build_madt_cpu,
|
||||
+ build_cpu_cppc_fn build_cpu_cppc,
|
||||
+ hwaddr base_addr,
|
||||
const char *res_root,
|
||||
const char *event_handler_method,
|
||||
AmlRegionSpace rs)
|
||||
@@ -668,6 +670,10 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
aml_append(dev, aml_name_decl("_UID", uid));
|
||||
}
|
||||
|
||||
+ if (build_cpu_cppc) {
|
||||
+ build_cpu_cppc(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);
|
||||
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
|
||||
index db4ca8a66a..e10799ecc6 100644
|
||||
--- a/hw/i386/acpi-build.c
|
||||
+++ b/hw/i386/acpi-build.c
|
||||
@@ -1545,7 +1545,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
.smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL,
|
||||
.fw_unplugs_cpu = pm->smi_on_cpu_unplug,
|
||||
};
|
||||
- build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
|
||||
+ build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry, NULL,
|
||||
pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02",
|
||||
AML_SYSTEM_IO);
|
||||
}
|
||||
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
||||
index 76bc7eb251..b31a2e50d9 100644
|
||||
--- a/include/hw/acpi/cpu.h
|
||||
+++ b/include/hw/acpi/cpu.h
|
||||
@@ -59,8 +59,12 @@ typedef struct CPUHotplugFeatures {
|
||||
typedef void (*build_madt_cpu_fn)(int uid, const CPUArchIdList *apic_ids,
|
||||
GArray *entry, bool force_enabled);
|
||||
|
||||
+typedef void (*build_cpu_cppc_fn)(int uid, int num_cpu, Aml *dev);
|
||||
+
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
- build_madt_cpu_fn build_madt_cpu, hwaddr base_addr,
|
||||
+ build_madt_cpu_fn build_madt_cpu,
|
||||
+ build_cpu_cppc_fn build_cpu_cppc,
|
||||
+ hwaddr base_addr,
|
||||
const char *res_root,
|
||||
const char *event_handler_method,
|
||||
AmlRegionSpace rs);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
36
acpi-cpu-Fix-cpu_hotplug_hw_init.patch
Normal file
36
acpi-cpu-Fix-cpu_hotplug_hw_init.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 14c4062c4acc7d417d163276b65e59073ba18eeb Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 14:51:18 +0800
|
||||
Subject: [PATCH] acpi/cpu: Fix cpu_hotplug_hw_init()
|
||||
|
||||
For the present but disabled vCPUs, they will be released after
|
||||
cpu_hotplug_hw_init(), we should not assign it to AcpiCpuStatus.
|
||||
|
||||
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 c922c380aa..b258396e01 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -229,7 +229,6 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
||||
for (i = 0; i < id_list->len; i++) {
|
||||
struct CPUState *cpu = CPU(id_list->cpus[i].cpu);
|
||||
if (qemu_present_cpu(cpu)) {
|
||||
- state->devs[i].cpu = cpu;
|
||||
state->devs[i].is_present = true;
|
||||
} else {
|
||||
if (qemu_persistent_cpu(cpu)) {
|
||||
@@ -240,6 +239,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
||||
}
|
||||
|
||||
if (qemu_enabled_cpu(cpu)) {
|
||||
+ state->devs[i].cpu = cpu;
|
||||
state->devs[i].is_enabled = true;
|
||||
} else {
|
||||
state->devs[i].is_enabled = false;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
47
acpi-ged-Init-cpu-hotplug-only-when-machine-support-.patch
Normal file
47
acpi-ged-Init-cpu-hotplug-only-when-machine-support-.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 6e17d32d6df25d4fac1a31da61d89e0bb9c8c7da Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 22:20:20 +0800
|
||||
Subject: [PATCH] acpi/ged: Init cpu hotplug only when machine support it
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index 0266733a54..6e4f5f075f 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -403,6 +403,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->evt, obj, &ged_evt_ops, ged_st,
|
||||
TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN);
|
||||
@@ -427,12 +428,15 @@ static void acpi_ged_initfn(Object *obj)
|
||||
TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT);
|
||||
sysbus_init_mmio(sbd, &ged_st->regs);
|
||||
|
||||
- s->cpuhp.device = OBJECT(s);
|
||||
- memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container",
|
||||
- ACPI_CPU_HOTPLUG_REG_LEN);
|
||||
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container_cpuhp);
|
||||
- cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
|
||||
- &s->cpuhp_state, 0);
|
||||
+ mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
+ if (mc->possible_cpu_arch_ids) {
|
||||
+ s->cpuhp.device = OBJECT(s);
|
||||
+ memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container",
|
||||
+ ACPI_CPU_HOTPLUG_REG_LEN);
|
||||
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &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)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
40
acpi-ged-Remove-cpuhp-field-of-ged.patch
Normal file
40
acpi-ged-Remove-cpuhp-field-of-ged.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 7af2722536b4b0d80f6c508066e8e77158869923 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 23:34:01 +0800
|
||||
Subject: [PATCH] acpi/ged: Remove cpuhp field of ged
|
||||
|
||||
It's unused.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 1 -
|
||||
include/hw/acpi/generic_event_device.h | 1 -
|
||||
2 files changed, 2 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index 6e4f5f075f..4731a614a3 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -430,7 +430,6 @@ static void acpi_ged_initfn(Object *obj)
|
||||
|
||||
mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
if (mc->possible_cpu_arch_ids) {
|
||||
- s->cpuhp.device = OBJECT(s);
|
||||
memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container",
|
||||
ACPI_CPU_HOTPLUG_REG_LEN);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container_cpuhp);
|
||||
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
||||
index a803ea818e..90fc41cbb8 100644
|
||||
--- a/include/hw/acpi/generic_event_device.h
|
||||
+++ b/include/hw/acpi/generic_event_device.h
|
||||
@@ -110,7 +110,6 @@ struct AcpiGedState {
|
||||
MemoryRegion container_memhp;
|
||||
CPUHotplugState cpuhp_state;
|
||||
MemoryRegion container_cpuhp;
|
||||
- AcpiCpuHotplug cpuhp;
|
||||
GEDState ged_state;
|
||||
uint32_t ged_event_bitmap;
|
||||
qemu_irq irq;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
51
arm-acpi-Enable-ACPI-support-for-vcpu-hotplug.patch
Normal file
51
arm-acpi-Enable-ACPI-support-for-vcpu-hotplug.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 37aab238363c8242aa76853396c4f272b5508bca Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Mon, 8 Jun 2020 15:25:35 +0100
|
||||
Subject: [PATCH] arm/acpi: Enable ACPI support for vcpu hotplug
|
||||
|
||||
ACPI is required to interface QEMU with the guest. Roughly falls into below
|
||||
cases,
|
||||
|
||||
1. Convey the possible vcpus config at the machine init time to the guest
|
||||
using various DSDT tables like MADT etc.
|
||||
2. Convey vcpu hotplug events to guest(using GED)
|
||||
3. Assist in evaluation of various ACPI methods(like _EVT, _STA, _OST, _EJ0,
|
||||
_MAT etc.)
|
||||
4. Provides ACPI cpu hotplug state and 12 Byte memory mapped cpu hotplug
|
||||
control register interface to the OSPM/guest corresponding to each possible
|
||||
vcpu. The register interface consists of various R/W fields and their
|
||||
handling operations. These are called when ever register fields or memory
|
||||
regions are accessed(i.e. read or written) by OSPM when ever it evaluates
|
||||
various ACPI methods.
|
||||
|
||||
Note: lot of this framework code is inherited from the changes already done for
|
||||
x86 but still some minor changes are required to make it compatible with
|
||||
ARM64.)
|
||||
|
||||
This patch enables the ACPI support for virtual cpu hotplug. ACPI changes
|
||||
required will follow in subsequent patches.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
|
||||
index 3ada335a24..c0a7d0bd58 100644
|
||||
--- a/hw/arm/Kconfig
|
||||
+++ b/hw/arm/Kconfig
|
||||
@@ -29,6 +29,7 @@ config ARM_VIRT
|
||||
select ACPI_HW_REDUCED
|
||||
select ACPI_APEI
|
||||
select ACPI_VIOT
|
||||
+ select ACPI_CPU_HOTPLUG
|
||||
select VIRTIO_MEM_SUPPORTED
|
||||
select ACPI_CXL
|
||||
select ACPI_HMAT
|
||||
--
|
||||
2.27.0
|
||||
|
||||
98
arm-acpi-Fix-when-make-qemu-system-aarch64-at-x86_64.patch
Normal file
98
arm-acpi-Fix-when-make-qemu-system-aarch64-at-x86_64.patch
Normal file
@ -0,0 +1,98 @@
|
||||
From d269fb9a41abf5888a9bfeec2f8d1684b2d4dfb0 Mon Sep 17 00:00:00 2001
|
||||
From: saarloos <9090-90-90-9090@163.com>
|
||||
Date: Sat, 30 Mar 2024 21:32:27 +0800
|
||||
Subject: [PATCH] arm/acpi: Fix when make qemu-system-aarch64 at x86_64 host
|
||||
bios_tables_test fail reason: __aarch64__ macro let build_pptt at x86_64 and
|
||||
aarch64 host build different function that let bios_tables_test fail.
|
||||
|
||||
Signed-off-by: Yangzi Zhang <zhangziyang1@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/acpi/aml-build.c | 5 +----
|
||||
hw/arm/virt-acpi-build.c | 2 +-
|
||||
include/hw/acpi/aml-build.h | 5 +++--
|
||||
3 files changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
||||
index 714498165a..bf9c59f544 100644
|
||||
--- a/hw/acpi/aml-build.c
|
||||
+++ b/hw/acpi/aml-build.c
|
||||
@@ -2016,7 +2016,6 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
}
|
||||
}
|
||||
|
||||
-#ifdef __aarch64__
|
||||
/*
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29.2 Cache Type Structure (Type 1)
|
||||
@@ -2072,7 +2071,7 @@ static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level,
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
*/
|
||||
-void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
+void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
@@ -2172,7 +2171,6 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
-#else
|
||||
/*
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
@@ -2248,7 +2246,6 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
-#endif
|
||||
|
||||
/* build rev1/rev3/rev5.1/rev6.0 FADT */
|
||||
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 3cb50bdc65..48fc77fb83 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -1024,7 +1024,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||
|
||||
if (!vmc->no_cpu_topology) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
- build_pptt(tables_blob, tables->linker, ms,
|
||||
+ build_pptt_arm(tables_blob, tables->linker, ms,
|
||||
vms->oem_id, vms->oem_table_id);
|
||||
}
|
||||
|
||||
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
||||
index 200cb113de..7281c281f6 100644
|
||||
--- a/include/hw/acpi/aml-build.h
|
||||
+++ b/include/hw/acpi/aml-build.h
|
||||
@@ -221,7 +221,6 @@ struct AcpiBuildTables {
|
||||
BIOSLinker *linker;
|
||||
} AcpiBuildTables;
|
||||
|
||||
-#ifdef __aarch64__
|
||||
/* Definitions of the hardcoded cache info*/
|
||||
|
||||
typedef enum {
|
||||
@@ -266,7 +265,6 @@ struct offset_status {
|
||||
uint32_t l1i_offset;
|
||||
};
|
||||
|
||||
-#endif
|
||||
|
||||
typedef
|
||||
struct CrsRangeEntry {
|
||||
@@ -542,6 +540,9 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
+void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
+ const char *oem_id, const char *oem_table_id);
|
||||
+
|
||||
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
78
arm-cpu-Some-fixes-for-arm_cpu_unrealizefn.patch
Normal file
78
arm-cpu-Some-fixes-for-arm_cpu_unrealizefn.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From b394996c99c0af0de870a5d79fff69f01d504b0c Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 14:47:07 +0800
|
||||
Subject: [PATCH] arm/cpu: Some fixes for arm_cpu_unrealizefn()
|
||||
|
||||
Some minor fixes for arm_cpu_unrealizefn().
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
target/arm/cpu.c | 33 +++++++++++++++++++++------------
|
||||
1 file changed, 21 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
||||
index 501f88eb2f..9dd61c10ea 100644
|
||||
--- a/target/arm/cpu.c
|
||||
+++ b/target/arm/cpu.c
|
||||
@@ -2418,6 +2418,7 @@ static void arm_cpu_unrealizefn(DeviceState *dev)
|
||||
CPUState *cs = CPU(dev);
|
||||
bool has_secure;
|
||||
|
||||
+#ifndef CONFIG_USER_ONLY
|
||||
has_secure = cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY);
|
||||
|
||||
/* rock 'n' un-roll, whatever happened in the arm_cpu_realizefn cleanly */
|
||||
@@ -2433,30 +2434,38 @@ static void arm_cpu_unrealizefn(DeviceState *dev)
|
||||
if (has_secure) {
|
||||
cpu_address_space_destroy(cs, ARMASIdx_S);
|
||||
}
|
||||
+#endif
|
||||
|
||||
destroy_cpreg_list(cpu);
|
||||
arm_cpu_unregister_gdb_regs(cpu);
|
||||
unregister_cp_regs_for_features(cpu);
|
||||
|
||||
+#ifndef CONFIG_USER_ONLY
|
||||
+ if (tcg_enabled() && cpu_isar_feature(aa64_rme, cpu)) {
|
||||
+ arm_unregister_el_change_hooks(cpu);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (cpu->sau_sregion && arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
g_free(env->sau.rbar);
|
||||
g_free(env->sau.rlar);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_PMSA) &&
|
||||
- arm_feature(env, ARM_FEATURE_V7) &&
|
||||
- cpu->pmsav7_dregion) {
|
||||
- if (arm_feature(env, ARM_FEATURE_V8)) {
|
||||
- g_free(env->pmsav8.rbar[M_REG_NS]);
|
||||
- g_free(env->pmsav8.rlar[M_REG_NS]);
|
||||
- if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
- g_free(env->pmsav8.rbar[M_REG_S]);
|
||||
- g_free(env->pmsav8.rlar[M_REG_S]);
|
||||
+ arm_feature(env, ARM_FEATURE_V7)) {
|
||||
+ if (cpu->pmsav7_dregion) {
|
||||
+ if (arm_feature(env, ARM_FEATURE_V8)) {
|
||||
+ g_free(env->pmsav8.rbar[M_REG_NS]);
|
||||
+ g_free(env->pmsav8.rlar[M_REG_NS]);
|
||||
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
+ g_free(env->pmsav8.rbar[M_REG_S]);
|
||||
+ g_free(env->pmsav8.rlar[M_REG_S]);
|
||||
+ }
|
||||
+ } else {
|
||||
+ g_free(env->pmsav7.drbar);
|
||||
+ g_free(env->pmsav7.drsr);
|
||||
+ g_free(env->pmsav7.dracr);
|
||||
}
|
||||
- } else {
|
||||
- g_free(env->pmsav7.drbar);
|
||||
- g_free(env->pmsav7.drsr);
|
||||
- g_free(env->pmsav7.dracr);
|
||||
}
|
||||
if (cpu->pmsav8r_hdregion) {
|
||||
g_free(env->pmsav8.hprbar);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
72
arm-kvm-Set-psci-smccc-filter-only-with-vcpu-hotplug.patch
Normal file
72
arm-kvm-Set-psci-smccc-filter-only-with-vcpu-hotplug.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From 85e8e1ee8560e587845142342f81b218e44cba6a Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 22:07:33 +0800
|
||||
Subject: [PATCH] arm/kvm: Set psci smccc filter only with vcpu hotplug
|
||||
|
||||
The smccc filter mechanism is supported by newer Linux kernel,
|
||||
don't try to do it unconditionaly.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 4 +++-
|
||||
target/arm/kvm.c | 21 ++++++++++++---------
|
||||
2 files changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index e60f3431f9..38b5d214a1 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2366,8 +2366,10 @@ static void machvirt_init(MachineState *machine)
|
||||
finalize_gic_version(vms);
|
||||
if (tcg_enabled() || hvf_enabled() || qtest_enabled() ||
|
||||
(vms->gic_version < VIRT_GIC_VERSION_3)) {
|
||||
- machine->smp.max_cpus = smp_cpus;
|
||||
mc->has_hotpluggable_cpus = false;
|
||||
+ }
|
||||
+ if (!mc->has_hotpluggable_cpus) {
|
||||
+ machine->smp.max_cpus = smp_cpus;
|
||||
warn_report("cpu hotplug feature has been disabled");
|
||||
}
|
||||
|
||||
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
||||
index 66caf9e5e7..19783d567f 100644
|
||||
--- a/target/arm/kvm.c
|
||||
+++ b/target/arm/kvm.c
|
||||
@@ -259,6 +259,7 @@ int kvm_arch_get_default_type(MachineState *ms)
|
||||
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
int ret = 0;
|
||||
|
||||
/* For ARM interrupt delivery is always asynchronous,
|
||||
@@ -316,15 +317,17 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
* filter in the Host KVM. This is required to support features like
|
||||
* virtual CPU Hotplug on ARM platforms.
|
||||
*/
|
||||
- if (kvm_arm_set_smccc_filter(PSCI_0_2_FN64_CPU_ON,
|
||||
- KVM_SMCCC_FILTER_FWD_TO_USER)) {
|
||||
- error_report("CPU On PSCI-to-user-space fwd filter install failed");
|
||||
- abort();
|
||||
- }
|
||||
- if (kvm_arm_set_smccc_filter(PSCI_0_2_FN_CPU_OFF,
|
||||
- KVM_SMCCC_FILTER_FWD_TO_USER)) {
|
||||
- error_report("CPU Off PSCI-to-user-space fwd filter install failed");
|
||||
- abort();
|
||||
+ if (mc->has_hotpluggable_cpus && ms->smp.max_cpus > ms->smp.cpus) {
|
||||
+ if (kvm_arm_set_smccc_filter(PSCI_0_2_FN64_CPU_ON,
|
||||
+ KVM_SMCCC_FILTER_FWD_TO_USER)) {
|
||||
+ error_report("CPU On PSCI-to-user-space fwd filter install failed");
|
||||
+ mc->has_hotpluggable_cpus = false;
|
||||
+ }
|
||||
+ if (kvm_arm_set_smccc_filter(PSCI_0_2_FN_CPU_OFF,
|
||||
+ KVM_SMCCC_FILTER_FWD_TO_USER)) {
|
||||
+ error_report("CPU Off PSCI-to-user-space fwd filter install failed");
|
||||
+ mc->has_hotpluggable_cpus = false;
|
||||
+ }
|
||||
}
|
||||
|
||||
kvm_arm_init_debug(s);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
67
arm-virt-Add-cpu-hotplug-events-to-GED-during-creati.patch
Normal file
67
arm-virt-Add-cpu-hotplug-events-to-GED-during-creati.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From f8914ec04d4d892520aa443eaf8018c80516adee Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sun, 6 Aug 2023 16:27:01 +0000
|
||||
Subject: [PATCH] arm/virt: Add cpu hotplug events to GED during creation
|
||||
|
||||
Add CPU Hotplug event to the set of supported ged-events during the creation of
|
||||
GED device during VM init. Also initialize the memory map for CPU Hotplug
|
||||
control device used in event exchanges between Qemu/VMM and the guest.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 5 ++++-
|
||||
include/hw/arm/virt.h | 1 +
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 78ed3c4ba8..155000f22f 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -78,6 +78,7 @@
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
+#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/virtio/virtio-md-pci.h"
|
||||
#include "hw/virtio/virtio-iommu.h"
|
||||
#include "hw/char/pl011.h"
|
||||
@@ -157,6 +158,7 @@ static const MemMapEntry base_memmap[] = {
|
||||
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
|
||||
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
|
||||
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
|
||||
+ [VIRT_CPUHP_ACPI] = { 0x090c0000, 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 */
|
||||
@@ -725,7 +727,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
DeviceState *dev;
|
||||
MachineState *ms = MACHINE(vms);
|
||||
int irq = vms->irqmap[VIRT_ACPI_GED];
|
||||
- uint32_t event = ACPI_GED_PWR_DOWN_EVT;
|
||||
+ uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_CPU_HOTPLUG_EVT;
|
||||
|
||||
if (ms->ram_slots) {
|
||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
||||
@@ -741,6 +743,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
|
||||
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), 3, vms->memmap[VIRT_CPUHP_ACPI].base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
|
||||
|
||||
return dev;
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index c2fde0522c..5de0185063 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -76,6 +76,7 @@ enum {
|
||||
VIRT_PCDIMM_ACPI,
|
||||
VIRT_ACPI_GED,
|
||||
VIRT_NVDIMM_ACPI,
|
||||
+ VIRT_CPUHP_ACPI,
|
||||
VIRT_PVTIME,
|
||||
VIRT_LOWMEMMAP_LAST,
|
||||
};
|
||||
--
|
||||
2.27.0
|
||||
|
||||
197
arm-virt-Add-update-basic-hot-un-plug-framework.patch
Normal file
197
arm-virt-Add-update-basic-hot-un-plug-framework.patch
Normal file
@ -0,0 +1,197 @@
|
||||
From 724ab355c047cfb3e970d9ea78577087568eb095 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Fri, 8 May 2020 18:40:19 +0100
|
||||
Subject: [PATCH] arm/virt: Add/update basic hot-(un)plug framework
|
||||
|
||||
Add CPU hot-unplug hooks and update hotplug hooks with additional sanity checks
|
||||
for use in hotplug paths.
|
||||
|
||||
Note, Functional contents of the hooks(now left with TODO comment) shall be
|
||||
gradually filled in the subsequent patches in an incremental approach to patch
|
||||
and logic building which would be roughly as follows:
|
||||
1. (Un-)wiring of interrupts between vCPU<->GIC
|
||||
2. Sending events to Guest for hot-(un)plug so that guest can take appropriate
|
||||
actions.
|
||||
3. Notifying GIC about hot-(un)plug action so that vCPU could be (un-)stitched
|
||||
to the GIC CPU interface.
|
||||
4. Updating the Guest with Next boot info for this vCPU in the firmware.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 104 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index bf385a469c..ed354be326 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -83,6 +83,7 @@
|
||||
#include "hw/virtio/virtio-iommu.h"
|
||||
#include "hw/char/pl011.h"
|
||||
#include "qemu/guest-random.h"
|
||||
+#include "qapi/qmp/qdict.h"
|
||||
|
||||
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
|
||||
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
|
||||
@@ -3083,12 +3084,23 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
MachineState *ms = MACHINE(hotplug_dev);
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
ARMCPU *cpu = ARM_CPU(dev);
|
||||
CPUState *cs = CPU(dev);
|
||||
CPUArchId *cpu_slot;
|
||||
int32_t min_cpuid = 0;
|
||||
int32_t max_cpuid;
|
||||
|
||||
+ if (dev->hotplugged && !vms->acpi_dev) {
|
||||
+ error_setg(errp, "GED acpi device does not exists");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
|
||||
+ error_setg(errp, "CPU hotplug not supported on this machine");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* sanity check the cpu */
|
||||
if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
||||
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
||||
@@ -3137,6 +3149,22 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
}
|
||||
virt_cpu_set_properties(OBJECT(cs), cpu_slot, errp);
|
||||
|
||||
+ /*
|
||||
+ * Fix the GIC for this new vCPU being plugged. The QOM CPU object for the
|
||||
+ * new vCPU need to be updated in the corresponding QOM GICv3CPUState object
|
||||
+ * We also need to re-wire the IRQs for this new CPU object. This update
|
||||
+ * is limited to the QOM only and does not affects the KVM. Later has
|
||||
+ * already been pre-sized with possible CPU at VM init time. This is a
|
||||
+ * workaround to the constraints posed by ARM architecture w.r.t supporting
|
||||
+ * CPU Hotplug. Specification does not exist for the later.
|
||||
+ * This patch-up is required both for {cold,hot}-plugged vCPUs. Cold-inited
|
||||
+ * vCPUs have their GIC state initialized during machvit_init().
|
||||
+ */
|
||||
+ if (vms->acpi_dev) {
|
||||
+ /* TODO: update GIC about this hotplug change here */
|
||||
+ /* TODO: wire the GIC<->CPU irqs */
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* To give persistent presence view of vCPUs to the guest, ACPI might need
|
||||
* to fake the presence of the vCPUs to the guest but keep them disabled.
|
||||
@@ -3148,6 +3176,7 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
MachineState *ms = MACHINE(hotplug_dev);
|
||||
CPUState *cs = CPU(dev);
|
||||
CPUArchId *cpu_slot;
|
||||
@@ -3156,10 +3185,81 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
cpu_slot->cpu = OBJECT(dev);
|
||||
|
||||
+ /*
|
||||
+ * Update the ACPI Hotplug state both for vCPUs being {hot,cold}-plugged.
|
||||
+ * vCPUs can be cold-plugged using '-device' option. For vCPUs being hot
|
||||
+ * plugged, guest is also notified.
|
||||
+ */
|
||||
+ if (vms->acpi_dev) {
|
||||
+ /* TODO: update acpi hotplug state. Send cpu hotplug event to guest */
|
||||
+ /* TODO: register cpu for reset & update F/W info for the next boot */
|
||||
+ }
|
||||
+
|
||||
cs->disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
+static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
+ DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
+ ARMCPU *cpu = ARM_CPU(dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+
|
||||
+ if (!vms->acpi_dev || !dev->realized) {
|
||||
+ error_setg(errp, "GED does not exists or device is not realized!");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!mc->has_hotpluggable_cpus) {
|
||||
+ error_setg(errp, "CPU hot(un)plug not supported on this machine");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (cs->cpu_index == first_cpu->cpu_index) {
|
||||
+ error_setg(errp, "Boot CPU(id%d=%d:%d:%d:%d) hot-unplug not supported",
|
||||
+ first_cpu->cpu_index, cpu->socket_id, cpu->cluster_id,
|
||||
+ cpu->core_id, cpu->thread_id);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO: request cpu hotplug from guest */
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
+ MachineState *ms = MACHINE(hotplug_dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+ CPUArchId *cpu_slot;
|
||||
+
|
||||
+ if (!vms->acpi_dev || !dev->realized) {
|
||||
+ error_setg(errp, "GED does not exists or device is not realized!");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
+
|
||||
+ /* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
|
||||
+
|
||||
+ /* TODO: unwire the gic-cpu irqs here */
|
||||
+ /* TODO: update the GIC about this hot unplug change */
|
||||
+
|
||||
+ /* TODO: unregister cpu for reset & update F/W info for the next boot */
|
||||
+
|
||||
+ qobject_unref(dev->opts);
|
||||
+ dev->opts = NULL;
|
||||
+
|
||||
+ cpu_slot->cpu = NULL;
|
||||
+ cs->disabled = true;
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -3284,6 +3384,8 @@ static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
|
||||
virtio_md_pci_unplug_request(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev),
|
||||
errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ virt_cpu_unplug_request(hotplug_dev, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "device unplug request for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -3297,6 +3399,8 @@ static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
|
||||
virt_dimm_unplug(hotplug_dev, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
|
||||
virtio_md_pci_unplug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ virt_cpu_unplug(hotplug_dev, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "virt: device unplug for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
--
|
||||
2.27.0
|
||||
|
||||
221
arm-virt-Changes-to-un-wire-GICC-vCPU-IRQs-during-ho.patch
Normal file
221
arm-virt-Changes-to-un-wire-GICC-vCPU-IRQs-during-ho.patch
Normal file
@ -0,0 +1,221 @@
|
||||
From a68abeefcbd78daaf7179b922f6b9040b4b63101 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 9 May 2020 15:50:33 +0100
|
||||
Subject: [PATCH] arm/virt: Changes to (un)wire GICC<->vCPU IRQs during
|
||||
hot-(un)plug
|
||||
|
||||
Refactors the existing GIC create code to extract common code to wire the
|
||||
vcpu<->gic interrupts. This function could be used with cold-plug case and also
|
||||
used when vCPU is hot-plugged. It also introduces a new function to unwire the
|
||||
vcpu<->gic interrupts for the vCPU hot-unplug cases.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 138 ++++++++++++++++++++++++++++-------------
|
||||
hw/core/gpio.c | 2 +-
|
||||
include/hw/qdev-core.h | 2 +
|
||||
3 files changed, 99 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index ed354be326..97bf4cca11 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -798,6 +798,99 @@ static void create_v2m(VirtMachineState *vms)
|
||||
vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 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,
|
||||
+};
|
||||
+
|
||||
+static void unwire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(vms);
|
||||
+ unsigned int max_cpus = ms->smp.max_cpus;
|
||||
+ DeviceState *cpudev = DEVICE(cs);
|
||||
+ DeviceState *gicdev = vms->gic;
|
||||
+ int cpu = CPU(cs)->cpu_index;
|
||||
+ int type = vms->gic_version;
|
||||
+ int irq;
|
||||
+
|
||||
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
+ qdev_disconnect_gpio_out_named(cpudev, NULL, irq);
|
||||
+ }
|
||||
+
|
||||
+ if (type != VIRT_GIC_VERSION_2) {
|
||||
+ qdev_disconnect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
|
||||
+ 0);
|
||||
+ } else if (vms->virt) {
|
||||
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
|
||||
+ cpu + 4 * max_cpus);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * RFC: Question: This currently does not takes care of intimating the
|
||||
+ * devices which might be sitting on system bus. Do we need a
|
||||
+ * sysbus_disconnect_irq() which also does the job of notification beside
|
||||
+ * disconnection?
|
||||
+ */
|
||||
+ qdev_disconnect_gpio_out_named(cpudev, "pmu-interrupt", 0);
|
||||
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ, cpu);
|
||||
+ qdev_disconnect_gpio_out_named(gicdev,
|
||||
+ SYSBUS_DEVICE_GPIO_IRQ, cpu + max_cpus);
|
||||
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
|
||||
+ cpu + 2 * max_cpus);
|
||||
+ qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
|
||||
+ cpu + 3 * max_cpus);
|
||||
+}
|
||||
+
|
||||
+static void wire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(vms);
|
||||
+ unsigned int max_cpus = ms->smp.max_cpus;
|
||||
+ DeviceState *cpudev = DEVICE(cs);
|
||||
+ DeviceState *gicdev = vms->gic;
|
||||
+ int cpu = CPU(cs)->cpu_index;
|
||||
+ int type = vms->gic_version;
|
||||
+ SysBusDevice *gicbusdev;
|
||||
+ int intidbase;
|
||||
+ int irq;
|
||||
+
|
||||
+ intidbase = NUM_IRQS + cpu * GIC_INTERNAL;
|
||||
+
|
||||
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
+ qdev_connect_gpio_out(cpudev, irq,
|
||||
+ qdev_get_gpio_in(gicdev,
|
||||
+ intidbase + timer_irq[irq]));
|
||||
+ }
|
||||
+
|
||||
+ gicbusdev = SYS_BUS_DEVICE(gicdev);
|
||||
+ if (type != VIRT_GIC_VERSION_2) {
|
||||
+ qemu_irq qirq = qdev_get_gpio_in(gicdev,
|
||||
+ intidbase + ARCH_GIC_MAINT_IRQ);
|
||||
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
|
||||
+ 0, qirq);
|
||||
+ } else if (vms->virt) {
|
||||
+ qemu_irq qirq = qdev_get_gpio_in(gicdev,
|
||||
+ intidbase + ARCH_GIC_MAINT_IRQ);
|
||||
+ sysbus_connect_irq(gicbusdev, cpu + 4 * max_cpus, qirq);
|
||||
+ }
|
||||
+
|
||||
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
||||
+ qdev_get_gpio_in(gicdev,
|
||||
+ intidbase + VIRTUAL_PMU_IRQ));
|
||||
+ sysbus_connect_irq(gicbusdev, cpu, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||
+ sysbus_connect_irq(gicbusdev, cpu + max_cpus,
|
||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
||||
+ sysbus_connect_irq(gicbusdev, cpu + 2 * max_cpus,
|
||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
||||
+ sysbus_connect_irq(gicbusdev, cpu + 3 * max_cpus,
|
||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
||||
+}
|
||||
+
|
||||
static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
{
|
||||
MachineState *ms = MACHINE(vms);
|
||||
@@ -894,46 +987,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
* 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 intidbase = NUM_IRQS + i * GIC_INTERNAL;
|
||||
- /* 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 (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
- qdev_connect_gpio_out(cpudev, irq,
|
||||
- qdev_get_gpio_in(vms->gic,
|
||||
- intidbase + timer_irq[irq]));
|
||||
- }
|
||||
-
|
||||
- if (vms->gic_version != VIRT_GIC_VERSION_2) {
|
||||
- qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
||||
- intidbase + 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,
|
||||
- intidbase + ARCH_GIC_MAINT_IRQ);
|
||||
- sysbus_connect_irq(gicbusdev, i + 4 * max_cpus, irq);
|
||||
- }
|
||||
-
|
||||
- qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
||||
- qdev_get_gpio_in(vms->gic, intidbase
|
||||
- + VIRTUAL_PMU_IRQ));
|
||||
-
|
||||
- sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + max_cpus,
|
||||
- qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + 2 * max_cpus,
|
||||
- qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + 3 * max_cpus,
|
||||
- qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
||||
+ wire_gic_cpu_irqs(vms, qemu_get_cpu(i));
|
||||
}
|
||||
|
||||
fdt_add_gic_node(vms);
|
||||
@@ -3162,7 +3216,7 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
*/
|
||||
if (vms->acpi_dev) {
|
||||
/* TODO: update GIC about this hotplug change here */
|
||||
- /* TODO: wire the GIC<->CPU irqs */
|
||||
+ wire_gic_cpu_irqs(vms, cs);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3246,7 +3300,7 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
|
||||
/* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
|
||||
|
||||
- /* TODO: unwire the gic-cpu irqs here */
|
||||
+ unwire_gic_cpu_irqs(vms, cs);
|
||||
/* TODO: update the GIC about this hot unplug change */
|
||||
|
||||
/* TODO: unregister cpu for reset & update F/W info for the next boot */
|
||||
diff --git a/hw/core/gpio.c b/hw/core/gpio.c
|
||||
index 80d07a6ec9..abb164d5c0 100644
|
||||
--- a/hw/core/gpio.c
|
||||
+++ b/hw/core/gpio.c
|
||||
@@ -143,7 +143,7 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
|
||||
|
||||
/* disconnect a GPIO output, returning the disconnected input (if any) */
|
||||
|
||||
-static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
|
||||
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
|
||||
const char *name, int n)
|
||||
{
|
||||
char *propname = g_strdup_printf("%s[%d]",
|
||||
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
|
||||
index 151d968238..2d3661d6cd 100644
|
||||
--- a/include/hw/qdev-core.h
|
||||
+++ b/include/hw/qdev-core.h
|
||||
@@ -739,6 +739,8 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n);
|
||||
*/
|
||||
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
|
||||
const char *name, int n);
|
||||
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
|
||||
+ const char *name, int n);
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
73
arm-virt-Consider-has_ged-when-set-mc-has_hotpluggab.patch
Normal file
73
arm-virt-Consider-has_ged-when-set-mc-has_hotpluggab.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From baa26f2fc075522f91c3e9a332fc4fa3f3b167bf Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 22:55:49 +0800
|
||||
Subject: [PATCH] arm/virt: Consider has_ged when set mc->has_hotpluggable_cpus
|
||||
|
||||
Vcpu hotplug relies on ged device.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 26 ++++++++++++++++----------
|
||||
1 file changed, 16 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 38b5d214a1..00e57f2d75 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2357,6 +2357,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;
|
||||
|
||||
if (!cpu_type_valid(machine->cpu_type)) {
|
||||
error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
|
||||
@@ -2364,14 +2365,6 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
|
||||
finalize_gic_version(vms);
|
||||
- if (tcg_enabled() || hvf_enabled() || qtest_enabled() ||
|
||||
- (vms->gic_version < VIRT_GIC_VERSION_3)) {
|
||||
- mc->has_hotpluggable_cpus = false;
|
||||
- }
|
||||
- if (!mc->has_hotpluggable_cpus) {
|
||||
- machine->smp.max_cpus = smp_cpus;
|
||||
- warn_report("cpu hotplug feature has been disabled");
|
||||
- }
|
||||
|
||||
possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
|
||||
@@ -2501,6 +2494,21 @@ static void machvirt_init(MachineState *machine)
|
||||
create_fdt(vms);
|
||||
qemu_log("cpu init start\n");
|
||||
|
||||
+ cpu_class = object_class_by_name(machine->cpu_type);
|
||||
+ has_ged = has_ged && firmware_loaded &&
|
||||
+ virt_is_acpi_enabled(vms) &&
|
||||
+ !!object_class_dynamic_cast(cpu_class, TYPE_AARCH64_CPU);
|
||||
+ if (tcg_enabled() || hvf_enabled() || qtest_enabled() ||
|
||||
+ (vms->gic_version < VIRT_GIC_VERSION_3) || !has_ged) {
|
||||
+ mc->has_hotpluggable_cpus = false;
|
||||
+ }
|
||||
+ if (!mc->has_hotpluggable_cpus) {
|
||||
+ if (machine->smp.max_cpus > smp_cpus) {
|
||||
+ warn_report("cpu hotplug feature has been disabled");
|
||||
+ }
|
||||
+ machine->smp.max_cpus = smp_cpus;
|
||||
+ }
|
||||
+
|
||||
notifier_list_init(&vms->cpuhp_notifiers);
|
||||
possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
assert(possible_cpus->len == max_cpus);
|
||||
@@ -2581,8 +2589,6 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_gic(vms, sysmem);
|
||||
|
||||
- has_ged = has_ged && aarch64 && firmware_loaded &&
|
||||
- virt_is_acpi_enabled(vms);
|
||||
if (has_ged) {
|
||||
vms->acpi_dev = create_acpi_ged(vms);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
54
arm-virt-Create-GED-dev-before-disabled-CPU-Objs-are.patch
Normal file
54
arm-virt-Create-GED-dev-before-disabled-CPU-Objs-are.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 028d71744dfeedabfa67d629c71a6ed5e494cc68 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 29 Aug 2023 00:47:05 +0000
|
||||
Subject: [PATCH] arm/virt: Create GED dev before *disabled* CPU Objs are
|
||||
destroyed
|
||||
|
||||
ACPI CPU hotplug state (is_present=_STA.PRESENT, is_enabled=_STA.ENABLED) for
|
||||
all the possible vCPUs MUST be initialized during machine init. This is done
|
||||
during the creation of the GED device. VMM/Qemu MUST expose/fake the ACPI state
|
||||
of the disabled vCPUs to the Guest kernel as 'present' (_STA.PRESENT) always
|
||||
i.e. ACPI persistent. if the 'disabled' vCPU objectes are destroyed before the
|
||||
GED device has been created then their ACPI hotplug state might not get
|
||||
initialized correctly as acpi_persistent flag is part of the CPUState. This will
|
||||
expose wrong status of the unplugged vCPUs to the Guest kernel.
|
||||
|
||||
Hence, moving the GED device creation before disabled vCPU objects get destroyed
|
||||
as part of the post CPU init routine.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 155000f22f..818398e753 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2472,6 +2472,12 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_gic(vms, sysmem);
|
||||
|
||||
+ has_ged = has_ged && aarch64 && firmware_loaded &&
|
||||
+ virt_is_acpi_enabled(vms);
|
||||
+ if (has_ged) {
|
||||
+ vms->acpi_dev = create_acpi_ged(vms);
|
||||
+ }
|
||||
+
|
||||
virt_cpu_post_init(vms, sysmem);
|
||||
|
||||
fdt_add_pmu_nodes(vms);
|
||||
@@ -2496,9 +2502,7 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_pcie(vms);
|
||||
|
||||
- if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
|
||||
- vms->acpi_dev = create_acpi_ged(vms);
|
||||
- } else {
|
||||
+ if (!has_ged) {
|
||||
create_gpio_devices(vms, VIRT_GPIO, sysmem);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
47
arm-virt-Fix-adjudgement-of-core_id-for-vcpu-hotplug.patch
Normal file
47
arm-virt-Fix-adjudgement-of-core_id-for-vcpu-hotplug.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 00a78edf572783c18a1d4945758371c0f175e321 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 15:41:14 +0800
|
||||
Subject: [PATCH] arm/virt: Fix adjudgement of core_id for vcpu hotplugged
|
||||
|
||||
The core_id should between 0 and ms->smp.cores - 1.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 14 +++-----------
|
||||
1 file changed, 3 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 934b0412ef..e60f3431f9 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3170,8 +3170,6 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
ARMCPU *cpu = ARM_CPU(dev);
|
||||
CPUState *cs = CPU(dev);
|
||||
CPUArchId *cpu_slot;
|
||||
- int32_t min_cpuid = 0;
|
||||
- int32_t max_cpuid;
|
||||
|
||||
if (dev->hotplugged && !vms->acpi_dev) {
|
||||
error_setg(errp, "GED acpi device does not exists");
|
||||
@@ -3196,15 +3194,9 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
- max_cpuid = ms->possible_cpus->len - 1;
|
||||
- if (!dev->hotplugged) {
|
||||
- min_cpuid = vms->acpi_dev ? ms->smp.cpus : 0;
|
||||
- max_cpuid = vms->acpi_dev ? max_cpuid : ms->smp.cpus - 1;
|
||||
- }
|
||||
-
|
||||
- if ((cpu->core_id < min_cpuid) || (cpu->core_id > max_cpuid)) {
|
||||
- error_setg(errp, "Invalid core-id %d specified, correct range %d:%d",
|
||||
- cpu->core_id, min_cpuid, max_cpuid);
|
||||
+ if ((cpu->core_id < 0) || (cpu->core_id >= ms->smp.cores)) {
|
||||
+ error_setg(errp, "Invalid core-id %d specified, correct range 0:%u",
|
||||
+ cpu->core_id, ms->smp.cores - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
71
arm-virt-Init-PMU-at-host-for-all-possible-vcpus.patch
Normal file
71
arm-virt-Init-PMU-at-host-for-all-possible-vcpus.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From c375e6fdc49f7d3d0232786e4cfd8b792379107c Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Wed, 6 May 2020 14:12:34 +0100
|
||||
Subject: [PATCH] arm/virt: Init PMU at host for all possible vcpus
|
||||
|
||||
PMU for all possible vCPUs must be initialized at the VM initialization time.
|
||||
Refactor existing code to accomodate possible vCPUs. This also assumes that all
|
||||
processor being used are identical.
|
||||
|
||||
Past discussion for reference:
|
||||
Link: https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg00131.html
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 12 ++++++++----
|
||||
include/hw/arm/virt.h | 1 +
|
||||
2 files changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 08ba255317..78ed3c4ba8 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2055,12 +2055,14 @@ static void finalize_gic_version(VirtMachineState *vms)
|
||||
*/
|
||||
static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
{
|
||||
+ CPUArchIdList *possible_cpus = vms->parent.possible_cpus;
|
||||
int max_cpus = MACHINE(vms)->smp.max_cpus;
|
||||
- bool aarch64, pmu, steal_time;
|
||||
+ bool aarch64, steal_time;
|
||||
CPUState *cpu;
|
||||
+ int n;
|
||||
|
||||
aarch64 = object_property_get_bool(OBJECT(first_cpu), "aarch64", NULL);
|
||||
- pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
|
||||
+ vms->pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
|
||||
steal_time = object_property_get_bool(OBJECT(first_cpu),
|
||||
"kvm-steal-time", NULL);
|
||||
|
||||
@@ -2087,8 +2089,10 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
memory_region_add_subregion(sysmem, pvtime_reg_base, pvtime);
|
||||
}
|
||||
|
||||
- CPU_FOREACH(cpu) {
|
||||
- if (pmu) {
|
||||
+ for (n = 0; n < possible_cpus->len; n++) {
|
||||
+ cpu = qemu_get_possible_cpu(n);
|
||||
+
|
||||
+ if (vms->pmu) {
|
||||
assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU));
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
kvm_arm_pmu_set_irq(cpu, VIRTUAL_PMU_IRQ);
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index a6977bade5..c2fde0522c 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -155,6 +155,7 @@ struct VirtMachineState {
|
||||
bool ras;
|
||||
bool mte;
|
||||
bool dtb_randomness;
|
||||
+ bool pmu;
|
||||
OnOffAuto acpi;
|
||||
VirtGICType gic_version;
|
||||
VirtIOMMUType iommu;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
97
arm-virt-Make-ARM-vCPU-present-status-ACPI-persisten.patch
Normal file
97
arm-virt-Make-ARM-vCPU-present-status-ACPI-persisten.patch
Normal file
@ -0,0 +1,97 @@
|
||||
From 3780dddd4fc8f0471525c50893e24846d1474692 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 8 Aug 2023 00:43:18 +0000
|
||||
Subject: [PATCH] arm/virt: Make ARM vCPU *present* status ACPI *persistent*
|
||||
|
||||
ARM arch does not allow CPUs presence to be changed [1] after kernel has booted.
|
||||
Hence, firmware/ACPI/Qemu must ensure persistent view of the vCPUs to the Guest
|
||||
kernel even when they are not present in the QoM i.e. are unplugged or are
|
||||
yet-to-be-plugged
|
||||
|
||||
References:
|
||||
[1] Check comment 5 in the bugzilla entry
|
||||
Link: https://bugzilla.tianocore.org/show_bug.cgi?id=4481#c5
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
cpu-common.c | 6 ++++++
|
||||
hw/arm/virt.c | 7 +++++++
|
||||
include/hw/core/cpu.h | 20 ++++++++++++++++++++
|
||||
3 files changed, 33 insertions(+)
|
||||
|
||||
diff --git a/cpu-common.c b/cpu-common.c
|
||||
index d041a351ab..da52e45760 100644
|
||||
--- a/cpu-common.c
|
||||
+++ b/cpu-common.c
|
||||
@@ -128,6 +128,12 @@ bool qemu_enabled_cpu(CPUState *cpu)
|
||||
return cpu && !cpu->disabled;
|
||||
}
|
||||
|
||||
+bool qemu_persistent_cpu(CPUState *cpu)
|
||||
+{
|
||||
+ /* cpu state can be faked to the guest via acpi */
|
||||
+ return cpu->acpi_persistent;
|
||||
+}
|
||||
+
|
||||
uint64_t qemu_get_cpu_archid(int cpu_index)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 818398e753..91b2653c03 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3104,6 +3104,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
return;
|
||||
}
|
||||
virt_cpu_set_properties(OBJECT(cs), cpu_slot, errp);
|
||||
+
|
||||
+ /*
|
||||
+ * To give persistent presence view of vCPUs to the guest, ACPI might need
|
||||
+ * to fake the presence of the vCPUs to the guest but keep them disabled.
|
||||
+ * This shall be used during the init of ACPI Hotplug state and hot-unplug
|
||||
+ */
|
||||
+ cs->acpi_persistent = true;
|
||||
}
|
||||
|
||||
static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
||||
index fdfb952259..0ca778eb75 100644
|
||||
--- a/include/hw/core/cpu.h
|
||||
+++ b/include/hw/core/cpu.h
|
||||
@@ -550,6 +550,13 @@ struct CPUState {
|
||||
* By default every CPUState is enabled as of now across all archs.
|
||||
*/
|
||||
bool disabled;
|
||||
+ /*
|
||||
+ * On certain architectures, to give persistent view of the 'presence' of
|
||||
+ * vCPUs to the guest, ACPI might need to fake the 'presence' of the vCPUs
|
||||
+ * but keep them ACPI disabled to the guest. This is done by returning
|
||||
+ * _STA.PRES=True and _STA.Ena=False for the unplugged vCPUs in QEMU QoM.
|
||||
+ */
|
||||
+ bool acpi_persistent;
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
int cpu_index;
|
||||
int cluster_index;
|
||||
@@ -957,6 +964,19 @@ bool qemu_present_cpu(CPUState *cpu);
|
||||
*/
|
||||
bool qemu_enabled_cpu(CPUState *cpu);
|
||||
|
||||
+/**
|
||||
+ * qemu_persistent_cpu:
|
||||
+ * @cpu: The vCPU to check
|
||||
+ *
|
||||
+ * Checks if the vCPU state should always be reflected as *present* via ACPI
|
||||
+ * to the Guest. By default, this is False on all architectures and has to be
|
||||
+ * explicity set during initialization.
|
||||
+ *
|
||||
+ * Returns: True if it is ACPI 'persistent' CPU
|
||||
+ *
|
||||
+ */
|
||||
+bool qemu_persistent_cpu(CPUState *cpu);
|
||||
+
|
||||
/**
|
||||
* qemu_get_cpu_archid:
|
||||
* @cpu_index: possible vCPU for which arch-id needs to be retreived
|
||||
--
|
||||
2.27.0
|
||||
|
||||
88
arm-virt-Release-objects-for-disabled-possible-vCPUs.patch
Normal file
88
arm-virt-Release-objects-for-disabled-possible-vCPUs.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From 097e3b46a7eede0182a846f7b993e14d3eed83b7 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 9 Jun 2020 03:01:08 +0100
|
||||
Subject: [PATCH] arm/virt: Release objects for *disabled* possible vCPUs after
|
||||
init
|
||||
|
||||
During machvirt_init(), QOM ARMCPU objects are also pre-created along with the
|
||||
corresponding KVM vCPUs in the host for all possible vCPUs. This necessary
|
||||
because of the architectural constraint, KVM restricts the deferred creation of
|
||||
the KVM vCPUs and VGIC initialization/sizing after VM init. Hence, VGIC is
|
||||
pre-sized with possible vCPUs.
|
||||
|
||||
After initialization of the machine is complete disabled possible KVM vCPUs are
|
||||
then parked at the per-virt-machine list "kvm_parked_vcpus" and we release the
|
||||
QOM ARMCPU objects for the disabled vCPUs. These shall be re-created at the time
|
||||
when vCPU is hotplugged again. QOM ARMCPU object is then re-attached with
|
||||
corresponding parked KVM vCPU.
|
||||
|
||||
Alternatively, we could've never released the QOM CPU objects and kept on
|
||||
reusing. This approach might require some modifications of qdevice_add()
|
||||
interface to get old ARMCPU object instead of creating a new one for the hotplug
|
||||
request.
|
||||
|
||||
Each of the above approaches come with their own pros and cons. This prototype
|
||||
uses the 1st approach.(suggestions are welcome!)
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 32 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 32 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 91b2653c03..bf385a469c 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2060,6 +2060,7 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
{
|
||||
CPUArchIdList *possible_cpus = vms->parent.possible_cpus;
|
||||
int max_cpus = MACHINE(vms)->smp.max_cpus;
|
||||
+ MachineState *ms = MACHINE(vms);
|
||||
bool aarch64, steal_time;
|
||||
CPUState *cpu;
|
||||
int n;
|
||||
@@ -2120,6 +2121,37 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (kvm_enabled() || tcg_enabled()) {
|
||||
+ for (n = 0; n < possible_cpus->len; n++) {
|
||||
+ cpu = qemu_get_possible_cpu(n);
|
||||
+
|
||||
+ /*
|
||||
+ * Now, GIC has been sized with possible CPUs and we dont require
|
||||
+ * disabled vCPU objects to be represented in the QOM. Release the
|
||||
+ * disabled ARMCPU objects earlier used during init for pre-sizing.
|
||||
+ *
|
||||
+ * We fake to the guest through ACPI about the presence(_STA.PRES=1)
|
||||
+ * of these non-existent vCPUs at VMM/qemu and present these as
|
||||
+ * disabled vCPUs(_STA.ENA=0) so that they cant be used. These vCPUs
|
||||
+ * can be later added to the guest through hotplug exchanges when
|
||||
+ * ARMCPU objects are created back again using 'device_add' QMP
|
||||
+ * command.
|
||||
+ */
|
||||
+ /*
|
||||
+ * RFC: Question: Other approach could've been to keep them forever
|
||||
+ * and release it only once when qemu exits as part of finalize or
|
||||
+ * when new vCPU is hotplugged. In the later old could be released
|
||||
+ * for the newly created object for the same vCPU?
|
||||
+ */
|
||||
+ if (!qemu_enabled_cpu(cpu)) {
|
||||
+ CPUArchId *cpu_slot;
|
||||
+ cpu_slot = virt_find_cpu_slot(ms, cpu->cpu_index);
|
||||
+ cpu_slot->cpu = NULL;
|
||||
+ object_unref(OBJECT(cpu));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
static void virt_cpu_set_properties(Object *cpuobj, const CPUArchId *cpu_slot,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
55
arm-virt-Require-mc-has_hotpluggable_cpus-for-cold-p.patch
Normal file
55
arm-virt-Require-mc-has_hotpluggable_cpus-for-cold-p.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 519699c61eeb980bb7d7f443eb95c0406aae82da Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 23:05:39 +0800
|
||||
Subject: [PATCH] arm/virt: Require mc->has_hotpluggable_cpus for cold-plugged
|
||||
vcpu
|
||||
|
||||
Cold-plugged vCPU also need mc->has_hotpluggable_cpus.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 00e57f2d75..73b29c7f73 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3179,16 +3179,6 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
CPUState *cs = CPU(dev);
|
||||
CPUArchId *cpu_slot;
|
||||
|
||||
- if (dev->hotplugged && !vms->acpi_dev) {
|
||||
- error_setg(errp, "GED acpi device does not exists");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
|
||||
- error_setg(errp, "CPU hotplug not supported on this machine");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
/* sanity check the cpu */
|
||||
if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
||||
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
||||
@@ -3222,6 +3212,17 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
|
||||
cs->cpu_index = virt_get_cpu_id_from_cpu_topo(ms, dev);
|
||||
|
||||
+ /* Except for cold-booted vCPUs, this should check presence of ACPI GED */
|
||||
+ if (cs->cpu_index >= ms->smp.cpus && !vms->acpi_dev) {
|
||||
+ error_setg(errp, "GED acpi device does not exists");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (cs->cpu_index >= ms->smp.cpus && !mc->has_hotpluggable_cpus) {
|
||||
+ error_setg(errp, "CPU [cold|hot]plug not supported on this machine");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
if (qemu_present_cpu(CPU(cpu_slot->cpu))) {
|
||||
error_setg(errp, "cpu(id%d=%d:%d:%d:%d) with arch-id %" PRIu64 " exist",
|
||||
--
|
||||
2.27.0
|
||||
|
||||
123
arm-virt-Update-the-guest-via-GED-about-CPU-hot-un-p.patch
Normal file
123
arm-virt-Update-the-guest-via-GED-about-CPU-hot-un-p.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From afb71c88d935349cdf9763e8f51f77334ab615ec Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Fri, 8 May 2020 18:54:10 +0100
|
||||
Subject: [PATCH] arm/virt: Update the guest(via GED) about CPU hot-(un)plug
|
||||
events
|
||||
|
||||
During any vCPU hot-(un)plug, running guest VM needs to be intimated about the
|
||||
new vCPU being added or request the deletion of the vCPU which is already part
|
||||
of the guest VM. This is done using the ACPI GED event which eventually gets
|
||||
demultiplexed to a CPU hotplug event and further to specific hot-(un)plug event
|
||||
of a particular vCPU.
|
||||
|
||||
This change adds the ACPI calls to the existing hot-(un)plug hooks to trigger
|
||||
ACPI GED events from QEMU to guest VM.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 33 ++++++++++++++++++++++++++++++---
|
||||
1 file changed, 30 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 0312fa366d..60cd560ab9 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3256,6 +3256,7 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
MachineState *ms = MACHINE(hotplug_dev);
|
||||
CPUState *cs = CPU(dev);
|
||||
+ Error *local_err = NULL;
|
||||
CPUArchId *cpu_slot;
|
||||
|
||||
/* insert the cold/hot-plugged vcpu in the slot */
|
||||
@@ -3268,12 +3269,20 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
* plugged, guest is also notified.
|
||||
*/
|
||||
if (vms->acpi_dev) {
|
||||
- /* TODO: update acpi hotplug state. Send cpu hotplug event to guest */
|
||||
+ HotplugHandlerClass *hhc;
|
||||
+ /* update acpi hotplug state and send cpu hotplug event to guest */
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
|
||||
+ hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
/* TODO: register cpu for reset & update F/W info for the next boot */
|
||||
}
|
||||
|
||||
cs->disabled = false;
|
||||
return;
|
||||
+fail:
|
||||
+ error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
@@ -3281,8 +3290,10 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
+ HotplugHandlerClass *hhc;
|
||||
ARMCPU *cpu = ARM_CPU(dev);
|
||||
CPUState *cs = CPU(dev);
|
||||
+ Error *local_err = NULL;
|
||||
|
||||
if (!vms->acpi_dev || !dev->realized) {
|
||||
error_setg(errp, "GED does not exists or device is not realized!");
|
||||
@@ -3301,9 +3312,16 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
- /* TODO: request cpu hotplug from guest */
|
||||
+ /* request cpu hotplug from guest */
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
|
||||
+ hhc->unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
return;
|
||||
+fail:
|
||||
+ error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
@@ -3311,7 +3329,9 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
MachineState *ms = MACHINE(hotplug_dev);
|
||||
+ HotplugHandlerClass *hhc;
|
||||
CPUState *cs = CPU(dev);
|
||||
+ Error *local_err = NULL;
|
||||
CPUArchId *cpu_slot;
|
||||
|
||||
if (!vms->acpi_dev || !dev->realized) {
|
||||
@@ -3321,7 +3341,12 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
|
||||
cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
|
||||
- /* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
|
||||
+ /* update the acpi cpu hotplug state for cpu hot-unplug */
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
|
||||
+ hhc->unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
unwire_gic_cpu_irqs(vms, cs);
|
||||
virt_update_gic(vms, cs);
|
||||
@@ -3335,6 +3360,8 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
cs->disabled = true;
|
||||
|
||||
return;
|
||||
+fail:
|
||||
+ error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
43
arm-virt-acpi-Build-CPUs-AML-with-CPU-Hotplug-suppor.patch
Normal file
43
arm-virt-acpi-Build-CPUs-AML-with-CPU-Hotplug-suppor.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From bea23b0f82cedbd860b66c7b9e1f6bb0ca85d1cf Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sun, 6 Aug 2023 17:05:30 +0000
|
||||
Subject: [PATCH] arm/virt/acpi: Build CPUs AML with CPU Hotplug support
|
||||
|
||||
Support of vCPU Hotplug requires sequence of ACPI handshakes between Qemu and
|
||||
Guest kernel when a vCPU is plugged or unplugged. Most of the AML code to
|
||||
support these handshakes already exists. This AML need to be build during VM
|
||||
init for ARM architecture as well if the GED support exists.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 084c8abc7c..d88f3cded1 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -937,7 +937,19 @@ 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);
|
||||
+ /* if GED is enabled then cpus AML shall be added as part build_cpus_aml */
|
||||
+ if (vms->acpi_dev) {
|
||||
+ CPUHotplugFeatures opts = {
|
||||
+ .acpi_1_compatible = false,
|
||||
+ .has_legacy_cphp = false
|
||||
+ };
|
||||
+
|
||||
+ build_cpus_aml(scope, ms, opts, NULL, virt_acpi_dsdt_cpu_cppc,
|
||||
+ memmap[VIRT_CPUHP_ACPI].base,
|
||||
+ "\\_SB", NULL, AML_SYSTEM_MEMORY);
|
||||
+ } else {
|
||||
+ acpi_dsdt_add_cpus(scope, vms);
|
||||
+ }
|
||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
||||
if (vmc->acpi_expose_flash) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
76
arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch
Normal file
76
arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From 2d5040ce21af5fc02a8588456be7316fcd5bc2a0 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 2 Apr 2024 16:36:38 +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 to reuse it.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 34 ++++++++++++++++++++--------------
|
||||
1 file changed, 20 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 48fc77fb83..084c8abc7c 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -123,8 +123,23 @@ 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, VirtMachineState *vms,
|
||||
- const MemMapEntry *cppc_memmap)
|
||||
+static void virt_acpi_dsdt_cpu_cppc(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, VirtMachineState *vms)
|
||||
{
|
||||
MachineState *ms = MACHINE(vms);
|
||||
uint16_t i;
|
||||
@@ -134,18 +149,9 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms,
|
||||
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, ms->smp.cpus);
|
||||
- }
|
||||
+ virt_acpi_dsdt_cpu_cppc(i, ms->smp.cpus, dev);
|
||||
|
||||
- aml_append(scope, dev);
|
||||
+ aml_append(scope, dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,7 +937,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, &memmap[VIRT_CPUFREQ]);
|
||||
+ acpi_dsdt_add_cpus(scope, vms);
|
||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
||||
if (vmc->acpi_expose_flash) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
38
arm-virt-acpi-Require-possible_cpu_arch_ids-for-buil.patch
Normal file
38
arm-virt-acpi-Require-possible_cpu_arch_ids-for-buil.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 0bee56446962676992d11e5879f6fbac57e785e8 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 23:38:31 +0800
|
||||
Subject: [PATCH] arm/virt-acpi: Require possible_cpu_arch_ids for
|
||||
build_cpus_aml()
|
||||
|
||||
As the acpi_dev requires possible_cpu_arch_ids to support
|
||||
vcpu hotplug.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 590afcfa98..46642efac4 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -1003,6 +1003,7 @@ static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(vms);
|
||||
Aml *scope, *dsdt;
|
||||
MachineState *ms = MACHINE(vms);
|
||||
const MemMapEntry *memmap = vms->memmap;
|
||||
@@ -1020,7 +1021,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
*/
|
||||
scope = aml_scope("\\_SB");
|
||||
/* if GED is enabled then cpus AML shall be added as part build_cpus_aml */
|
||||
- if (vms->acpi_dev) {
|
||||
+ if (mc->has_hotpluggable_cpus) {
|
||||
CPUHotplugFeatures opts = {
|
||||
.acpi_1_compatible = false,
|
||||
.has_legacy_cphp = false
|
||||
--
|
||||
2.27.0
|
||||
|
||||
225
arm-virt-gicv3-Changes-to-pre-size-GIC-with-possible.patch
Normal file
225
arm-virt-gicv3-Changes-to-pre-size-GIC-with-possible.patch
Normal file
@ -0,0 +1,225 @@
|
||||
From fe61cbaf2dc92b062c8d147b05c3ce213734c24a Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Wed, 6 May 2020 02:20:23 +0100
|
||||
Subject: [PATCH] arm/virt,gicv3: Changes to pre-size GIC with possible vcpus
|
||||
@machine init
|
||||
|
||||
GIC needs to be pre-sized with possible vcpus at the initialization time. This
|
||||
is necessary because Memory regions and resources associated with GICC/GICR
|
||||
etc cannot be changed (add/del/modified) after VM has inited. Also, GIC_TYPER
|
||||
needs to be initialized with mp_affinity and cpu interface number association.
|
||||
This cannot be changed after GIC has initialized.
|
||||
|
||||
Once all the cpu interfaces of the GIC has been inited it needs to be ensured
|
||||
that any updates to the GICC during reset only takes place for the present
|
||||
vcpus and not the disabled ones. Therefore, proper checks are required at
|
||||
various places.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
[changed the comment in arm_gicv3_icc_reset]
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 13 +++++++------
|
||||
hw/intc/arm_gicv3_common.c | 7 +++++--
|
||||
hw/intc/arm_gicv3_cpuif.c | 8 ++++++++
|
||||
hw/intc/arm_gicv3_kvm.c | 34 +++++++++++++++++++++++++++++++---
|
||||
include/hw/arm/virt.h | 2 +-
|
||||
5 files changed, 52 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index f10d75366b..08ba255317 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -802,6 +802,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
const char *gictype;
|
||||
int i;
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
+ unsigned int max_cpus = ms->smp.max_cpus;
|
||||
uint32_t nb_redist_regions = 0;
|
||||
int revision;
|
||||
|
||||
@@ -826,7 +827,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
}
|
||||
vms->gic = qdev_new(gictype);
|
||||
qdev_prop_set_uint32(vms->gic, "revision", revision);
|
||||
- qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
|
||||
+ qdev_prop_set_uint32(vms->gic, "num-cpu", max_cpus);
|
||||
/* Note that the num-irq property counts both internal and external
|
||||
* interrupts; there are always 32 of the former (mandated by GIC spec).
|
||||
*/
|
||||
@@ -838,7 +839,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
if (vms->gic_version != VIRT_GIC_VERSION_2) {
|
||||
QList *redist_region_count;
|
||||
uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
|
||||
- uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
|
||||
+ uint32_t redist0_count = MIN(max_cpus, redist0_capacity);
|
||||
|
||||
nb_redist_regions = virt_gicv3_redist_region_count(vms);
|
||||
|
||||
@@ -915,7 +916,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
} else if (vms->virt) {
|
||||
qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
||||
intidbase + ARCH_GIC_MAINT_IRQ);
|
||||
- sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
|
||||
+ sysbus_connect_irq(gicbusdev, i + 4 * max_cpus, irq);
|
||||
}
|
||||
|
||||
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
||||
@@ -923,11 +924,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
+ VIRTUAL_PMU_IRQ));
|
||||
|
||||
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + smp_cpus,
|
||||
+ sysbus_connect_irq(gicbusdev, i + max_cpus,
|
||||
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
|
||||
+ sysbus_connect_irq(gicbusdev, i + 2 * max_cpus,
|
||||
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
||||
- sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
|
||||
+ sysbus_connect_irq(gicbusdev, i + 3 * max_cpus,
|
||||
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
||||
}
|
||||
|
||||
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
|
||||
index 2ebf880ead..ebd99af610 100644
|
||||
--- a/hw/intc/arm_gicv3_common.c
|
||||
+++ b/hw/intc/arm_gicv3_common.c
|
||||
@@ -392,10 +392,13 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
|
||||
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
- CPUState *cpu = qemu_get_cpu(i);
|
||||
+ CPUState *cpu = qemu_get_possible_cpu(i);
|
||||
uint64_t cpu_affid;
|
||||
|
||||
- s->cpu[i].cpu = cpu;
|
||||
+ if (qemu_enabled_cpu(cpu)) {
|
||||
+ s->cpu[i].cpu = cpu;
|
||||
+ }
|
||||
+
|
||||
s->cpu[i].gic = s;
|
||||
/* Store GICv3CPUState in CPUARMState gicv3state pointer */
|
||||
gicv3_set_gicv3state(cpu, &s->cpu[i]);
|
||||
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
|
||||
index ab1a00508e..0d0eb2f62f 100644
|
||||
--- a/hw/intc/arm_gicv3_cpuif.c
|
||||
+++ b/hw/intc/arm_gicv3_cpuif.c
|
||||
@@ -934,6 +934,10 @@ void gicv3_cpuif_update(GICv3CPUState *cs)
|
||||
ARMCPU *cpu = ARM_CPU(cs->cpu);
|
||||
CPUARMState *env = &cpu->env;
|
||||
|
||||
+ if (!qemu_enabled_cpu(cs->cpu)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq,
|
||||
@@ -1826,6 +1830,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs,
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
GICv3CPUState *ocs = &s->cpu[i];
|
||||
|
||||
+ if (!qemu_enabled_cpu(ocs->cpu)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (irm) {
|
||||
/* IRM == 1 : route to all CPUs except self */
|
||||
if (cs == ocs) {
|
||||
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
|
||||
index 77eb37e131..db06c75e2b 100644
|
||||
--- a/hw/intc/arm_gicv3_kvm.c
|
||||
+++ b/hw/intc/arm_gicv3_kvm.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "hw/intc/arm_gicv3_common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
+#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "kvm_arm.h"
|
||||
@@ -458,6 +459,18 @@ static void kvm_arm_gicv3_put(GICv3State *s)
|
||||
GICv3CPUState *c = &s->cpu[ncpu];
|
||||
int num_pri_bits;
|
||||
|
||||
+ /*
|
||||
+ * To support hotplug of vcpus we need to make sure all gic cpuif/GICC
|
||||
+ * are initialized at machvirt init time. Once the init is done we
|
||||
+ * release the ARMCPU object for disabled vcpus but this leg could hit
|
||||
+ * during reset of GICC later as well i.e. after init has happened and
|
||||
+ * all of the cases we want to make sure we dont acess the GICC for
|
||||
+ * the disabled VCPUs.
|
||||
+ */
|
||||
+ if (!qemu_enabled_cpu(c->cpu)) {
|
||||
+ 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);
|
||||
@@ -616,6 +629,11 @@ static void kvm_arm_gicv3_get(GICv3State *s)
|
||||
GICv3CPUState *c = &s->cpu[ncpu];
|
||||
int num_pri_bits;
|
||||
|
||||
+ /* don't access GICC for the disabled vCPUs. */
|
||||
+ if (!qemu_enabled_cpu(c->cpu)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false);
|
||||
kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
|
||||
&c->icc_ctlr_el1[GICV3_NS], false);
|
||||
@@ -695,10 +713,19 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
return;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * This shall be called even when vcpu is being hotplugged or onlined and
|
||||
+ * other vcpus might be running. Host kernel KVM code to handle device
|
||||
+ * access of IOCTLs KVM_{GET|SET}_DEVICE_ATTR might fail due to inability to
|
||||
+ * grab vcpu locks for all the vcpus. Hence, we need to pause all vcpus to
|
||||
+ * facilitate locking within host.
|
||||
+ */
|
||||
+ pause_all_vcpus();
|
||||
/* 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, c->gicr_typer),
|
||||
&c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
|
||||
+ resume_all_vcpus();
|
||||
|
||||
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
|
||||
}
|
||||
@@ -808,9 +835,10 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
|
||||
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
|
||||
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
|
||||
-
|
||||
- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
|
||||
+ CPUState *cs = qemu_get_cpu(i);
|
||||
+ if (qemu_enabled_cpu(cs)) {
|
||||
+ define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* 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 49d1ec8656..a6977bade5 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -208,7 +208,7 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
|
||||
|
||||
assert(vms->gic_version != VIRT_GIC_VERSION_2);
|
||||
|
||||
- return (MACHINE(vms)->smp.cpus > redist0_capacity &&
|
||||
+ return (MACHINE(vms)->smp.max_cpus > redist0_capacity &&
|
||||
vms->highmem_redists) ? 2 : 1;
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
221
arm-virt-kvm-Pre-create-disabled-possible-vCPUs-mach.patch
Normal file
221
arm-virt-kvm-Pre-create-disabled-possible-vCPUs-mach.patch
Normal file
@ -0,0 +1,221 @@
|
||||
From 2669fd26cbc36e24ebfc844c240b45ad831701cc Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 5 May 2020 18:44:59 +0100
|
||||
Subject: [PATCH] arm/virt,kvm: Pre-create disabled possible vCPUs @machine
|
||||
init
|
||||
|
||||
In ARMv8 architecture, GIC needs all the vCPUs to be created and present when
|
||||
it is initialized. This is because:
|
||||
1. GICC and MPIDR association must be fixed at the VM initialization time.
|
||||
This is represented by register GIC_TYPER(mp_afffinity, proc_num)
|
||||
2. GICC(cpu interfaces), GICR(redistributors) etc all must be initialized
|
||||
at the boot time as well.
|
||||
3. Memory regions associated with GICR etc. cannot be changed(add/del/mod)
|
||||
after VM has inited.
|
||||
|
||||
This patch adds the support to pre-create all such possible vCPUs within the
|
||||
host using the KVM interface as part of the virt machine initialization. These
|
||||
vCPUs could later be attached to QOM/ACPI while they are actually hot plugged
|
||||
and made present.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Reported-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
[VP: Identified CPU stall issue & suggested probable fix]
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 53 +++++++++++++++++++++++++++++++++++++++++--
|
||||
include/hw/core/cpu.h | 1 +
|
||||
target/arm/cpu64.c | 1 +
|
||||
target/arm/kvm.c | 32 ++++++++++++++++++++++++++
|
||||
target/arm/kvm64.c | 9 +++++++-
|
||||
target/arm/kvm_arm.h | 11 +++++++++
|
||||
6 files changed, 104 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 2f04bc7666..f10d75366b 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2389,8 +2389,10 @@ static void machvirt_init(MachineState *machine)
|
||||
assert(possible_cpus->len == max_cpus);
|
||||
for (n = 0; n < possible_cpus->len; n++) {
|
||||
Object *cpuobj;
|
||||
+ CPUState *cs;
|
||||
|
||||
cpuobj = object_new(possible_cpus->cpus[n].type);
|
||||
+ cs = CPU(cpuobj);
|
||||
|
||||
aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
|
||||
object_property_set_int(cpuobj, "socket-id",
|
||||
@@ -2402,8 +2404,55 @@ static void machvirt_init(MachineState *machine)
|
||||
object_property_set_int(cpuobj, "thread-id",
|
||||
virt_get_thread_id(machine, n), NULL);
|
||||
|
||||
- qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
||||
- object_unref(cpuobj);
|
||||
+ if (n < smp_cpus) {
|
||||
+ qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
||||
+ object_unref(cpuobj);
|
||||
+ } else {
|
||||
+ CPUArchId *cpu_slot;
|
||||
+
|
||||
+ /* handling for vcpus which are yet to be hot-plugged */
|
||||
+ cs->cpu_index = n;
|
||||
+ cpu_slot = virt_find_cpu_slot(machine, cs->cpu_index);
|
||||
+
|
||||
+ /*
|
||||
+ * ARM host vCPU features need to be fixed at the boot time. But as
|
||||
+ * per current approach this CPU object will be destroyed during
|
||||
+ * cpu_post_init(). During hotplug of vCPUs these properties are
|
||||
+ * initialized again.
|
||||
+ */
|
||||
+ virt_cpu_set_properties(cpuobj, cpu_slot, &error_fatal);
|
||||
+
|
||||
+ /*
|
||||
+ * For KVM, we shall be pre-creating the now disabled/un-plugged
|
||||
+ * possbile host vcpus and park them till the time they are
|
||||
+ * actually hot plugged. This is required to pre-size the host
|
||||
+ * GICC and GICR with the all possible vcpus for this VM.
|
||||
+ */
|
||||
+ if (kvm_enabled()) {
|
||||
+ kvm_arm_create_host_vcpu(ARM_CPU(cs));
|
||||
+ }
|
||||
+ /*
|
||||
+ * Add disabled vCPU to CPU slot during the init phase of the virt
|
||||
+ * machine
|
||||
+ * 1. We need this ARMCPU object during the GIC init. This object
|
||||
+ * will facilitate in pre-realizing the GIC. Any info like
|
||||
+ * mp-affinity(required to derive gicr_type) etc. could still be
|
||||
+ * fetched while preserving QOM abstraction akin to realized
|
||||
+ * vCPUs.
|
||||
+ * 2. Now, after initialization of the virt machine is complete we
|
||||
+ * could use two approaches to deal with this ARMCPU object:
|
||||
+ * (i) re-use this ARMCPU object during hotplug of this vCPU.
|
||||
+ * OR
|
||||
+ * (ii) defer release this ARMCPU object after gic has been
|
||||
+ * initialized or during pre-plug phase when a vCPU is
|
||||
+ * hotplugged.
|
||||
+ *
|
||||
+ * We will use the (ii) approach and release the ARMCPU objects
|
||||
+ * after GIC and machine has been fully initialized during
|
||||
+ * machine_init_done() phase.
|
||||
+ */
|
||||
+ cpu_slot->cpu = OBJECT(cs);
|
||||
+ }
|
||||
}
|
||||
fdt_add_timer_nodes(vms);
|
||||
fdt_add_cpu_nodes(vms);
|
||||
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
||||
index c30636a936..fdfb952259 100644
|
||||
--- a/include/hw/core/cpu.h
|
||||
+++ b/include/hw/core/cpu.h
|
||||
@@ -528,6 +528,7 @@ struct CPUState {
|
||||
uint32_t kvm_fetch_index;
|
||||
uint64_t dirty_pages;
|
||||
int kvm_vcpu_stats_fd;
|
||||
+ VMChangeStateEntry *vmcse;
|
||||
|
||||
/* Use by accel-block: CPU is executing an ioctl() */
|
||||
QemuLockCnt in_ioctl_lock;
|
||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||
index e226b60b72..5d28838175 100644
|
||||
--- a/target/arm/cpu64.c
|
||||
+++ b/target/arm/cpu64.c
|
||||
@@ -859,6 +859,7 @@ static void aarch64_cpu_initfn(Object *obj)
|
||||
* enabled explicitly
|
||||
*/
|
||||
cs->disabled = true;
|
||||
+ cs->thread_id = 0;
|
||||
}
|
||||
|
||||
static void aarch64_cpu_finalizefn(Object *obj)
|
||||
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
||||
index f59f4f81b2..70cf15b550 100644
|
||||
--- a/target/arm/kvm.c
|
||||
+++ b/target/arm/kvm.c
|
||||
@@ -659,6 +659,38 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
|
||||
write_list_to_cpustate(cpu);
|
||||
}
|
||||
|
||||
+void kvm_arm_create_host_vcpu(ARMCPU *cpu)
|
||||
+{
|
||||
+ CPUState *cs = CPU(cpu);
|
||||
+ unsigned long vcpu_id = cs->cpu_index;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = kvm_create_vcpu(cs);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("Failed to create host vcpu %ld", vcpu_id);
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Initialize the vCPU in the host. This will reset the sys regs
|
||||
+ * for this vCPU and related registers like MPIDR_EL1 etc. also
|
||||
+ * gets programmed during this call to host. These are referred
|
||||
+ * later while setting device attributes of the GICR during GICv3
|
||||
+ * reset
|
||||
+ */
|
||||
+ ret = kvm_arch_init_vcpu(cs);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("Failed to initialize host vcpu %ld", vcpu_id);
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * park the created vCPU. shall be used during kvm_get_vcpu() when
|
||||
+ * threads are created during realization of ARM vCPUs.
|
||||
+ */
|
||||
+ kvm_park_vcpu(cs);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Update KVM's MP_STATE based on what QEMU thinks it is
|
||||
*/
|
||||
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
|
||||
index 3c175c93a7..03ce1e7525 100644
|
||||
--- a/target/arm/kvm64.c
|
||||
+++ b/target/arm/kvm64.c
|
||||
@@ -562,7 +562,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
|
||||
+ /*
|
||||
+ * Install VM change handler only when vCPU thread has been spawned
|
||||
+ * i.e. vCPU is being realized
|
||||
+ */
|
||||
+ if (cs->thread_id) {
|
||||
+ cs->vmcse = qemu_add_vm_change_state_handler(kvm_arm_vm_state_change,
|
||||
+ cs);
|
||||
+ }
|
||||
|
||||
/* Determine init features for this CPU */
|
||||
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
|
||||
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
|
||||
index 051a0da41c..31408499b3 100644
|
||||
--- a/target/arm/kvm_arm.h
|
||||
+++ b/target/arm/kvm_arm.h
|
||||
@@ -163,6 +163,17 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu);
|
||||
*/
|
||||
void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
||||
|
||||
+/**
|
||||
+ * kvm_arm_create_host_vcpu:
|
||||
+ * @cpu: ARMCPU
|
||||
+ *
|
||||
+ * Called at to pre create all possible kvm vCPUs within the the host at the
|
||||
+ * virt machine init time. This will also init this pre-created vCPU and
|
||||
+ * hence result in vCPU reset at host. These pre created and inited vCPUs
|
||||
+ * shall be parked for use when ARM vCPUs are actually realized.
|
||||
+ */
|
||||
+void kvm_arm_create_host_vcpu(ARMCPU *cpu);
|
||||
+
|
||||
/**
|
||||
* kvm_arm_init_serror_injection:
|
||||
* @cs: CPUState
|
||||
--
|
||||
2.27.0
|
||||
|
||||
153
arm-virt-target-arm-Add-new-ARMCPU-socket-cluster-co.patch
Normal file
153
arm-virt-target-arm-Add-new-ARMCPU-socket-cluster-co.patch
Normal file
@ -0,0 +1,153 @@
|
||||
From c8e062285078e688e692214baf97b35246fc2552 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 5 May 2020 23:19:17 +0100
|
||||
Subject: [PATCH] arm/virt,target/arm: Add new ARMCPU
|
||||
{socket,cluster,core,thread}-id property
|
||||
|
||||
This shall be used to store user specified topology{socket,cluster,core,thread}
|
||||
and shall be converted to a unique 'vcpu-id' which is used as slot-index during
|
||||
hot(un)plug of vCPU.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
target/arm/cpu.c | 4 +++
|
||||
target/arm/cpu.h | 4 +++
|
||||
3 files changed, 71 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index f4c3d47f30..94481d45d4 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -227,6 +227,11 @@ static const char *valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
||||
+static int virt_get_socket_id(const MachineState *ms, int cpu_index);
|
||||
+static int virt_get_cluster_id(const MachineState *ms, int cpu_index);
|
||||
+static int virt_get_core_id(const MachineState *ms, int cpu_index);
|
||||
+static int virt_get_thread_id(const MachineState *ms, int cpu_index);
|
||||
+
|
||||
static bool cpu_type_valid(const char *cpu)
|
||||
{
|
||||
int i;
|
||||
@@ -2264,6 +2269,14 @@ static void machvirt_init(MachineState *machine)
|
||||
&error_fatal);
|
||||
|
||||
aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
|
||||
+ object_property_set_int(cpuobj, "socket-id",
|
||||
+ virt_get_socket_id(machine, n), NULL);
|
||||
+ object_property_set_int(cpuobj, "cluster-id",
|
||||
+ virt_get_cluster_id(machine, n), NULL);
|
||||
+ object_property_set_int(cpuobj, "core-id",
|
||||
+ virt_get_core_id(machine, n), NULL);
|
||||
+ object_property_set_int(cpuobj, "thread-id",
|
||||
+ virt_get_thread_id(machine, n), NULL);
|
||||
|
||||
if (!vms->secure) {
|
||||
object_property_set_bool(cpuobj, "has_el3", false, NULL);
|
||||
@@ -2750,10 +2763,59 @@ static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
return socket_id % ms->numa_state->num_nodes;
|
||||
}
|
||||
|
||||
+static int virt_get_socket_id(const MachineState *ms, int cpu_index)
|
||||
+{
|
||||
+ assert(cpu_index >= 0 && cpu_index < ms->possible_cpus->len);
|
||||
+
|
||||
+ return ms->possible_cpus->cpus[cpu_index].props.socket_id;
|
||||
+}
|
||||
+
|
||||
+static int virt_get_cluster_id(const MachineState *ms, int cpu_index)
|
||||
+{
|
||||
+ assert(cpu_index >= 0 && cpu_index < ms->possible_cpus->len);
|
||||
+
|
||||
+ return ms->possible_cpus->cpus[cpu_index].props.cluster_id;
|
||||
+}
|
||||
+
|
||||
+static int virt_get_core_id(const MachineState *ms, int cpu_index)
|
||||
+{
|
||||
+ assert(cpu_index >= 0 && cpu_index < ms->possible_cpus->len);
|
||||
+
|
||||
+ return ms->possible_cpus->cpus[cpu_index].props.core_id;
|
||||
+}
|
||||
+
|
||||
+static int virt_get_thread_id(const MachineState *ms, int cpu_index)
|
||||
+{
|
||||
+ assert(cpu_index >= 0 && cpu_index < ms->possible_cpus->len);
|
||||
+
|
||||
+ return ms->possible_cpus->cpus[cpu_index].props.thread_id;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+virt_get_cpu_id_from_cpu_topo(const MachineState *ms, DeviceState *dev)
|
||||
+{
|
||||
+ int cpu_id, sock_vcpu_num, clus_vcpu_num, core_vcpu_num;
|
||||
+ ARMCPU *cpu = ARM_CPU(dev);
|
||||
+
|
||||
+ /* calculate total logical cpus across socket/cluster/core */
|
||||
+ sock_vcpu_num = cpu->socket_id * (ms->smp.threads * ms->smp.cores *
|
||||
+ ms->smp.clusters);
|
||||
+ clus_vcpu_num = cpu->cluster_id * (ms->smp.threads * ms->smp.cores);
|
||||
+ core_vcpu_num = cpu->core_id * ms->smp.threads;
|
||||
+
|
||||
+ /* get vcpu-id(logical cpu index) for this vcpu from this topology */
|
||||
+ cpu_id = (sock_vcpu_num + clus_vcpu_num + core_vcpu_num) + cpu->thread_id;
|
||||
+
|
||||
+ assert(cpu_id >= 0 && cpu_id < ms->possible_cpus->len);
|
||||
+
|
||||
+ return cpu_id;
|
||||
+}
|
||||
+
|
||||
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
int n;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
+ unsigned int smp_threads = ms->smp.threads;
|
||||
VirtMachineState *vms = VIRT_MACHINE(ms);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(vms);
|
||||
|
||||
@@ -2767,6 +2829,7 @@ 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 = smp_threads;
|
||||
ms->possible_cpus->cpus[n].arch_id =
|
||||
virt_cpu_mp_affinity(vms, n);
|
||||
|
||||
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
||||
index efb22a87f9..cce315c18a 100644
|
||||
--- a/target/arm/cpu.c
|
||||
+++ b/target/arm/cpu.c
|
||||
@@ -2422,6 +2422,10 @@ 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, 0),
|
||||
+ DEFINE_PROP_INT32("cluster-id", ARMCPU, cluster_id, 0),
|
||||
+ DEFINE_PROP_INT32("core-id", ARMCPU, core_id, 0),
|
||||
+ DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, 0),
|
||||
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 a0282e0d28..145d3dbf13 100644
|
||||
--- a/target/arm/cpu.h
|
||||
+++ b/target/arm/cpu.h
|
||||
@@ -1096,6 +1096,10 @@ struct ArchCPU {
|
||||
QLIST_HEAD(, ARMELChangeHook) el_change_hooks;
|
||||
|
||||
int32_t node_id; /* NUMA node this CPU belongs to */
|
||||
+ int32_t socket_id;
|
||||
+ int32_t cluster_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.27.0
|
||||
|
||||
328
arm-virt-target-arm-Machine-init-time-change-common-.patch
Normal file
328
arm-virt-target-arm-Machine-init-time-change-common-.patch
Normal file
@ -0,0 +1,328 @@
|
||||
From 7cd2d7ef7bb7f6c6a97988d86b97922ff700ab06 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Wed, 6 May 2020 00:13:31 +0100
|
||||
Subject: [PATCH] arm/virt,target/arm: Machine init time change common to vCPU
|
||||
{cold|hot}-plug
|
||||
|
||||
Refactor and introduce the common logic required during the initialization of
|
||||
both cold and hot plugged vCPUs. Also initialize the *disabled* state of the
|
||||
vCPUs which shall be used further during init phases of various other components
|
||||
like GIC, PMU, ACPI etc as part of the virt machine initialization.
|
||||
|
||||
KVM vCPUs corresponding to unplugged/yet-to-be-plugged QOM CPUs are kept in
|
||||
powered-off state in the KVM Host and do not run the guest code. Plugged vCPUs
|
||||
are also kept in powered-off state but vCPU threads exist and is kept sleeping.
|
||||
|
||||
TBD:
|
||||
For the cold booted vCPUs, this change also exists in the arm_load_kernel()
|
||||
in boot.c but for the hotplugged CPUs this change should still remain part of
|
||||
the pre-plug phase. We are duplicating the powering-off of the cold booted CPUs.
|
||||
Shall we remove the duplicate change from boot.c?
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Reported-by: Gavin Shan <gavin.shan@redhat.com>
|
||||
[GS: pointed the assertion due to wrong range check]
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 149 ++++++++++++++++++++++++++++++++++++++++-----
|
||||
target/arm/cpu.c | 7 +++
|
||||
target/arm/cpu64.c | 14 +++++
|
||||
3 files changed, 156 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 8f647422d8..2f04bc7666 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -227,6 +227,7 @@ static const char *valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
||||
+static CPUArchId *virt_find_cpu_slot(MachineState *ms, int vcpuid);
|
||||
static int virt_get_socket_id(const MachineState *ms, int cpu_index);
|
||||
static int virt_get_cluster_id(const MachineState *ms, int cpu_index);
|
||||
static int virt_get_core_id(const MachineState *ms, int cpu_index);
|
||||
@@ -2249,6 +2250,14 @@ static void machvirt_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+ finalize_gic_version(vms);
|
||||
+ if (tcg_enabled() || hvf_enabled() || qtest_enabled() ||
|
||||
+ (vms->gic_version < VIRT_GIC_VERSION_3)) {
|
||||
+ machine->smp.max_cpus = smp_cpus;
|
||||
+ mc->has_hotpluggable_cpus = false;
|
||||
+ warn_report("cpu hotplug feature has been disabled");
|
||||
+ }
|
||||
+
|
||||
possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
|
||||
/*
|
||||
@@ -2275,11 +2284,6 @@ static void machvirt_init(MachineState *machine)
|
||||
virt_set_memmap(vms, pa_bits);
|
||||
}
|
||||
|
||||
- /* We can probe only here because during property set
|
||||
- * KVM is not available yet
|
||||
- */
|
||||
- finalize_gic_version(vms);
|
||||
-
|
||||
sysmem = vms->sysmem = get_system_memory();
|
||||
|
||||
if (vms->secure) {
|
||||
@@ -2385,17 +2389,9 @@ static void machvirt_init(MachineState *machine)
|
||||
assert(possible_cpus->len == max_cpus);
|
||||
for (n = 0; n < possible_cpus->len; n++) {
|
||||
Object *cpuobj;
|
||||
- CPUState *cs;
|
||||
-
|
||||
- if (n >= smp_cpus) {
|
||||
- break;
|
||||
- }
|
||||
|
||||
cpuobj = object_new(possible_cpus->cpus[n].type);
|
||||
|
||||
- cs = CPU(cpuobj);
|
||||
- cs->cpu_index = n;
|
||||
-
|
||||
aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
|
||||
object_property_set_int(cpuobj, "socket-id",
|
||||
virt_get_socket_id(machine, n), NULL);
|
||||
@@ -2902,6 +2898,50 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
return ms->possible_cpus;
|
||||
}
|
||||
|
||||
+static CPUArchId *virt_find_cpu_slot(MachineState *ms, int vcpuid)
|
||||
+{
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(ms);
|
||||
+ CPUArchId *found_cpu;
|
||||
+ uint64_t mp_affinity;
|
||||
+
|
||||
+ assert(vcpuid >= 0 && vcpuid < ms->possible_cpus->len);
|
||||
+
|
||||
+ /*
|
||||
+ * RFC: Question:
|
||||
+ * TBD: Should mp-affinity be treated as MPIDR?
|
||||
+ */
|
||||
+ mp_affinity = virt_cpu_mp_affinity(vms, vcpuid);
|
||||
+ found_cpu = &ms->possible_cpus->cpus[vcpuid];
|
||||
+
|
||||
+ assert(found_cpu->arch_id == mp_affinity);
|
||||
+
|
||||
+ /*
|
||||
+ * RFC: Question:
|
||||
+ * Slot-id is the index where vCPU with certain arch-id(=mpidr/ap-affinity)
|
||||
+ * is plugged. For Host KVM, MPIDR for vCPU is derived using vcpu-id.
|
||||
+ * As I understand, MPIDR and vcpu-id are property of vCPU but slot-id is
|
||||
+ * more related to machine? Current code assumes slot-id and vcpu-id are
|
||||
+ * same i.e. meaning of slot is bit vague.
|
||||
+ *
|
||||
+ * Q1: Is there any requirement to clearly represent slot and dissociate it
|
||||
+ * from vcpu-id?
|
||||
+ * Q2: Should we make MPIDR within host KVM user configurable?
|
||||
+ *
|
||||
+ * +----+----+----+----+----+----+----+----+
|
||||
+ * MPIDR ||| Res | Aff2 | Aff1 | Aff0 |
|
||||
+ * +----+----+----+----+----+----+----+----+
|
||||
+ * \ \ \ | |
|
||||
+ * \ 8bit \ 8bit \ |4bit|
|
||||
+ * \<------->\<------->\ |<-->|
|
||||
+ * \ \ \| |
|
||||
+ * +----+----+----+----+----+----+----+----+
|
||||
+ * VCPU-ID | Byte4 | Byte2 | Byte1 | Byte0 |
|
||||
+ * +----+----+----+----+----+----+----+----+
|
||||
+ */
|
||||
+
|
||||
+ return found_cpu;
|
||||
+}
|
||||
+
|
||||
static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -2945,6 +2985,81 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
|
||||
dev, &error_abort);
|
||||
}
|
||||
|
||||
+static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||
+ MachineState *ms = MACHINE(hotplug_dev);
|
||||
+ ARMCPU *cpu = ARM_CPU(dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+ CPUArchId *cpu_slot;
|
||||
+ int32_t min_cpuid = 0;
|
||||
+ int32_t max_cpuid;
|
||||
+
|
||||
+ /* sanity check the cpu */
|
||||
+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
||||
+ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
||||
+ ms->cpu_type);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->thread_id < 0) || (cpu->thread_id >= ms->smp.threads)) {
|
||||
+ error_setg(errp, "Invalid thread-id %u specified, correct range 0:%u",
|
||||
+ cpu->thread_id, ms->smp.threads - 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ max_cpuid = ms->possible_cpus->len - 1;
|
||||
+ if (!dev->hotplugged) {
|
||||
+ min_cpuid = vms->acpi_dev ? ms->smp.cpus : 0;
|
||||
+ max_cpuid = vms->acpi_dev ? max_cpuid : ms->smp.cpus - 1;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->core_id < min_cpuid) || (cpu->core_id > max_cpuid)) {
|
||||
+ error_setg(errp, "Invalid core-id %d specified, correct range %d:%d",
|
||||
+ cpu->core_id, min_cpuid, max_cpuid);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->cluster_id < 0) || (cpu->cluster_id >= ms->smp.clusters)) {
|
||||
+ error_setg(errp, "Invalid cluster-id %u specified, correct range 0:%u",
|
||||
+ cpu->cluster_id, ms->smp.clusters - 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->socket_id < 0) || (cpu->socket_id >= ms->smp.sockets)) {
|
||||
+ error_setg(errp, "Invalid socket-id %u specified, correct range 0:%u",
|
||||
+ cpu->socket_id, ms->smp.sockets - 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ cs->cpu_index = virt_get_cpu_id_from_cpu_topo(ms, dev);
|
||||
+
|
||||
+ cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
+ if (qemu_present_cpu(CPU(cpu_slot->cpu))) {
|
||||
+ error_setg(errp, "cpu(id%d=%d:%d:%d:%d) with arch-id %" PRIu64 " exist",
|
||||
+ cs->cpu_index, cpu->socket_id, cpu->cluster_id, cpu->core_id,
|
||||
+ cpu->thread_id, cpu_slot->arch_id);
|
||||
+ return;
|
||||
+ }
|
||||
+ virt_cpu_set_properties(OBJECT(cs), cpu_slot, errp);
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(hotplug_dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+ CPUArchId *cpu_slot;
|
||||
+
|
||||
+ /* insert the cold/hot-plugged vcpu in the slot */
|
||||
+ cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
|
||||
+ cpu_slot->cpu = OBJECT(dev);
|
||||
+
|
||||
+ cs->disabled = false;
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -2987,6 +3102,8 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
qlist_append_str(reserved_regions, resv_prop_str);
|
||||
qdev_prop_set_array(dev, "reserved-regions", reserved_regions);
|
||||
g_free(resv_prop_str);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ virt_cpu_pre_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3008,6 +3125,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
virt_memory_plug(hotplug_dev, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
|
||||
virtio_md_pci_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ virt_cpu_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||
@@ -3092,7 +3211,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
|
||||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI) ||
|
||||
- object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||
+ object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
|
||||
+ object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
return HOTPLUG_HANDLER(machine);
|
||||
}
|
||||
return NULL;
|
||||
@@ -3169,6 +3289,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
#endif
|
||||
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/target/arm/cpu.c b/target/arm/cpu.c
|
||||
index cce315c18a..18b8a79c8f 100644
|
||||
--- a/target/arm/cpu.c
|
||||
+++ b/target/arm/cpu.c
|
||||
@@ -2477,6 +2477,12 @@ static const struct TCGCPUOps arm_tcg_ops = {
|
||||
};
|
||||
#endif /* CONFIG_TCG */
|
||||
|
||||
+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);
|
||||
@@ -2495,6 +2501,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
||||
cc->class_by_name = arm_cpu_class_by_name;
|
||||
cc->has_work = arm_cpu_has_work;
|
||||
cc->dump_state = arm_cpu_dump_state;
|
||||
+ cc->get_arch_id = arm_cpu_get_arch_id;
|
||||
cc->set_pc = arm_cpu_set_pc;
|
||||
cc->get_pc = arm_cpu_get_pc;
|
||||
cc->gdb_read_register = arm_cpu_gdb_read_register;
|
||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||
index 471014b5a9..e226b60b72 100644
|
||||
--- a/target/arm/cpu64.c
|
||||
+++ b/target/arm/cpu64.c
|
||||
@@ -850,6 +850,17 @@ static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
+static void aarch64_cpu_initfn(Object *obj)
|
||||
+{
|
||||
+ CPUState *cs = CPU(obj);
|
||||
+
|
||||
+ /*
|
||||
+ * we start every ARM64 vcpu as disabled possible vCPU. It needs to be
|
||||
+ * enabled explicitly
|
||||
+ */
|
||||
+ cs->disabled = true;
|
||||
+}
|
||||
+
|
||||
static void aarch64_cpu_finalizefn(Object *obj)
|
||||
{
|
||||
}
|
||||
@@ -862,7 +873,9 @@ static const gchar *aarch64_gdb_arch_name(CPUState *cs)
|
||||
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
+ DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
+ dc->user_creatable = true;
|
||||
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
|
||||
cc->gdb_num_core_regs = 34;
|
||||
@@ -908,6 +921,7 @@ void aarch64_cpu_register(const ARMCPUInfo *info)
|
||||
static const TypeInfo aarch64_cpu_type_info = {
|
||||
.name = TYPE_AARCH64_CPU,
|
||||
.parent = TYPE_ARM_CPU,
|
||||
+ .instance_init = aarch64_cpu_initfn,
|
||||
.instance_finalize = aarch64_cpu_finalizefn,
|
||||
.abstract = true,
|
||||
.class_init = aarch64_cpu_class_init,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
29
arm-virt.c-Convey-local_err-when-set-psci-conduit.patch
Normal file
29
arm-virt.c-Convey-local_err-when-set-psci-conduit.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From 25438f2cdb13d07c1bd228fcf4223c21da368548 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 15:15:31 +0800
|
||||
Subject: [PATCH] arm/virt.c: Convey local_err when set psci-conduit
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index ed437ce0e8..934b0412ef 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2323,7 +2323,10 @@ static void virt_cpu_set_properties(Object *cpuobj, const CPUArchId *cpu_slot,
|
||||
*/
|
||||
if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
|
||||
object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit,
|
||||
- NULL);
|
||||
+ &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* Secondary CPUs start in PSCI powered-down state */
|
||||
if (CPU(cpuobj)->cpu_index > 0) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
615
arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch
Normal file
615
arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch
Normal file
@ -0,0 +1,615 @@
|
||||
From ebe05c34a66969e4cacc4d6c030dfe93ace89cb2 Mon Sep 17 00:00:00 2001
|
||||
From: Ying Fang <fangying1@huawei.com>
|
||||
Date: Tue, 19 Mar 2024 14:35:55 +0800
|
||||
Subject: [PATCH] arm64: Add the cpufreq device to show cpufreq info to guest
|
||||
|
||||
On ARM64 platform, cpu frequency is retrieved via ACPI CPPC.
|
||||
A virtual cpufreq device based on ACPI CPPC is created to
|
||||
present cpu frequency info to the guest.
|
||||
|
||||
The default frequency is set to host cpu nominal frequency,
|
||||
which is obtained from the host CPPC sysfs. Other performance
|
||||
data are set to the same value, since we don't support guest
|
||||
performance scaling here.
|
||||
|
||||
Performance counters are also not emulated and they simply
|
||||
return 1 if read, and guest should fallback to use desired
|
||||
performance value as the current performance.
|
||||
|
||||
Guest kernel version above 4.18 is required to make it work.
|
||||
|
||||
This series is backported from:
|
||||
https://patchwork.kernel.org/cover/11379943/
|
||||
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
configs/devices/aarch64-softmmu/default.mak | 1 +
|
||||
hw/acpi/aml-build.c | 22 ++
|
||||
hw/acpi/cpufreq.c | 283 ++++++++++++++++++++
|
||||
hw/acpi/meson.build | 1 +
|
||||
hw/arm/virt-acpi-build.c | 79 +++++-
|
||||
hw/arm/virt.c | 13 +
|
||||
hw/char/Kconfig | 4 +
|
||||
include/hw/acpi/acpi-defs.h | 40 +++
|
||||
include/hw/acpi/aml-build.h | 3 +
|
||||
include/hw/arm/virt.h | 1 +
|
||||
10 files changed, 444 insertions(+), 3 deletions(-)
|
||||
create mode 100644 hw/acpi/cpufreq.c
|
||||
|
||||
diff --git a/configs/devices/aarch64-softmmu/default.mak b/configs/devices/aarch64-softmmu/default.mak
|
||||
index f82a04c27d..8d66d0f1af 100644
|
||||
--- a/configs/devices/aarch64-softmmu/default.mak
|
||||
+++ b/configs/devices/aarch64-softmmu/default.mak
|
||||
@@ -8,3 +8,4 @@ include ../arm-softmmu/default.mak
|
||||
# CONFIG_XLNX_ZYNQMP_ARM=n
|
||||
# CONFIG_XLNX_VERSAL=n
|
||||
# CONFIG_SBSA_REF=n
|
||||
+# CONFIG_CPUFREQ=n
|
||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
||||
index 2968df5562..714498165a 100644
|
||||
--- a/hw/acpi/aml-build.c
|
||||
+++ b/hw/acpi/aml-build.c
|
||||
@@ -1554,6 +1554,28 @@ Aml *aml_sleep(uint64_t msec)
|
||||
return var;
|
||||
}
|
||||
|
||||
+/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */
|
||||
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
|
||||
+ uint8_t reg_offset, AmlAccessType type, uint64_t addr)
|
||||
+{
|
||||
+ int i;
|
||||
+ Aml *var = aml_alloc();
|
||||
+ build_append_byte(var->buf, 0x82); /* Generic Register Descriptor */
|
||||
+ build_append_byte(var->buf, 0x0C); /* Length, bits[7:0] value = 0x0C */
|
||||
+ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */
|
||||
+ build_append_byte(var->buf, rs); /* Address Space ID */
|
||||
+ build_append_byte(var->buf, reg_width); /* Register Bit Width */
|
||||
+ build_append_byte(var->buf, reg_offset); /* Register Bit Offset */
|
||||
+ build_append_byte(var->buf, type); /* Access Size */
|
||||
+
|
||||
+ /* Register address */
|
||||
+ for (i = 0; i < 8; i++) {
|
||||
+ build_append_byte(var->buf, extract64(addr, i * 8, 8));
|
||||
+ }
|
||||
+
|
||||
+ return var;
|
||||
+}
|
||||
+
|
||||
static uint8_t Hex2Byte(const char *src)
|
||||
{
|
||||
int hi, lo;
|
||||
diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000000..a84db490b3
|
||||
--- /dev/null
|
||||
+++ b/hw/acpi/cpufreq.c
|
||||
@@ -0,0 +1,283 @@
|
||||
+/*
|
||||
+ * ACPI CPPC register device
|
||||
+ *
|
||||
+ * Support for showing CPU frequency in guest OS.
|
||||
+ *
|
||||
+ * Copyright (c) 2019 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/>.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "hw/sysbus.h"
|
||||
+#include "chardev/char.h"
|
||||
+#include "qemu/log.h"
|
||||
+#include "trace.h"
|
||||
+#include "qemu/option.h"
|
||||
+#include "sysemu/sysemu.h"
|
||||
+#include "hw/acpi/acpi-defs.h"
|
||||
+#include "qemu/cutils.h"
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "hw/boards.h"
|
||||
+
|
||||
+#define TYPE_CPUFREQ "cpufreq"
|
||||
+#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ)
|
||||
+#define NOMINAL_FREQ_FILE "/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq"
|
||||
+#define CPU_MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
|
||||
+#define HZ_MAX_LENGTH 1024
|
||||
+#define MAX_SUPPORT_SPACE 0x10000
|
||||
+
|
||||
+/*
|
||||
+ * Since Hi1616 will not support CPPC, we simply use its nominal frequency as
|
||||
+ * the default.
|
||||
+ */
|
||||
+#define DEFAULT_HZ 2400
|
||||
+
|
||||
+int cppc_regs_offset[CPPC_REG_COUNT] = {
|
||||
+ [HIGHEST_PERF] = 0,
|
||||
+ [NOMINAL_PERF] = 4,
|
||||
+ [LOW_NON_LINEAR_PERF] = 8,
|
||||
+ [LOWEST_PERF] = 12,
|
||||
+ [GUARANTEED_PERF] = 16,
|
||||
+ [DESIRED_PERF] = 20,
|
||||
+ [MIN_PERF] = -1,
|
||||
+ [MAX_PERF] = -1,
|
||||
+ [PERF_REDUC_TOLERANCE] = -1,
|
||||
+ [TIME_WINDOW] = -1,
|
||||
+ [CTR_WRAP_TIME] = -1,
|
||||
+ [REFERENCE_CTR] = 24,
|
||||
+ [DELIVERED_CTR] = 32,
|
||||
+ [PERF_LIMITED] = 40,
|
||||
+ [ENABLE] = -1,
|
||||
+ [AUTO_SEL_ENABLE] = -1,
|
||||
+ [AUTO_ACT_WINDOW] = -1,
|
||||
+ [ENERGY_PERF] = -1,
|
||||
+ [REFERENCE_PERF] = -1,
|
||||
+ [LOWEST_FREQ] = 44,
|
||||
+ [NOMINAL_FREQ] = 48,
|
||||
+};
|
||||
+
|
||||
+typedef struct CpuhzState {
|
||||
+ SysBusDevice parent_obj;
|
||||
+
|
||||
+ MemoryRegion iomem;
|
||||
+ uint32_t HighestPerformance;
|
||||
+ uint32_t NominalPerformance;
|
||||
+ uint32_t LowestNonlinearPerformance;
|
||||
+ uint32_t LowestPerformance;
|
||||
+ uint32_t GuaranteedPerformance;
|
||||
+ uint32_t DesiredPerformance;
|
||||
+ uint64_t ReferencePerformanceCounter;
|
||||
+ uint64_t DeliveredPerformanceCounter;
|
||||
+ uint32_t PerformanceLimited;
|
||||
+ uint32_t LowestFreq;
|
||||
+ uint32_t NominalFreq;
|
||||
+ uint32_t reg_size;
|
||||
+} CpuhzState;
|
||||
+
|
||||
+
|
||||
+static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size)
|
||||
+{
|
||||
+ CpuhzState *s = (CpuhzState *)opaque;
|
||||
+ uint64_t r;
|
||||
+ uint64_t n;
|
||||
+
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ unsigned int smp_cpus = ms->smp.cpus;
|
||||
+
|
||||
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
|
||||
+ warn_report("cpufreq_read: offset 0x%lx out of range", offset);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
|
||||
+ switch (n) {
|
||||
+ case 0:
|
||||
+ r = s->HighestPerformance;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ r = s->NominalPerformance;
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ r = s->LowestNonlinearPerformance;
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ r = s->LowestPerformance;
|
||||
+ break;
|
||||
+ case 16:
|
||||
+ r = s->GuaranteedPerformance;
|
||||
+ break;
|
||||
+ case 20:
|
||||
+ r = s->DesiredPerformance;
|
||||
+ break;
|
||||
+ /*
|
||||
+ * We don't have real counters and it is hard to emulate, so always set the
|
||||
+ * counter value to 1 to rely on Linux to use the DesiredPerformance value
|
||||
+ * directly.
|
||||
+ */
|
||||
+ case 24:
|
||||
+ r = s->ReferencePerformanceCounter;
|
||||
+ break;
|
||||
+ /*
|
||||
+ * Guest may still access the register by 32bit; add the process to
|
||||
+ * eliminate unnecessary warnings.
|
||||
+ */
|
||||
+ case 28:
|
||||
+ r = s->ReferencePerformanceCounter >> 32;
|
||||
+ break;
|
||||
+ case 32:
|
||||
+ r = s->DeliveredPerformanceCounter;
|
||||
+ break;
|
||||
+ case 36:
|
||||
+ r = s->DeliveredPerformanceCounter >> 32;
|
||||
+ break;
|
||||
+
|
||||
+ case 40:
|
||||
+ r = s->PerformanceLimited;
|
||||
+ break;
|
||||
+ case 44:
|
||||
+ r = s->LowestFreq;
|
||||
+ break;
|
||||
+ case 48:
|
||||
+ r = s->NominalFreq;
|
||||
+ break;
|
||||
+ default:
|
||||
+ error_printf("cpufreq_read: Bad offset 0x%lx\n", offset);
|
||||
+ r = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static void cpufreq_write(void *opaque, hwaddr offset,
|
||||
+ uint64_t value, unsigned size)
|
||||
+{
|
||||
+ uint64_t n;
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ unsigned int smp_cpus = ms->smp.cpus;
|
||||
+
|
||||
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
|
||||
+ error_printf("cpufreq_write: offset 0x%lx out of range", offset);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
|
||||
+
|
||||
+ switch (n) {
|
||||
+ case 20:
|
||||
+ break;
|
||||
+ default:
|
||||
+ error_printf("cpufreq_write: Bad offset 0x%lx\n", offset);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static uint32_t CPPC_Read(const char *hostpath)
|
||||
+{
|
||||
+ int fd;
|
||||
+ char buffer[HZ_MAX_LENGTH] = { 0 };
|
||||
+ uint64_t hz;
|
||||
+ int len;
|
||||
+ const char *endptr = NULL;
|
||||
+ int ret;
|
||||
+
|
||||
+ fd = qemu_open_old(hostpath, O_RDONLY);
|
||||
+ if (fd < 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ len = read(fd, buffer, HZ_MAX_LENGTH);
|
||||
+ qemu_close(fd);
|
||||
+ if (len <= 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ ret = qemu_strtoul(buffer, &endptr, 0, &hz);
|
||||
+ if (ret < 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return (uint32_t)hz;
|
||||
+}
|
||||
+
|
||||
+static const MemoryRegionOps cpufreq_ops = {
|
||||
+ .read = cpufreq_read,
|
||||
+ .write = cpufreq_write,
|
||||
+ .endianness = DEVICE_NATIVE_ENDIAN,
|
||||
+};
|
||||
+
|
||||
+static void hz_init(CpuhzState *s)
|
||||
+{
|
||||
+ uint32_t hz;
|
||||
+
|
||||
+ hz = CPPC_Read(NOMINAL_FREQ_FILE);
|
||||
+ if (hz == 0) {
|
||||
+ hz = CPPC_Read(CPU_MAX_FREQ_FILE);
|
||||
+ if (hz == 0) {
|
||||
+ hz = DEFAULT_HZ;
|
||||
+ } else {
|
||||
+ /* Value in CpuMaxFrequency is in KHz unit; convert to MHz */
|
||||
+ hz = hz / 1000;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ s->HighestPerformance = hz;
|
||||
+ s->NominalPerformance = hz;
|
||||
+ s->LowestNonlinearPerformance = hz;
|
||||
+ s->LowestPerformance = hz;
|
||||
+ s->GuaranteedPerformance = hz;
|
||||
+ s->DesiredPerformance = hz;
|
||||
+ s->ReferencePerformanceCounter = 1;
|
||||
+ s->DeliveredPerformanceCounter = 1;
|
||||
+ s->PerformanceLimited = 0;
|
||||
+ s->LowestFreq = hz;
|
||||
+ s->NominalFreq = hz;
|
||||
+}
|
||||
+
|
||||
+static void cpufreq_init(Object *obj)
|
||||
+{
|
||||
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
+ CpuhzState *s = CPUFREQ(obj);
|
||||
+
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ unsigned int smp_cpus = ms->smp.cpus;
|
||||
+
|
||||
+ s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE;
|
||||
+ if (s->reg_size > MAX_SUPPORT_SPACE) {
|
||||
+ error_report("Required space 0x%x excesses the max support 0x%x",
|
||||
+ s->reg_size, MAX_SUPPORT_SPACE);
|
||||
+ goto err_end;
|
||||
+ }
|
||||
+
|
||||
+ memory_region_init_io(&s->iomem, OBJECT(s), &cpufreq_ops, s, "cpufreq",
|
||||
+ s->reg_size);
|
||||
+ sysbus_init_mmio(sbd, &s->iomem);
|
||||
+ hz_init(s);
|
||||
+ return;
|
||||
+
|
||||
+err_end:
|
||||
+ /* Set desired perf register offset to -1 to indicate no support for CPPC */
|
||||
+ cppc_regs_offset[DESIRED_PERF] = -1;
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo cpufreq_arm_info = {
|
||||
+ .name = TYPE_CPUFREQ,
|
||||
+ .parent = TYPE_SYS_BUS_DEVICE,
|
||||
+ .instance_size = sizeof(CpuhzState),
|
||||
+ .instance_init = cpufreq_init,
|
||||
+};
|
||||
+
|
||||
+static void cpufreq_register_types(void)
|
||||
+{
|
||||
+ type_register_static(&cpufreq_arm_info);
|
||||
+}
|
||||
+
|
||||
+type_init(cpufreq_register_types)
|
||||
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
|
||||
index fc1b952379..d36b10ea3c 100644
|
||||
--- a/hw/acpi/meson.build
|
||||
+++ b/hw/acpi/meson.build
|
||||
@@ -27,6 +27,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c'))
|
||||
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
|
||||
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
|
||||
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
|
||||
+acpi_ss.add(when: 'CONFIG_CPUFREQ', if_true: files('cpufreq.c'))
|
||||
if have_tpm
|
||||
acpi_ss.add(files('tpm.c'))
|
||||
endif
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 8bc35a483c..3cb50bdc65 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -63,7 +63,68 @@
|
||||
|
||||
#define ACPI_BUILD_TABLE_SIZE 0x20000
|
||||
|
||||
-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms)
|
||||
+static void acpi_dsdt_add_psd(Aml *dev, int cpus)
|
||||
+{
|
||||
+ Aml *pkg;
|
||||
+ Aml *sub;
|
||||
+
|
||||
+ sub = aml_package(5);
|
||||
+ aml_append(sub, aml_int(5));
|
||||
+ aml_append(sub, aml_int(0));
|
||||
+ /* Assume all vCPUs belong to the same domain */
|
||||
+ aml_append(sub, aml_int(0));
|
||||
+ /* SW_ANY: OSPM coordinate, initiate on any processor */
|
||||
+ aml_append(sub, aml_int(0xFD));
|
||||
+ aml_append(sub, aml_int(cpus));
|
||||
+
|
||||
+ pkg = aml_package(1);
|
||||
+ aml_append(pkg, sub);
|
||||
+
|
||||
+ aml_append(dev, aml_name_decl("_PSD", pkg));
|
||||
+}
|
||||
+
|
||||
+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset)
|
||||
+{
|
||||
+ Aml *cpc;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Use version 3 of CPPC table from ACPI 6.3 */
|
||||
+ cpc = aml_package(23);
|
||||
+ aml_append(cpc, aml_int(23));
|
||||
+ aml_append(cpc, aml_int(3));
|
||||
+
|
||||
+ for (i = 0; i < CPPC_REG_COUNT; i++) {
|
||||
+ Aml *res;
|
||||
+ uint8_t reg_width;
|
||||
+ uint8_t acc_type;
|
||||
+ uint64_t addr;
|
||||
+
|
||||
+ if (regs_offset[i] == -1) {
|
||||
+ reg_width = 0;
|
||||
+ acc_type = AML_ANY_ACC;
|
||||
+ addr = 0;
|
||||
+ } else {
|
||||
+ addr = cpu_base + regs_offset[i];
|
||||
+ if (i == REFERENCE_CTR || i == DELIVERED_CTR) {
|
||||
+ reg_width = 64;
|
||||
+ acc_type = AML_QWORD_ACC;
|
||||
+ } else {
|
||||
+ reg_width = 32;
|
||||
+ acc_type = AML_DWORD_ACC;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ res = aml_resource_template();
|
||||
+ aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0,
|
||||
+ acc_type, addr));
|
||||
+ aml_append(cpc, res);
|
||||
+ }
|
||||
+
|
||||
+ aml_append(dev, aml_name_decl("_CPC", cpc));
|
||||
+}
|
||||
+
|
||||
+static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms,
|
||||
+ const MemMapEntry *cppc_memmap)
|
||||
{
|
||||
MachineState *ms = MACHINE(vms);
|
||||
uint16_t i;
|
||||
@@ -72,7 +133,19 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms)
|
||||
Aml *dev = aml_device("C%.03X", i);
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
|
||||
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
|
||||
- aml_append(scope, dev);
|
||||
+
|
||||
+ /*
|
||||
+ * 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, ms->smp.cpus);
|
||||
+ }
|
||||
+
|
||||
+ aml_append(scope, dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,7 +931,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);
|
||||
+ acpi_dsdt_add_cpus(scope, vms, &memmap[VIRT_CPUFREQ]);
|
||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
||||
if (vmc->acpi_expose_flash) {
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index b82bd1b8c8..c19cacec8b 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -157,6 +157,7 @@ static const MemMapEntry base_memmap[] = {
|
||||
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
|
||||
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
+ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
|
||||
[VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 },
|
||||
@@ -980,6 +981,16 @@ static void create_uart(const VirtMachineState *vms, int uart,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem)
|
||||
+{
|
||||
+ hwaddr base = vms->memmap[VIRT_CPUFREQ].base;
|
||||
+ DeviceState *dev = qdev_new("cpufreq");
|
||||
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||
+
|
||||
+ sysbus_realize_and_unref(s, &error_fatal);
|
||||
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
|
||||
+}
|
||||
+
|
||||
static void create_rtc(const VirtMachineState *vms)
|
||||
{
|
||||
char *nodename;
|
||||
@@ -2346,6 +2357,8 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
|
||||
|
||||
+ create_cpufreq(vms, sysmem);
|
||||
+
|
||||
if (vms->secure) {
|
||||
create_secure_ram(vms, secure_sysmem, secure_tag_sysmem);
|
||||
create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
|
||||
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
|
||||
index 6b6cf2fc1d..335a60c2c1 100644
|
||||
--- a/hw/char/Kconfig
|
||||
+++ b/hw/char/Kconfig
|
||||
@@ -71,3 +71,7 @@ config GOLDFISH_TTY
|
||||
|
||||
config SHAKTI_UART
|
||||
bool
|
||||
+
|
||||
+config CPUFREQ
|
||||
+ bool
|
||||
+ default y
|
||||
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
|
||||
index 2b42e4192b..b1f389fb4b 100644
|
||||
--- a/include/hw/acpi/acpi-defs.h
|
||||
+++ b/include/hw/acpi/acpi-defs.h
|
||||
@@ -93,4 +93,44 @@ typedef struct AcpiFadtData {
|
||||
#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
|
||||
#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
|
||||
|
||||
+/*
|
||||
+ * CPPC register definition from kernel header
|
||||
+ * include/acpi/cppc_acpi.h
|
||||
+ * The last element is newly added for easy use
|
||||
+ */
|
||||
+enum cppc_regs {
|
||||
+ HIGHEST_PERF,
|
||||
+ NOMINAL_PERF,
|
||||
+ LOW_NON_LINEAR_PERF,
|
||||
+ LOWEST_PERF,
|
||||
+ GUARANTEED_PERF,
|
||||
+ DESIRED_PERF,
|
||||
+ MIN_PERF,
|
||||
+ MAX_PERF,
|
||||
+ PERF_REDUC_TOLERANCE,
|
||||
+ TIME_WINDOW,
|
||||
+ CTR_WRAP_TIME,
|
||||
+ REFERENCE_CTR,
|
||||
+ DELIVERED_CTR,
|
||||
+ PERF_LIMITED,
|
||||
+ ENABLE,
|
||||
+ AUTO_SEL_ENABLE,
|
||||
+ AUTO_ACT_WINDOW,
|
||||
+ ENERGY_PERF,
|
||||
+ REFERENCE_PERF,
|
||||
+ LOWEST_FREQ,
|
||||
+ NOMINAL_FREQ,
|
||||
+ CPPC_REG_COUNT,
|
||||
+};
|
||||
+
|
||||
+#define CPPC_REG_PER_CPU_STRIDE 0x40
|
||||
+
|
||||
+/*
|
||||
+ * Offset for each CPPC register; -1 for unavailable
|
||||
+ *
|
||||
+ * Offset for each CPPC register; -1 for unavailable
|
||||
+ * The whole register space is unavailable if desired perf offset is -1.
|
||||
+ */
|
||||
+extern int cppc_regs_offset[CPPC_REG_COUNT];
|
||||
+
|
||||
#endif
|
||||
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
||||
index 84ded2ecd3..200cb113de 100644
|
||||
--- a/include/hw/acpi/aml-build.h
|
||||
+++ b/include/hw/acpi/aml-build.h
|
||||
@@ -429,6 +429,9 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
|
||||
uint8_t channel);
|
||||
Aml *aml_sleep(uint64_t msec);
|
||||
Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
|
||||
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
|
||||
+ uint8_t reg_offset, AmlAccessType type,
|
||||
+ uint64_t addr);
|
||||
|
||||
/* Block AML object primitives */
|
||||
Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index f69239850e..e944d434c4 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -60,6 +60,7 @@ enum {
|
||||
VIRT_GIC_REDIST,
|
||||
VIRT_SMMU,
|
||||
VIRT_UART,
|
||||
+ VIRT_CPUFREQ,
|
||||
VIRT_MMIO,
|
||||
VIRT_RTC,
|
||||
VIRT_FW_CFG,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
101
backup-memory-bakcup-hugepages-hugepages-files-maybe.patch
Normal file
101
backup-memory-bakcup-hugepages-hugepages-files-maybe.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From c28455a0bac4bbf171d1f19e162557377a85e96c Mon Sep 17 00:00:00 2001
|
||||
From: Ming Yang <yangming73@huawei.com>
|
||||
Date: Sat, 23 Mar 2024 16:32:46 +0800
|
||||
Subject: [PATCH] [backup] memory: bakcup hugepages: hugepages files maybe
|
||||
leftover
|
||||
|
||||
old info:
|
||||
commit id:
|
||||
3cb1b0ce091998532a30793e3272925da4e6f3aa
|
||||
old messages:
|
||||
hugepages: hugepages files maybe leftover
|
||||
|
||||
Before qemu uses the hugepage memory directory /dev/hugepages/libvirt/qemu/xxx,
|
||||
The directory may be deleted because of the destroy virtual machine.
|
||||
Cause qemu to create files directly under /dev/hugepages/libvirt/qemu/.
|
||||
After the file is created, the file is not cleaned up by unlink,
|
||||
and when the virtual machine is destroyed, libvirt will only clean up
|
||||
/dev/hugepages/libvirt/qemu/xxx directory. After creating the hugepage file,
|
||||
execute unlink to clean up the file to fix the problem.
|
||||
|
||||
Signed-off-by: Jinhua Cao <caojinhua1@huawei.com>
|
||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
||||
|
||||
Signed-off-by: Ming Yang <yangming73@huawei.com>
|
||||
---
|
||||
include/qemu/mmap-alloc.h | 4 ++++
|
||||
system/physmem.c | 9 ++++++++-
|
||||
util/mmap-alloc.c | 22 ++++++++++++++++++++++
|
||||
3 files changed, 34 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h
|
||||
index 8344daaa03..63e4edfd2f 100644
|
||||
--- a/include/qemu/mmap-alloc.h
|
||||
+++ b/include/qemu/mmap-alloc.h
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef QEMU_MMAP_ALLOC_H
|
||||
#define QEMU_MMAP_ALLOC_H
|
||||
|
||||
+#define HUGETLBFS_MAGIC 0x958458f6
|
||||
+
|
||||
+size_t qemu_fd_getfiletype(int fd);
|
||||
+
|
||||
typedef enum {
|
||||
QEMU_FS_TYPE_UNKNOWN = 0,
|
||||
QEMU_FS_TYPE_TMPFS,
|
||||
diff --git a/system/physmem.c b/system/physmem.c
|
||||
index a63853a7bc..f14d64819b 100644
|
||||
--- a/system/physmem.c
|
||||
+++ b/system/physmem.c
|
||||
@@ -1329,7 +1329,14 @@ static int file_ram_open(const char *path,
|
||||
/* @path names a file that doesn't exist, create it */
|
||||
fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
|
||||
if (fd >= 0) {
|
||||
- *created = true;
|
||||
+ info_report("open %s success \n", path);
|
||||
+ /* if fd file type is HUGETLBFS_MAGIC, unlink it, */
|
||||
+ /* in case to prevent residue after qemu killed */
|
||||
+ if (qemu_fd_getfiletype(fd) == HUGETLBFS_MAGIC) {
|
||||
+ unlink(path);
|
||||
+ } else {
|
||||
+ *created = true;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
} else if (errno == EISDIR) {
|
||||
diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
|
||||
index ed14f9c64d..6890ad676c 100644
|
||||
--- a/util/mmap-alloc.c
|
||||
+++ b/util/mmap-alloc.c
|
||||
@@ -30,6 +30,28 @@
|
||||
#include <linux/magic.h>
|
||||
#endif
|
||||
|
||||
+size_t qemu_fd_getfiletype(int fd)
|
||||
+{
|
||||
+ struct statfs fs;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (fd != -1) {
|
||||
+ do {
|
||||
+ ret = fstatfs(fd, &fs);
|
||||
+ } while (ret != 0 && errno == EINTR);
|
||||
+
|
||||
+ if (ret != 0) {
|
||||
+ fprintf(stderr, "Couldn't fstatfs() fd: %s\n",
|
||||
+ strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return fs.f_type;
|
||||
+ } else {
|
||||
+ fprintf(stderr, "fd is invalid \n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
QemuFsType qemu_fd_getfs(int fd)
|
||||
{
|
||||
#ifdef CONFIG_LINUX
|
||||
--
|
||||
2.27.0
|
||||
|
||||
47
block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch
Normal file
47
block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From f9aef3909d23af6a33c604f59dccfcb764090f01 Mon Sep 17 00:00:00 2001
|
||||
From: WangJian <wangjian161@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 11:29:15 +0800
|
||||
Subject: [PATCH] block: disallow block jobs when there is a BDRV_O_INACTIVE
|
||||
flag
|
||||
|
||||
Currently, migration will put a BDRV_O_INACTIVE flag
|
||||
on bs's open_flags until another resume being called. In that case,
|
||||
any IO from vm or block jobs will cause a qemu crash with an assert
|
||||
'assert(!(bs->open_flags & BDRV_O_INACTIVE))' failure in bdrv_co_pwritev
|
||||
function. we hereby disallow block jobs by faking a blocker.
|
||||
|
||||
Signed-off-by: wangjian161 <wangjian161@huawei.com>
|
||||
---
|
||||
block.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index bfb0861ec6..b7cb963929 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -7298,6 +7298,22 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
|
||||
bdrv_get_device_or_node_name(bs));
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * When migration puts a BDRV_O_INACTIVE flag on driver's open_flags,
|
||||
+ * we fake a blocker that doesn't exist. From now on, block jobs
|
||||
+ * will not be permitted.
|
||||
+ */
|
||||
+ if ((op == BLOCK_OP_TYPE_RESIZE || op == BLOCK_OP_TYPE_COMMIT_SOURCE ||
|
||||
+ op == BLOCK_OP_TYPE_MIRROR_SOURCE || op == BLOCK_OP_TYPE_MIRROR_TARGET) &&
|
||||
+ (bs->open_flags & BDRV_O_INACTIVE)) {
|
||||
+ if (errp) {
|
||||
+ error_setg(errp, "block device is in use by migration with"
|
||||
+ " a driver BDRV_O_INACTIVE flag setted");
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
return false;
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
32
bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch
Normal file
32
bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 48a328ee1a5a71b7048e4591310471c759fc5af6 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Mon, 27 Jul 2020 20:39:07 +0800
|
||||
Subject: [PATCH] bugfix: irq: Avoid covering object refcount of qemu_irq
|
||||
|
||||
Avoid covering object refcount of qemu_irq, otherwise it may causes
|
||||
memory leak.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
hw/core/irq.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/core/irq.c b/hw/core/irq.c
|
||||
index 3f14e2dda7..df9b5dac9b 100644
|
||||
--- a/hw/core/irq.c
|
||||
+++ b/hw/core/irq.c
|
||||
@@ -110,7 +110,10 @@ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
|
||||
int i;
|
||||
qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
- *old_irqs[i] = *gpio_in[i];
|
||||
+ old_irqs[i]->handler = gpio_in[i]->handler;
|
||||
+ old_irqs[i]->opaque = gpio_in[i]->opaque;
|
||||
+ old_irqs[i]->n = gpio_in[i]->n;
|
||||
+
|
||||
gpio_in[i]->handler = handler;
|
||||
gpio_in[i]->opaque = &old_irqs[i];
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
116
coro-support-live-patch-for-libcare.patch
Normal file
116
coro-support-live-patch-for-libcare.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From c2b377814e7874811d7eb98462d5153e966281cf Mon Sep 17 00:00:00 2001
|
||||
From: Fei Xu <xufei30@huawei.com>
|
||||
Date: Wed, 3 Apr 2024 18:05:25 +0800
|
||||
Subject: [PATCH] coro: support live patch for libcare
|
||||
|
||||
Signed-off-by: Dawei Jiang <jiangdawei15@huawei.com>
|
||||
---
|
||||
include/qemu/coroutine_int.h | 3 ++-
|
||||
util/coroutine-ucontext.c | 52 ++++++++++++++++++++++++++++++++++++
|
||||
util/qemu-coroutine.c | 4 +++
|
||||
3 files changed, 58 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
|
||||
index 1da148552f..11b550a0fc 100644
|
||||
--- a/include/qemu/coroutine_int.h
|
||||
+++ b/include/qemu/coroutine_int.h
|
||||
@@ -73,5 +73,6 @@ Coroutine *qemu_coroutine_new(void);
|
||||
void qemu_coroutine_delete(Coroutine *co);
|
||||
CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to,
|
||||
CoroutineAction action);
|
||||
-
|
||||
+void qemu_coroutine_info_add(const Coroutine *co_);
|
||||
+void qemu_coroutine_info_delete(const Coroutine *co_);
|
||||
#endif
|
||||
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
|
||||
index 7b304c79d9..650c21846d 100644
|
||||
--- a/util/coroutine-ucontext.c
|
||||
+++ b/util/coroutine-ucontext.c
|
||||
@@ -80,6 +80,19 @@ union cc_arg {
|
||||
int i[2];
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * coroutines list for libcare
|
||||
+ */
|
||||
+struct CoroutineInformation {
|
||||
+ sigjmp_buf *env;
|
||||
+ QLIST_ENTRY(CoroutineInformation) next;
|
||||
+};
|
||||
+
|
||||
+static QemuMutex coro_mtx;
|
||||
+QLIST_HEAD(, CoroutineInformation) coro_info_list = QLIST_HEAD_INITIALIZER(pool);
|
||||
+int coro_env_offset = offsetof(struct CoroutineInformation, env);
|
||||
+int coro_next_offset = offsetof(struct CoroutineInformation, next);
|
||||
+
|
||||
/*
|
||||
* QEMU_ALWAYS_INLINE only does so if __OPTIMIZE__, so we cannot use it.
|
||||
* always_inline is required to avoid TSan runtime fatal errors.
|
||||
@@ -340,3 +353,42 @@ bool qemu_in_coroutine(void)
|
||||
|
||||
return self && self->caller;
|
||||
}
|
||||
+
|
||||
+static void __attribute__((constructor)) coro_mutex_init(void)
|
||||
+{
|
||||
+ qemu_mutex_init(&coro_mtx);
|
||||
+}
|
||||
+
|
||||
+void qemu_coroutine_info_add(const Coroutine *co_)
|
||||
+{
|
||||
+ CoroutineUContext *co;
|
||||
+ struct CoroutineInformation *coro_info;
|
||||
+
|
||||
+ /* save coroutine env to coro_info_list */
|
||||
+ co = DO_UPCAST(CoroutineUContext, base, co_);
|
||||
+ coro_info = g_malloc0(sizeof(struct CoroutineInformation));
|
||||
+ coro_info->env = &co->env;
|
||||
+
|
||||
+ qemu_mutex_lock(&coro_mtx);
|
||||
+ QLIST_INSERT_HEAD(&coro_info_list, coro_info, next);
|
||||
+ qemu_mutex_unlock(&coro_mtx);
|
||||
+}
|
||||
+
|
||||
+void qemu_coroutine_info_delete(const Coroutine *co_)
|
||||
+{
|
||||
+ CoroutineUContext *co;
|
||||
+ struct CoroutineInformation *coro_info;
|
||||
+
|
||||
+ /* Remove relative coroutine env info from coro_info_list */
|
||||
+ co = DO_UPCAST(CoroutineUContext, base, co_);
|
||||
+
|
||||
+ qemu_mutex_lock(&coro_mtx);
|
||||
+ QLIST_FOREACH(coro_info, &coro_info_list, next) {
|
||||
+ if (coro_info->env == &co->env) {
|
||||
+ QLIST_REMOVE(coro_info, next);
|
||||
+ g_free(coro_info);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ qemu_mutex_unlock(&coro_mtx);
|
||||
+}
|
||||
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
|
||||
index 5fd2dbaf8b..f550214484 100644
|
||||
--- a/util/qemu-coroutine.c
|
||||
+++ b/util/qemu-coroutine.c
|
||||
@@ -89,6 +89,8 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque)
|
||||
co = qemu_coroutine_new();
|
||||
}
|
||||
|
||||
+ qemu_coroutine_info_add(co);
|
||||
+
|
||||
co->entry = entry;
|
||||
co->entry_arg = opaque;
|
||||
QSIMPLEQ_INIT(&co->co_queue_wakeup);
|
||||
@@ -99,6 +101,8 @@ static void coroutine_delete(Coroutine *co)
|
||||
{
|
||||
co->caller = NULL;
|
||||
|
||||
+ qemu_coroutine_info_delete(co);
|
||||
+
|
||||
if (IS_ENABLED(CONFIG_COROUTINE_POOL)) {
|
||||
if (release_pool_size < qatomic_read(&pool_max_size) * 2) {
|
||||
QSLIST_INSERT_HEAD_ATOMIC(&release_pool, co, pool_next);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
60
cpu-add-Cortex-A72-processor-kvm-target-support.patch
Normal file
60
cpu-add-Cortex-A72-processor-kvm-target-support.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From 5853333c9513caea541701c95a4ac691bb97452f Mon Sep 17 00:00:00 2001
|
||||
From: Xu Yandong <xuyandong2@huawei.com>
|
||||
Date: Tue, 19 Mar 2024 10:45:56 +0800
|
||||
Subject: [PATCH] cpu: add Cortex-A72 processor kvm target support
|
||||
|
||||
The ARM Cortex-A72 is ARMv8-A micro-architecture,
|
||||
add kvm target to ARM Cortex-A72 processor definition.
|
||||
|
||||
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
|
||||
Signed-off-by: Mingwang Li <limingwang@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
target/arm/cpu64.c | 2 +-
|
||||
target/arm/kvm-consts.h | 3 +++
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||
index 922eac3b61..471014b5a9 100644
|
||||
--- a/target/arm/cpu64.c
|
||||
+++ b/target/arm/cpu64.c
|
||||
@@ -710,6 +710,7 @@ static void aarch64_a72_initfn(Object *obj)
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
|
||||
cpu->dtb_compatible = "arm,cortex-a72";
|
||||
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_GENERIC_V8;
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
@@ -773,7 +774,6 @@ static void aarch64_kunpeng_920_initfn(Object *obj)
|
||||
cpu->isar.id_aa64dfr0 = 0x110305408;
|
||||
cpu->isar.id_aa64isar0 = 0x10211120;
|
||||
cpu->isar.id_aa64mmfr0 = 0x101125;
|
||||
- cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8;
|
||||
}
|
||||
|
||||
static void aarch64_host_initfn(Object *obj)
|
||||
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
|
||||
index 7c6adc14f6..c034823170 100644
|
||||
--- a/target/arm/kvm-consts.h
|
||||
+++ b/target/arm/kvm-consts.h
|
||||
@@ -133,6 +133,8 @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
|
||||
#define QEMU_KVM_ARM_TARGET_CORTEX_A57 2
|
||||
#define QEMU_KVM_ARM_TARGET_XGENE_POTENZA 3
|
||||
#define QEMU_KVM_ARM_TARGET_CORTEX_A53 4
|
||||
+/* Generic ARM v8 target */
|
||||
+#define QEMU_KVM_ARM_TARGET_GENERIC_V8 5
|
||||
|
||||
/* There's no kernel define for this: sentinel value which
|
||||
* matches no KVM target value for either 64 or 32 bit
|
||||
@@ -144,6 +146,7 @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
|
||||
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
|
||||
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
|
||||
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
|
||||
+MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_GENERIC_V8, KVM_ARM_TARGET_GENERIC_V8);
|
||||
|
||||
#define CP_REG_ARM64 0x6000000000000000ULL
|
||||
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
|
||||
--
|
||||
2.27.0
|
||||
|
||||
120
cpu-add-Kunpeng-920-cpu-support.patch
Normal file
120
cpu-add-Kunpeng-920-cpu-support.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From e4ae54316651bf6af12de263da158c5ec4ed0401 Mon Sep 17 00:00:00 2001
|
||||
From: Xu Yandong <xuyandong2@huawei.com>
|
||||
Date: Mon, 18 Mar 2024 17:31:31 +0800
|
||||
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: Mingwang Li <limingwang@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 1 +
|
||||
target/arm/cpu64.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 73 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index be2856c018..500a15aa5b 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -220,6 +220,7 @@ static const char *valid_cpus[] = {
|
||||
#endif
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
+ ARM_CPU_TYPE_NAME("Kunpeng-920"),
|
||||
ARM_CPU_TYPE_NAME("host"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||
index 1e9c6c85ae..922eac3b61 100644
|
||||
--- a/target/arm/cpu64.c
|
||||
+++ b/target/arm/cpu64.c
|
||||
@@ -705,6 +705,77 @@ static void aarch64_a53_initfn(Object *obj)
|
||||
define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
}
|
||||
|
||||
+static void aarch64_a72_initfn(Object *obj)
|
||||
+{
|
||||
+ ARMCPU *cpu = ARM_CPU(obj);
|
||||
+
|
||||
+ cpu->dtb_compatible = "arm,cortex-a72";
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
+ cpu->midr = 0x410fd083;
|
||||
+ cpu->revidr = 0x00000000;
|
||||
+ cpu->reset_fpsid = 0x41034080;
|
||||
+ cpu->isar.mvfr0 = 0x10110222;
|
||||
+ cpu->isar.mvfr1 = 0x12111111;
|
||||
+ cpu->isar.mvfr2 = 0x00000043;
|
||||
+ cpu->ctr = 0x8444c004;
|
||||
+ cpu->reset_sctlr = 0x00c50838;
|
||||
+ cpu->isar.id_pfr0 = 0x00000131;
|
||||
+ cpu->isar.id_pfr1 = 0x00011011;
|
||||
+ cpu->isar.id_dfr0 = 0x03010066;
|
||||
+ cpu->id_afr0 = 0x00000000;
|
||||
+ cpu->isar.id_mmfr0 = 0x10201105;
|
||||
+ cpu->isar.id_mmfr1 = 0x40000000;
|
||||
+ cpu->isar.id_mmfr2 = 0x01260000;
|
||||
+ cpu->isar.id_mmfr3 = 0x02102211;
|
||||
+ cpu->isar.id_isar0 = 0x02101110;
|
||||
+ cpu->isar.id_isar1 = 0x13112111;
|
||||
+ cpu->isar.id_isar2 = 0x21232042;
|
||||
+ cpu->isar.id_isar3 = 0x01112131;
|
||||
+ cpu->isar.id_isar4 = 0x00011142;
|
||||
+ cpu->isar.id_isar5 = 0x00011121;
|
||||
+ cpu->isar.id_aa64pfr0 = 0x00002222;
|
||||
+ cpu->isar.id_aa64dfr0 = 0x10305106;
|
||||
+ cpu->isar.id_aa64isar0 = 0x00011120;
|
||||
+ cpu->isar.id_aa64mmfr0 = 0x00001124;
|
||||
+ cpu->isar.dbgdidr = 0x3516d000;
|
||||
+ cpu->clidr = 0x0a200023;
|
||||
+ cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
|
||||
+ cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
|
||||
+ cpu->ccsidr[2] = 0x707fe07a; /* 1MB L2 cache */
|
||||
+ cpu->dcz_blocksize = 4; /* 64 bytes */
|
||||
+ cpu->gic_num_lrs = 4;
|
||||
+ cpu->gic_vpribits = 5;
|
||||
+ cpu->gic_vprebits = 5;
|
||||
+ define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
+}
|
||||
+
|
||||
+static void aarch64_kunpeng_920_initfn(Object *obj)
|
||||
+{
|
||||
+ ARMCPU *cpu = ARM_CPU(obj);
|
||||
+
|
||||
+ /*
|
||||
+ * Hisilicon Kunpeng-920 CPU is similar to cortex-a72,
|
||||
+ * so first initialize cpu data as cortex-a72,
|
||||
+ * and then update the special register.
|
||||
+ */
|
||||
+ aarch64_a72_initfn(obj);
|
||||
+
|
||||
+ cpu->midr = 0x480fd010;
|
||||
+ cpu->ctr = 0x84448004;
|
||||
+ cpu->isar.id_aa64pfr0 = 0x11001111;
|
||||
+ cpu->isar.id_aa64dfr0 = 0x110305408;
|
||||
+ cpu->isar.id_aa64isar0 = 0x10211120;
|
||||
+ cpu->isar.id_aa64mmfr0 = 0x101125;
|
||||
+ cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8;
|
||||
+}
|
||||
+
|
||||
static void aarch64_host_initfn(Object *obj)
|
||||
{
|
||||
#if defined(CONFIG_KVM)
|
||||
@@ -744,6 +815,7 @@ static void aarch64_max_initfn(Object *obj)
|
||||
static const ARMCPUInfo aarch64_cpus[] = {
|
||||
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
|
||||
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
|
||||
+ { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn},
|
||||
{ .name = "max", .initfn = aarch64_max_initfn },
|
||||
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
|
||||
{ .name = "host", .initfn = aarch64_host_initfn },
|
||||
--
|
||||
2.27.0
|
||||
|
||||
25
cpu-features-fix-bug-for-memory-leakage.patch
Normal file
25
cpu-features-fix-bug-for-memory-leakage.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 9ebad9c3020625df0a178e6a2d06eaae15ef767c Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 12:51:19 +0800
|
||||
Subject: [PATCH] cpu/features: fix bug for memory leakage
|
||||
|
||||
strList hash not free after used, Fix it.
|
||||
---
|
||||
target/i386/cpu.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index fc61a84b1e..f94405c02b 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -5475,6 +5475,7 @@ static void x86_cpu_get_unavailable_features(Object *obj, Visitor *v,
|
||||
|
||||
x86_cpu_list_feature_names(xc->filtered_features, &result);
|
||||
visit_type_strList(v, "unavailable-features", &result, errp);
|
||||
+ qapi_free_strList(result);
|
||||
}
|
||||
|
||||
/* Print all cpuid feature names in featureset
|
||||
--
|
||||
2.27.0
|
||||
|
||||
144
cpus-common-Add-common-CPU-utility-for-possible-vCPU.patch
Normal file
144
cpus-common-Add-common-CPU-utility-for-possible-vCPU.patch
Normal file
@ -0,0 +1,144 @@
|
||||
From 444de91551c1e141a76bf3dae4cebee9dbd57b49 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Wed, 6 May 2020 02:48:49 +0100
|
||||
Subject: [PATCH] cpus-common: Add common CPU utility for possible vCPUs
|
||||
|
||||
Adds various utility functions which might be required to fetch or check the
|
||||
state of the possible vCPUs. This also introduces concept of *disabled* vCPUs,
|
||||
which are part of the *possible* vCPUs but are not part of the *present* vCPU.
|
||||
This state shall be used during machine init time to check the presence of
|
||||
vcpus.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
cpu-common.c | 31 +++++++++++++++++++++++++
|
||||
include/hw/core/cpu.h | 53 +++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 84 insertions(+)
|
||||
|
||||
diff --git a/cpu-common.c b/cpu-common.c
|
||||
index c81fd72d16..d041a351ab 100644
|
||||
--- a/cpu-common.c
|
||||
+++ b/cpu-common.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/lockable.h"
|
||||
#include "trace/trace-root.h"
|
||||
+#include "hw/boards.h"
|
||||
|
||||
QemuMutex qemu_cpu_list_lock;
|
||||
static QemuCond exclusive_cond;
|
||||
@@ -107,6 +108,36 @@ void cpu_list_remove(CPUState *cpu)
|
||||
cpu_list_generation_id++;
|
||||
}
|
||||
|
||||
+CPUState *qemu_get_possible_cpu(int index)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ const CPUArchIdList *possible_cpus = ms->possible_cpus;
|
||||
+
|
||||
+ assert((index >= 0) && (index < possible_cpus->len));
|
||||
+
|
||||
+ return CPU(possible_cpus->cpus[index].cpu);
|
||||
+}
|
||||
+
|
||||
+bool qemu_present_cpu(CPUState *cpu)
|
||||
+{
|
||||
+ return cpu;
|
||||
+}
|
||||
+
|
||||
+bool qemu_enabled_cpu(CPUState *cpu)
|
||||
+{
|
||||
+ return cpu && !cpu->disabled;
|
||||
+}
|
||||
+
|
||||
+uint64_t qemu_get_cpu_archid(int cpu_index)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ const CPUArchIdList *possible_cpus = ms->possible_cpus;
|
||||
+
|
||||
+ assert((cpu_index >= 0) && (cpu_index < possible_cpus->len));
|
||||
+
|
||||
+ return possible_cpus->cpus[cpu_index].arch_id;
|
||||
+}
|
||||
+
|
||||
CPUState *qemu_get_cpu(int index)
|
||||
{
|
||||
CPUState *cpu;
|
||||
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
||||
index c0c8320413..c30636a936 100644
|
||||
--- a/include/hw/core/cpu.h
|
||||
+++ b/include/hw/core/cpu.h
|
||||
@@ -538,6 +538,17 @@ struct CPUState {
|
||||
GArray *plugin_mem_cbs;
|
||||
#endif
|
||||
|
||||
+ /*
|
||||
+ * Some architectures do not allow *presence* of vCPUs to be changed
|
||||
+ * after guest has booted using information specified by VMM/firmware
|
||||
+ * via ACPI MADT at the boot time. Thus to enable vCPU hotplug on these
|
||||
+ * architectures possible vCPU can have CPUState object in 'disabled'
|
||||
+ * state or can also not have CPUState object at all. This is possible
|
||||
+ * when vCPU Hotplug is supported and vCPUs are 'yet-to-be-plugged' in
|
||||
+ * the QOM or have been hot-unplugged.
|
||||
+ * By default every CPUState is enabled as of now across all archs.
|
||||
+ */
|
||||
+ bool disabled;
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
int cpu_index;
|
||||
int cluster_index;
|
||||
@@ -913,6 +924,48 @@ static inline bool cpu_in_exclusive_context(const CPUState *cpu)
|
||||
*/
|
||||
CPUState *qemu_get_cpu(int index);
|
||||
|
||||
+/**
|
||||
+ * qemu_get_possible_cpu:
|
||||
+ * @index: The CPUState@cpu_index value of the CPU to obtain.
|
||||
+ * Input index MUST be in range [0, Max Possible CPUs)
|
||||
+ *
|
||||
+ * If CPUState object exists,then it gets a CPU matching
|
||||
+ * @index in the possible CPU array.
|
||||
+ *
|
||||
+ * Returns: The possible CPU or %NULL if CPU does not exist.
|
||||
+ */
|
||||
+CPUState *qemu_get_possible_cpu(int index);
|
||||
+
|
||||
+/**
|
||||
+ * qemu_present_cpu:
|
||||
+ * @cpu: The vCPU to check
|
||||
+ *
|
||||
+ * Checks if the vCPU is amongst the present possible vcpus.
|
||||
+ *
|
||||
+ * Returns: True if it is present possible vCPU else false
|
||||
+ */
|
||||
+bool qemu_present_cpu(CPUState *cpu);
|
||||
+
|
||||
+/**
|
||||
+ * qemu_enabled_cpu:
|
||||
+ * @cpu: The vCPU to check
|
||||
+ *
|
||||
+ * Checks if the vCPU is enabled.
|
||||
+ *
|
||||
+ * Returns: True if it is 'enabled' else false
|
||||
+ */
|
||||
+bool qemu_enabled_cpu(CPUState *cpu);
|
||||
+
|
||||
+/**
|
||||
+ * qemu_get_cpu_archid:
|
||||
+ * @cpu_index: possible vCPU for which arch-id needs to be retreived
|
||||
+ *
|
||||
+ * Fetches the vCPU arch-id from the present possible vCPUs.
|
||||
+ *
|
||||
+ * Returns: arch-id of the possible vCPU
|
||||
+ */
|
||||
+uint64_t qemu_get_cpu_archid(int cpu_index);
|
||||
+
|
||||
/**
|
||||
* cpu_exists:
|
||||
* @id: Guest-exposed CPU ID to lookup.
|
||||
--
|
||||
2.27.0
|
||||
|
||||
86
doc-Update-multi-thread-compression-doc.patch
Normal file
86
doc-Update-multi-thread-compression-doc.patch
Normal file
@ -0,0 +1,86 @@
|
||||
From 55e5f8cafda3c7d4a91e9d58c7b3259476e0dab9 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 16:36:47 +0800
|
||||
Subject: [PATCH] doc: Update multi-thread compression doc
|
||||
|
||||
Modify the doc to fit the previous changes.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
docs/multi-thread-compression.txt | 31 ++++++++++++++++++-------------
|
||||
1 file changed, 18 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/docs/multi-thread-compression.txt b/docs/multi-thread-compression.txt
|
||||
index 95b1556f67..450e5de469 100644
|
||||
--- a/docs/multi-thread-compression.txt
|
||||
+++ b/docs/multi-thread-compression.txt
|
||||
@@ -33,14 +33,15 @@ thread compression can be used to accelerate the compression process.
|
||||
|
||||
The decompression speed of Zlib is at least 4 times as quick as
|
||||
compression, if the source and destination CPU have equal speed,
|
||||
-keeping the compression thread count 4 times the decompression
|
||||
-thread count can avoid resource waste.
|
||||
+and you choose Zlib as compression method, keeping the compression
|
||||
+thread count 4 times the decompression thread count can avoid resource waste.
|
||||
|
||||
Compression level can be used to control the compression speed and the
|
||||
-compression ratio. High compression ratio will take more time, level 0
|
||||
-stands for no compression, level 1 stands for the best compression
|
||||
-speed, and level 9 stands for the best compression ratio. Users can
|
||||
-select a level number between 0 and 9.
|
||||
+compression ratio. High compression ratio will take more time,
|
||||
+level 1 stands for the best compression speed, and higher level means higher
|
||||
+compression ration. For Zlib, users can select a level number between 0 and 9,
|
||||
+where level 0 stands for no compression. For Zstd, users can select a
|
||||
+level number between 1 and 22.
|
||||
|
||||
|
||||
When to use the multiple thread compression in live migration
|
||||
@@ -116,16 +117,19 @@ to support the multiple thread compression migration:
|
||||
2. Activate compression on the source:
|
||||
{qemu} migrate_set_capability compress on
|
||||
|
||||
-3. Set the compression thread count on source:
|
||||
+3. Set the compression method:
|
||||
+ {qemu} migrate_set_parameter compress_method zstd
|
||||
+
|
||||
+4. Set the compression thread count on source:
|
||||
{qemu} migrate_set_parameter compress-threads 12
|
||||
|
||||
-4. Set the compression level on the source:
|
||||
+5. Set the compression level on the source:
|
||||
{qemu} migrate_set_parameter compress-level 1
|
||||
|
||||
-5. Set the decompression thread count on destination:
|
||||
+6. Set the decompression thread count on destination:
|
||||
{qemu} migrate_set_parameter decompress-threads 3
|
||||
|
||||
-6. Start outgoing migration:
|
||||
+7. Start outgoing migration:
|
||||
{qemu} migrate -d tcp:destination.host:4444
|
||||
{qemu} info migrate
|
||||
Capabilities: ... compress: on
|
||||
@@ -136,6 +140,7 @@ The following are the default settings:
|
||||
compress-threads: 8
|
||||
decompress-threads: 2
|
||||
compress-level: 1 (which means best speed)
|
||||
+ compress_method: zlib
|
||||
|
||||
So, only the first two steps are required to use the multiple
|
||||
thread compression in migration. You can do more if the default
|
||||
@@ -143,7 +148,7 @@ settings are not appropriate.
|
||||
|
||||
TODO
|
||||
====
|
||||
-Some faster (de)compression method such as LZ4 and Quicklz can help
|
||||
-to reduce the CPU consumption when doing (de)compression. If using
|
||||
-these faster (de)compression method, less (de)compression threads
|
||||
+Comparing to Zlib, Some faster (de)compression method such as LZ4
|
||||
+and Quicklz can help to reduce the CPU consumption when doing (de)compression.
|
||||
+If using these faster (de)compression method, less (de)compression threads
|
||||
are needed when doing the migration.
|
||||
--
|
||||
2.27.0
|
||||
|
||||
78
docs-Add-generic-vhost-vdpa-device-documentation.patch
Normal file
78
docs-Add-generic-vhost-vdpa-device-documentation.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 28ed79b98f08b5701dcaab7c6ad1015602b28e02 Mon Sep 17 00:00:00 2001
|
||||
From: libai <libai12@huawei.com>
|
||||
Date: Sat, 12 Nov 2022 22:40:13 +0800
|
||||
Subject: [PATCH] docs: Add generic vhost-vdpa device documentation
|
||||
|
||||
Add the description of the generic vhost-vdpa device
|
||||
|
||||
Signed-off-by: libai <libai12@huawei.com>
|
||||
---
|
||||
docs/system/device-emulation.rst | 1 +
|
||||
.../devices/vhost-vdpa-generic-device.rst | 46 +++++++++++++++++++
|
||||
2 files changed, 47 insertions(+)
|
||||
create mode 100644 docs/system/devices/vhost-vdpa-generic-device.rst
|
||||
|
||||
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
|
||||
index d1f3277cb0..e1b2d18fb1 100644
|
||||
--- a/docs/system/device-emulation.rst
|
||||
+++ b/docs/system/device-emulation.rst
|
||||
@@ -98,3 +98,4 @@ Emulated Devices
|
||||
devices/canokey.rst
|
||||
devices/usb-u2f.rst
|
||||
devices/igb.rst
|
||||
+ devices/vhost-vdpa-generic-device.rst
|
||||
diff --git a/docs/system/devices/vhost-vdpa-generic-device.rst b/docs/system/devices/vhost-vdpa-generic-device.rst
|
||||
new file mode 100644
|
||||
index 0000000000..25fbcac60e
|
||||
--- /dev/null
|
||||
+++ b/docs/system/devices/vhost-vdpa-generic-device.rst
|
||||
@@ -0,0 +1,46 @@
|
||||
+
|
||||
+=========================
|
||||
+vhost-vDPA generic device
|
||||
+=========================
|
||||
+
|
||||
+This document explains the usage of the vhost-vDPA generic device.
|
||||
+
|
||||
+Description
|
||||
+-----------
|
||||
+
|
||||
+vDPA(virtio data path acceleration) device is a device that uses a datapath
|
||||
+which complies with the virtio specifications with vendor specific control
|
||||
+path.
|
||||
+
|
||||
+QEMU provides two types of vhost-vDPA devices to enable the vDPA device, one
|
||||
+is type sensitive which means QEMU needs to know the actual device type
|
||||
+(e.g. net, blk, scsi) and another is called "vhost-vDPA generic device" which
|
||||
+is type insensitive
|
||||
+
|
||||
+The vhost-vDPA generic device builds on the vhost-vdpa subsystem and virtio
|
||||
+subsystem. It is quite small, but it can support any type of virtio device.
|
||||
+
|
||||
+Examples
|
||||
+--------
|
||||
+
|
||||
+Prepare the vhost-vDPA backends first:
|
||||
+
|
||||
+::
|
||||
+ host# ls -l /dev/vhost-vdpa-*
|
||||
+ crw------- 1 root root 236, 0 Nov 2 00:49 /dev/vhost-vdpa-0
|
||||
+
|
||||
+Start QEMU with virtio-mmio bus:
|
||||
+
|
||||
+::
|
||||
+ host# qemu-system \
|
||||
+ -M microvm -m 512 -smp 2 -kernel ... -initrd ... \
|
||||
+ -device vhost-vdpa-device,vhostdev=/dev/vhost-vdpa-0 \
|
||||
+ ...
|
||||
+
|
||||
+Start QEMU with virtio-pci bus:
|
||||
+
|
||||
+::
|
||||
+ host# qemu-system \
|
||||
+ -M pc -m 512 -smp 2 \
|
||||
+ -device vhost-vdpa-device-pci,vhostdev=/dev/vhost-vdpa-0 \
|
||||
+ ...\
|
||||
--
|
||||
2.27.0
|
||||
|
||||
250
feature-Add-log-for-each-modules.patch
Normal file
250
feature-Add-log-for-each-modules.patch
Normal file
@ -0,0 +1,250 @@
|
||||
From 30cc47b6dd3e9ff4842eb1c2a918bbabfd8c593b Mon Sep 17 00:00:00 2001
|
||||
From: "wangxinxin.wang@huawei.com" <wangxinxin.wang@huawei.com>
|
||||
Date: Sun, 17 Mar 2024 15:44:28 +0800
|
||||
Subject: [PATCH] feature: Add log for each modules
|
||||
|
||||
add log for each modules.
|
||||
|
||||
Signed-off-by: miaoyubo <miaoyubo@huawei.com>
|
||||
Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 5 ++++-
|
||||
hw/char/virtio-serial-bus.c | 5 +++++
|
||||
hw/pci/pci.c | 1 +
|
||||
hw/usb/bus.c | 6 ++++++
|
||||
hw/usb/host-libusb.c | 5 +++++
|
||||
hw/virtio/virtio-scsi-pci.c | 3 +++
|
||||
monitor/qmp-cmds.c | 3 +++
|
||||
os-posix.c | 1 +
|
||||
qapi/qmp-dispatch.c | 15 +++++++++++++++
|
||||
system/qdev-monitor.c | 5 +++++
|
||||
10 files changed, 48 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 33f4c6d547..d900df93a4 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -1834,7 +1834,10 @@ void kvm_irqchip_commit_routes(KVMState *s)
|
||||
s->irq_routes->flags = 0;
|
||||
trace_kvm_irqchip_commit_routes();
|
||||
ret = kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
|
||||
- assert(ret == 0);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("Set GSI routing failed: %m");
|
||||
+ abort();
|
||||
+ }
|
||||
}
|
||||
|
||||
static void kvm_add_routing_entry(KVMState *s,
|
||||
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
|
||||
index dd619f0731..44906057be 100644
|
||||
--- a/hw/char/virtio-serial-bus.c
|
||||
+++ b/hw/char/virtio-serial-bus.c
|
||||
@@ -257,6 +257,8 @@ static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
|
||||
virtio_stw_p(vdev, &cpkt.value, value);
|
||||
|
||||
trace_virtio_serial_send_control_event(port_id, event, value);
|
||||
+ qemu_log("virtio serial port %d send control message"
|
||||
+ " event = %d, value = %d\n", port_id, event, value);
|
||||
return send_control_msg(vser, &cpkt, sizeof(cpkt));
|
||||
}
|
||||
|
||||
@@ -364,6 +366,9 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
|
||||
cpkt.value = virtio_lduw_p(vdev, &gcpkt->value);
|
||||
|
||||
trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
|
||||
+ qemu_log("virtio serial port '%u' handle control message"
|
||||
+ " event = %d, value = %d\n",
|
||||
+ virtio_ldl_p(vdev, &gcpkt->id), cpkt.event, cpkt.value);
|
||||
|
||||
if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
|
||||
if (!cpkt.value) {
|
||||
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
|
||||
index c49417abb2..9da41088df 100644
|
||||
--- a/hw/pci/pci.c
|
||||
+++ b/hw/pci/pci.c
|
||||
@@ -2411,6 +2411,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
|
||||
snprintf(name, sizeof(name), "%s.rom",
|
||||
vmsd ? vmsd->name : object_get_typename(OBJECT(pdev)));
|
||||
|
||||
+ qemu_log("add rom file: %s\n", name);
|
||||
pdev->has_rom = true;
|
||||
memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize,
|
||||
&error_fatal);
|
||||
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
|
||||
index 92d6ed5626..20cd9b6e6f 100644
|
||||
--- a/hw/usb/bus.c
|
||||
+++ b/hw/usb/bus.c
|
||||
@@ -536,6 +536,10 @@ void usb_check_attach(USBDevice *dev, Error **errp)
|
||||
bus->qbus.name, port->path, portspeed);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ qemu_log("attach usb device \"%s\" (%s speed) to VM bus \"%s\", "
|
||||
+ "port \"%s\" (%s speed)\n", dev->product_desc, devspeed,
|
||||
+ bus->qbus.name, port->path, portspeed);
|
||||
}
|
||||
|
||||
void usb_device_attach(USBDevice *dev, Error **errp)
|
||||
@@ -564,6 +568,8 @@ int usb_device_detach(USBDevice *dev)
|
||||
|
||||
usb_detach(port);
|
||||
dev->attached = false;
|
||||
+ qemu_log("detach usb device \"%s\" from VM bus \"%s\", port \"%s\"\n",
|
||||
+ dev->product_desc, bus->qbus.name, port->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
|
||||
index dba469c1ef..11a246ac72 100644
|
||||
--- a/hw/usb/host-libusb.c
|
||||
+++ b/hw/usb/host-libusb.c
|
||||
@@ -992,6 +992,8 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
|
||||
|
||||
rc = libusb_open(dev, &s->dh);
|
||||
if (rc != 0) {
|
||||
+ qemu_log("libusb open usb device bus %d, device %d failed\n",
|
||||
+ bus_num, addr);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@@ -1019,6 +1021,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
|
||||
|
||||
libusb_get_device_descriptor(dev, &s->ddesc);
|
||||
usb_host_get_port(s->dev, s->port, sizeof(s->port));
|
||||
+ qemu_log("open a host usb device on bus %d, device %d\n", bus_num, addr);
|
||||
|
||||
usb_ep_init(udev);
|
||||
usb_host_ep_update(s);
|
||||
@@ -1146,6 +1149,8 @@ static int usb_host_close(USBHostDevice *s)
|
||||
usb_device_detach(udev);
|
||||
}
|
||||
|
||||
+ qemu_log("begin to reset the usb device, bus : %d, device : %d\n",
|
||||
+ s->bus_num, s->addr);
|
||||
usb_host_release_interfaces(s);
|
||||
libusb_reset_device(s->dh);
|
||||
usb_host_attach_kernel(s);
|
||||
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
|
||||
index e8e3442f38..e542d47162 100644
|
||||
--- a/hw/virtio/virtio-scsi-pci.c
|
||||
+++ b/hw/virtio/virtio-scsi-pci.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "qemu/module.h"
|
||||
#include "hw/virtio/virtio-pci.h"
|
||||
#include "qom/object.h"
|
||||
+#include "qemu/log.h"
|
||||
|
||||
typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
|
||||
|
||||
@@ -51,6 +52,8 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
||||
VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
|
||||
char *bus_name;
|
||||
|
||||
+ qemu_log("virtio scsi HBA %s begin to initialize.\n",
|
||||
+ !proxy->id ? "NULL" : proxy->id);
|
||||
if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
|
||||
conf->num_queues =
|
||||
virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
|
||||
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
|
||||
index b0f948d337..e78462b857 100644
|
||||
--- a/monitor/qmp-cmds.c
|
||||
+++ b/monitor/qmp-cmds.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "hw/intc/intc.h"
|
||||
#include "hw/rdma/rdma.h"
|
||||
+#include "qemu/log.h"
|
||||
|
||||
NameInfo *qmp_query_name(Error **errp)
|
||||
{
|
||||
@@ -110,8 +111,10 @@ void qmp_cont(Error **errp)
|
||||
}
|
||||
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
+ qemu_log("qmp cont is received in migration\n");
|
||||
autostart = 1;
|
||||
} else {
|
||||
+ qemu_log("qmp cont is received and vm is started\n");
|
||||
vm_start();
|
||||
}
|
||||
}
|
||||
diff --git a/os-posix.c b/os-posix.c
|
||||
index 52ef6990ff..8f70ee0534 100644
|
||||
--- a/os-posix.c
|
||||
+++ b/os-posix.c
|
||||
@@ -306,6 +306,7 @@ int os_mlock(void)
|
||||
#ifdef HAVE_MLOCKALL
|
||||
int ret = 0;
|
||||
|
||||
+ qemu_log("do mlockall\n");
|
||||
ret = mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
if (ret < 0) {
|
||||
error_report("mlockall: %s", strerror(errno));
|
||||
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
|
||||
index 7a215cbfd7..e33efd3740 100644
|
||||
--- a/qapi/qmp-dispatch.c
|
||||
+++ b/qapi/qmp-dispatch.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/log.h"
|
||||
+#include "qapi/qmp/qstring.h"
|
||||
|
||||
Visitor *qobject_input_visitor_new_qmp(QObject *obj)
|
||||
{
|
||||
@@ -220,6 +221,20 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ
|
||||
|
||||
assert(!(oob && qemu_in_coroutine()));
|
||||
assert(monitor_cur() == NULL);
|
||||
+
|
||||
+ 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, json->str);
|
||||
+ }
|
||||
+ g_string_free(json, true);
|
||||
+ }
|
||||
+
|
||||
if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
|
||||
monitor_set_cur(qemu_coroutine_self(), cur_mon);
|
||||
cmd->fn(args, &ret, &err);
|
||||
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
|
||||
index b10e483a9a..5b35704b5e 100644
|
||||
--- a/system/qdev-monitor.c
|
||||
+++ b/system/qdev-monitor.c
|
||||
@@ -644,6 +644,7 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
|
||||
if (path != NULL) {
|
||||
bus = qbus_find(path, errp);
|
||||
if (!bus) {
|
||||
+ qemu_log("can not find bus for %s\n", driver);
|
||||
return NULL;
|
||||
}
|
||||
if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
|
||||
@@ -714,6 +715,8 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
|
||||
object_set_properties_from_keyval(&dev->parent_obj, dev->opts, from_json,
|
||||
errp);
|
||||
if (*errp) {
|
||||
+ qemu_log("the bus %s -driver %s set property failed\n",
|
||||
+ bus ? bus->name : "None", driver);
|
||||
goto err_del_dev;
|
||||
}
|
||||
qemu_log("add qdev %s:%s success\n", driver, dev->id ? dev->id : "none");
|
||||
@@ -738,6 +741,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
|
||||
|
||||
ret = qdev_device_add_from_qdict(qdict, false, errp);
|
||||
if (ret) {
|
||||
+ qemu_log("add qdev %s:%s success\n", qemu_opt_get(opts, "driver"),
|
||||
+ qemu_opts_id(opts) ? qemu_opts_id(opts) : "none");
|
||||
qemu_opts_del(opts);
|
||||
}
|
||||
qobject_unref(qdict);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
158
feature-Add-logs-for-vm-start-and-destroy.patch
Normal file
158
feature-Add-logs-for-vm-start-and-destroy.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From 9a47271fb6c855ec92e087d59d65f3cc0c684725 Mon Sep 17 00:00:00 2001
|
||||
From: "wangxinxin.wang@huawei.com" <wangxinxin.wang@huawei.com>
|
||||
Date: Sun, 17 Mar 2024 15:04:09 +0800
|
||||
Subject: [PATCH] feature: Add logs for vm start and destroy
|
||||
|
||||
Add QEMU_LOG for vm start and destroy
|
||||
|
||||
Signed-off-by: miaoyubo <miaoyubo@huawei.com>
|
||||
Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/acpi/core.c | 4 ++++
|
||||
hw/core/reset.c | 2 ++
|
||||
system/main.c | 2 ++
|
||||
system/runstate.c | 2 ++
|
||||
system/vl.c | 6 ++++++
|
||||
5 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
|
||||
index ec5e127d17..b6241f70e9 100644
|
||||
--- a/hw/acpi/core.c
|
||||
+++ b/hw/acpi/core.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "qemu/config-file.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/qapi-events-run-state.h"
|
||||
@@ -588,13 +589,16 @@ static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
uint16_t sus_typ = (val >> 10) & 7;
|
||||
switch (sus_typ) {
|
||||
case 0: /* soft power off */
|
||||
+ qemu_log("VM will be soft power off\n");
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
break;
|
||||
case 1:
|
||||
+ qemu_log("VM will be suspend state\n");
|
||||
qemu_system_suspend_request();
|
||||
break;
|
||||
default:
|
||||
if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
|
||||
+ qemu_log("VM will be S4 state\n");
|
||||
qapi_event_send_suspend_disk();
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
}
|
||||
diff --git a/hw/core/reset.c b/hw/core/reset.c
|
||||
index d3263b613e..fa63bfedb7 100644
|
||||
--- a/hw/core/reset.c
|
||||
+++ b/hw/core/reset.c
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/queue.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
/* reset/shutdown handler */
|
||||
@@ -75,6 +76,7 @@ void qemu_devices_reset(ShutdownCause reason)
|
||||
{
|
||||
QEMUResetEntry *re, *nre;
|
||||
|
||||
+ qemu_log("reset all devices\n");
|
||||
/* reset all devices */
|
||||
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
|
||||
if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
|
||||
diff --git a/system/main.c b/system/main.c
|
||||
index 9b91d21ea8..28bb283ebf 100644
|
||||
--- a/system/main.c
|
||||
+++ b/system/main.c
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "qemu-main.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
@@ -34,6 +35,7 @@ int qemu_default_main(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
+ qemu_log("qemu enter main_loop\n");
|
||||
status = qemu_main_loop();
|
||||
qemu_cleanup(status);
|
||||
|
||||
diff --git a/system/runstate.c b/system/runstate.c
|
||||
index 62e6db8d42..538c645326 100644
|
||||
--- a/system/runstate.c
|
||||
+++ b/system/runstate.c
|
||||
@@ -769,9 +769,11 @@ static bool main_loop_should_exit(int *status)
|
||||
}
|
||||
if (qemu_powerdown_requested()) {
|
||||
qemu_system_powerdown();
|
||||
+ qemu_log("domain is power down by outside operation\n");
|
||||
}
|
||||
if (qemu_vmstop_requested(&r)) {
|
||||
vm_stop(r);
|
||||
+ qemu_log("domain is stopped by outside operation\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
diff --git a/system/vl.c b/system/vl.c
|
||||
index 2bcd9efb9a..165c3cae8a 100644
|
||||
--- a/system/vl.c
|
||||
+++ b/system/vl.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "qemu/help-texts.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/units.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/page-vary.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@@ -2633,6 +2634,7 @@ static void qemu_create_cli_devices(void)
|
||||
}
|
||||
|
||||
/* init generic devices */
|
||||
+ qemu_log("device init start\n");
|
||||
rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE);
|
||||
qemu_opts_foreach(qemu_find_opts("device"),
|
||||
device_init_func, NULL, &error_fatal);
|
||||
@@ -2778,6 +2780,7 @@ void qemu_init(int argc, char **argv)
|
||||
|
||||
qemu_init_subsystems();
|
||||
|
||||
+ qemu_log("qemu pid is %d, options parsing start\n", getpid());
|
||||
/* first pass of option parsing */
|
||||
optind = 1;
|
||||
while (optind < argc) {
|
||||
@@ -2997,6 +3000,7 @@ void qemu_init(int argc, char **argv)
|
||||
exit(0);
|
||||
break;
|
||||
case QEMU_OPTION_m:
|
||||
+ qemu_log("memory options parse start\n");
|
||||
opts = qemu_opts_parse_noisily(qemu_find_opts("memory"), optarg, true);
|
||||
if (opts == NULL) {
|
||||
exit(1);
|
||||
@@ -3714,6 +3718,7 @@ void qemu_init(int argc, char **argv)
|
||||
*/
|
||||
|
||||
machine_class = MACHINE_GET_CLASS(current_machine);
|
||||
+ qemu_log("configure accelerator %s start\n", machine_class->name);
|
||||
if (!qtest_enabled() && machine_class->deprecation_reason) {
|
||||
warn_report("Machine type '%s' is deprecated: %s",
|
||||
machine_class->name, machine_class->deprecation_reason);
|
||||
@@ -3732,6 +3737,7 @@ void qemu_init(int argc, char **argv)
|
||||
*/
|
||||
migration_object_init();
|
||||
|
||||
+ qemu_log("machine init start\n");
|
||||
/* parse features once if machine provides default cpu_type */
|
||||
current_machine->cpu_type = machine_class->default_cpu_type;
|
||||
if (cpu_option) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
46
fix-qemu-core-when-vhost-user-net-config-with-server.patch
Normal file
46
fix-qemu-core-when-vhost-user-net-config-with-server.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 97335ac382e36db18a61d3891f1fafd15475822e Mon Sep 17 00:00:00 2001
|
||||
From: caojinhuahw <caojinhua1@huawei.com>
|
||||
Date: Mon, 19 Dec 2022 12:35:50 +0000
|
||||
Subject: [PATCH] fix qemu-core when vhost-user-net config with server mode
|
||||
|
||||
commit 3a223111d7 set default reconnect for vhost-user-net
|
||||
device, if vhost-user-net config with server mode will
|
||||
casuse the core when ovs client stop.
|
||||
tcp_chr_disconnect ---> set tcp_char state disconnect
|
||||
tcp_chr start reconnect ---> set tcp_char state connecting
|
||||
tcp_char is listen ---> call tcp_chr_accept()
|
||||
fun tcp_char_accept() set tcp_char state to connecting, but
|
||||
current tcp_char state already is connecting, assert failed
|
||||
in tcp_char_change_state() raise qemu core
|
||||
assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED)
|
||||
|
||||
this commit check tcp_char mode, if tcp_char config with server
|
||||
mode, dont set reconnect time for tcp_chr.
|
||||
|
||||
fix: 3a223111d7 vhost-user: Add support reconnect vhost-user socket
|
||||
|
||||
Signed-off-by: caojinhuahw <caojinhua1@huawei.com>
|
||||
---
|
||||
chardev/char-socket.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
|
||||
index 9c60e15c8e..0c9ab069ae 100644
|
||||
--- a/chardev/char-socket.c
|
||||
+++ b/chardev/char-socket.c
|
||||
@@ -347,6 +347,12 @@ static void tcp_chr_set_reconnect_time(Chardev *chr,
|
||||
void qemu_chr_set_reconnect_time(Chardev *chr, int64_t reconnect_time)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_GET_CLASS(chr);
|
||||
+ SocketChardev *s = SOCKET_CHARDEV(chr);
|
||||
+
|
||||
+ /* if sock dev is listen, dont set reconnect time */
|
||||
+ if (s->is_listen) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (cc->chr_set_reconnect_time) {
|
||||
cc->chr_set_reconnect_time(chr, reconnect_time);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
129
freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch
Normal file
129
freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch
Normal file
@ -0,0 +1,129 @@
|
||||
From 0a6baf4799dd6e70d7959002ea6ddb998eddbc6d Mon Sep 17 00:00:00 2001
|
||||
From: "shenghualong@huawei.com" <shenghualong@huawei.com>
|
||||
Date: Mon, 18 Mar 2024 15:53:43 +0800
|
||||
Subject: [PATCH] freeclock: add qmp command to get time offset of vm in
|
||||
seconds
|
||||
|
||||
When setting the system time in VM, a RTC_CHANGE event will be reported.
|
||||
However, if libvirt is restarted while the event is be reporting, the
|
||||
event will be lost and we will get the old time (not the time we set in
|
||||
VM) after rebooting the VM.
|
||||
|
||||
We save the delta time in QEMU and add a rtc-date-diff qmp to get the
|
||||
delta time so that libvirt can get the latest time in VM according to
|
||||
the qmp after libvirt is restarted.
|
||||
|
||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
||||
Signed-off-by: zhangxinhao <zhangxinhao1@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/core/machine-qmp-cmds.c | 6 ++++++
|
||||
include/sysemu/rtc.h | 4 +++-
|
||||
qapi/misc.json | 9 +++++++++
|
||||
qapi/pragma.json | 3 ++-
|
||||
system/rtc.c | 11 +++++++++++
|
||||
5 files changed, 31 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
|
||||
index 3860a50c3b..f1389ef644 100644
|
||||
--- a/hw/core/machine-qmp-cmds.c
|
||||
+++ b/hw/core/machine-qmp-cmds.c
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
+#include "sysemu/rtc.h"
|
||||
#include "hw/acpi/vmgenid.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/intc/intc.h"
|
||||
@@ -373,6 +374,11 @@ HumanReadableText *qmp_x_query_irq(Error **errp)
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
|
||||
+int64_t qmp_query_rtc_date_diff(Error **errp)
|
||||
+{
|
||||
+ return get_rtc_date_diff();
|
||||
+}
|
||||
+
|
||||
GuidInfo *qmp_query_vm_generation_id(Error **errp)
|
||||
{
|
||||
GuidInfo *info;
|
||||
diff --git a/include/sysemu/rtc.h b/include/sysemu/rtc.h
|
||||
index 0fc8ad6fdf..3edae762d4 100644
|
||||
--- a/include/sysemu/rtc.h
|
||||
+++ b/include/sysemu/rtc.h
|
||||
@@ -54,5 +54,7 @@ void qemu_get_timedate(struct tm *tm, time_t offset);
|
||||
* then this function will return 3600.
|
||||
*/
|
||||
time_t qemu_timedate_diff(struct tm *tm);
|
||||
-
|
||||
+time_t get_rtc_date_diff(void);
|
||||
+void set_rtc_date_diff(time_t diff);
|
||||
+int64_t qmp_query_rtc_date_diff(Error **errp);
|
||||
#endif
|
||||
diff --git a/qapi/misc.json b/qapi/misc.json
|
||||
index cda2effa81..1832d5f460 100644
|
||||
--- a/qapi/misc.json
|
||||
+++ b/qapi/misc.json
|
||||
@@ -550,6 +550,15 @@
|
||||
'returns': ['CommandLineOptionInfo'],
|
||||
'allow-preconfig': true}
|
||||
|
||||
+##
|
||||
+# @query-rtc-date-diff:
|
||||
+#
|
||||
+# get vm's time offset
|
||||
+#
|
||||
+# Since: 2.8
|
||||
+##
|
||||
+{ 'command': 'query-rtc-date-diff', 'returns': 'int64' }
|
||||
+
|
||||
##
|
||||
# @RTC_CHANGE:
|
||||
#
|
||||
diff --git a/qapi/pragma.json b/qapi/pragma.json
|
||||
index 0aa4eeddd3..7a07b44bb1 100644
|
||||
--- a/qapi/pragma.json
|
||||
+++ b/qapi/pragma.json
|
||||
@@ -30,7 +30,8 @@
|
||||
'qom-get',
|
||||
'query-tpm-models',
|
||||
'query-tpm-types',
|
||||
- 'ringbuf-read' ],
|
||||
+ 'ringbuf-read',
|
||||
+ 'query-rtc-date-diff'],
|
||||
# Externally visible types whose member names may use uppercase
|
||||
'member-name-exceptions': [ # visible in:
|
||||
'ACPISlotType', # query-acpi-ospm-status
|
||||
diff --git a/system/rtc.c b/system/rtc.c
|
||||
index 4904581abe..e16b5fffc5 100644
|
||||
--- a/system/rtc.c
|
||||
+++ b/system/rtc.c
|
||||
@@ -44,6 +44,7 @@ static time_t rtc_ref_start_datetime;
|
||||
static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
|
||||
static int rtc_host_datetime_offset = -1; /* valid & used only with
|
||||
RTC_BASE_DATETIME */
|
||||
+static time_t rtc_date_diff = 0;
|
||||
QEMUClockType rtc_clock;
|
||||
/***********************************************************/
|
||||
/* RTC reference time/date access */
|
||||
@@ -108,6 +109,16 @@ time_t qemu_timedate_diff(struct tm *tm)
|
||||
return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
|
||||
}
|
||||
|
||||
+time_t get_rtc_date_diff(void)
|
||||
+{
|
||||
+ return rtc_date_diff;
|
||||
+}
|
||||
+
|
||||
+void set_rtc_date_diff(time_t diff)
|
||||
+{
|
||||
+ rtc_date_diff = diff;
|
||||
+}
|
||||
+
|
||||
static void configure_rtc_base_datetime(const char *startdate)
|
||||
{
|
||||
time_t rtc_start_datetime;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
31
freeclock-set-rtc_date_diff-for-X86.patch
Normal file
31
freeclock-set-rtc_date_diff-for-X86.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 0a0010fe0656a63e82aea495ab0a59145d3b5750 Mon Sep 17 00:00:00 2001
|
||||
From: "shenghualong@huawei.com" <shenghualong@huawei.com>
|
||||
Date: Thu, 21 Mar 2024 12:26:38 +0800
|
||||
Subject: [PATCH] freeclock: set rtc_date_diff for X86
|
||||
|
||||
Set rtc_date_diff in mc146818rtc.
|
||||
|
||||
Signed-off-by: l00500761 <liuxiangdong5@huawei.com>
|
||||
Signed-off-by: zhangxinhao <zhangxinhao1@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/rtc/mc146818rtc.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
|
||||
index 2d391a8396..e61c76d060 100644
|
||||
--- a/hw/rtc/mc146818rtc.c
|
||||
+++ b/hw/rtc/mc146818rtc.c
|
||||
@@ -606,7 +606,8 @@ static void rtc_set_time(MC146818RtcState *s)
|
||||
s->base_rtc = mktimegm(&tm);
|
||||
s->last_update = qemu_clock_get_ns(rtc_clock);
|
||||
|
||||
- qapi_event_send_rtc_change(qemu_timedate_diff(&tm), qom_path);
|
||||
+ set_rtc_date_diff(qemu_timedate_diff(&tm));
|
||||
+ qapi_event_send_rtc_change(get_rtc_date_diff(), qom_path);
|
||||
}
|
||||
|
||||
static void rtc_set_cmos(MC146818RtcState *s, const struct tm *tm)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
31
freeclock-set-rtc_date_diff-for-arm.patch
Normal file
31
freeclock-set-rtc_date_diff-for-arm.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 156be254a48d1d9b7aadcbfa4423485c592bc75d Mon Sep 17 00:00:00 2001
|
||||
From: "shenghualong@huawei.com" <shenghualong@huawei.com>
|
||||
Date: Thu, 21 Mar 2024 11:21:14 +0800
|
||||
Subject: [PATCH] freeclock: set rtc_date_diff for arm
|
||||
|
||||
Set rtc_date_diff in pl031.
|
||||
|
||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
||||
Signed-off-by: zhangxinhao <zhangxinhao1@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/rtc/pl031.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c
|
||||
index b01d0e75d1..f2e6baebba 100644
|
||||
--- a/hw/rtc/pl031.c
|
||||
+++ b/hw/rtc/pl031.c
|
||||
@@ -144,7 +144,8 @@ static void pl031_write(void * opaque, hwaddr offset,
|
||||
s->tick_offset += value - pl031_get_count(s);
|
||||
|
||||
qemu_get_timedate(&tm, s->tick_offset);
|
||||
- qapi_event_send_rtc_change(qemu_timedate_diff(&tm), qom_path);
|
||||
+ set_rtc_date_diff(qemu_timedate_diff(&tm));
|
||||
+ qapi_event_send_rtc_change(get_rtc_date_diff(), qom_path);
|
||||
|
||||
pl031_set_alarm(s);
|
||||
break;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
187
hw-acpi-ACPI-AML-Changes-to-reflect-the-correct-_STA.patch
Normal file
187
hw-acpi-ACPI-AML-Changes-to-reflect-the-correct-_STA.patch
Normal file
@ -0,0 +1,187 @@
|
||||
From 19a8fbccbc997110f472df308813ad2d7738065c Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Mon, 14 Nov 2022 02:25:28 +0000
|
||||
Subject: [PATCH] hw/acpi: ACPI/AML Changes to reflect the correct
|
||||
_STA.{PRES,ENA} Bits to Guest
|
||||
|
||||
ACPI AML changes to properly reflect the _STA.PRES and _STA.ENA Bits to the
|
||||
guest during initialzation, when CPUs are hotplugged and after CPUs are
|
||||
hot-unplugged.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 49 +++++++++++++++++++++++++++++++---
|
||||
hw/acpi/generic_event_device.c | 11 ++++++++
|
||||
include/hw/acpi/cpu.h | 2 ++
|
||||
3 files changed, 58 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index c8c11e51c6..991f1d4181 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -64,10 +64,11 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size)
|
||||
cdev = &cpu_st->devs[cpu_st->selector];
|
||||
switch (addr) {
|
||||
case ACPI_CPU_FLAGS_OFFSET_RW: /* pack and return is_* fields */
|
||||
- val |= cdev->cpu ? 1 : 0;
|
||||
+ val |= cdev->is_enabled ? 1 : 0;
|
||||
val |= cdev->is_inserting ? 2 : 0;
|
||||
val |= cdev->is_removing ? 4 : 0;
|
||||
val |= cdev->fw_remove ? 16 : 0;
|
||||
+ val |= cdev->is_present ? 32 : 0;
|
||||
trace_cpuhp_acpi_read_flags(cpu_st->selector, val);
|
||||
break;
|
||||
case ACPI_CPU_CMD_DATA_OFFSET_RW:
|
||||
@@ -229,7 +230,21 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
||||
struct CPUState *cpu = CPU(id_list->cpus[i].cpu);
|
||||
if (qemu_present_cpu(cpu)) {
|
||||
state->devs[i].cpu = cpu;
|
||||
+ state->devs[i].is_present = true;
|
||||
+ } else {
|
||||
+ if (qemu_persistent_cpu(cpu)) {
|
||||
+ state->devs[i].is_present = true;
|
||||
+ } else {
|
||||
+ state->devs[i].is_present = false;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ if (qemu_enabled_cpu(cpu)) {
|
||||
+ state->devs[i].is_enabled = true;
|
||||
+ } else {
|
||||
+ state->devs[i].is_enabled = false;
|
||||
+ }
|
||||
+
|
||||
state->devs[i].arch_id = id_list->cpus[i].arch_id;
|
||||
}
|
||||
memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state,
|
||||
@@ -262,6 +277,8 @@ void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
|
||||
cdev->cpu = CPU(dev);
|
||||
+ cdev->is_present = true;
|
||||
+ cdev->is_enabled = true;
|
||||
if (dev->hotplugged) {
|
||||
cdev->is_inserting = true;
|
||||
acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
|
||||
@@ -293,6 +310,11 @@ void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
|
||||
return;
|
||||
}
|
||||
|
||||
+ cdev->is_enabled = false;
|
||||
+ if (!qemu_persistent_cpu(CPU(dev))) {
|
||||
+ cdev->is_present = false;
|
||||
+ }
|
||||
+
|
||||
cdev->cpu = NULL;
|
||||
}
|
||||
|
||||
@@ -303,6 +325,8 @@ static const VMStateDescription vmstate_cpuhp_sts = {
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(is_inserting, AcpiCpuStatus),
|
||||
VMSTATE_BOOL(is_removing, AcpiCpuStatus),
|
||||
+ VMSTATE_BOOL(is_present, AcpiCpuStatus),
|
||||
+ VMSTATE_BOOL(is_enabled, AcpiCpuStatus),
|
||||
VMSTATE_UINT32(ost_event, AcpiCpuStatus),
|
||||
VMSTATE_UINT32(ost_status, AcpiCpuStatus),
|
||||
VMSTATE_END_OF_LIST()
|
||||
@@ -340,6 +364,7 @@ const VMStateDescription vmstate_cpu_hotplug = {
|
||||
#define CPU_REMOVE_EVENT "CRMV"
|
||||
#define CPU_EJECT_EVENT "CEJ0"
|
||||
#define CPU_FW_EJECT_EVENT "CEJF"
|
||||
+#define CPU_PRESENT "CPRS"
|
||||
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
build_madt_cpu_fn build_madt_cpu,
|
||||
@@ -400,7 +425,9 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
aml_append(field, aml_named_field(CPU_EJECT_EVENT, 1));
|
||||
/* tell firmware to do device eject, write only */
|
||||
aml_append(field, aml_named_field(CPU_FW_EJECT_EVENT, 1));
|
||||
- aml_append(field, aml_reserved_field(3));
|
||||
+ /* 1 if present, read only */
|
||||
+ aml_append(field, aml_named_field(CPU_PRESENT, 1));
|
||||
+ aml_append(field, aml_reserved_field(2));
|
||||
aml_append(field, aml_named_field(CPU_COMMAND, 8));
|
||||
aml_append(cpu_ctrl_dev, field);
|
||||
|
||||
@@ -430,6 +457,7 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
Aml *ctrl_lock = aml_name("%s.%s", cphp_res_path, CPU_LOCK);
|
||||
Aml *cpu_selector = aml_name("%s.%s", cphp_res_path, CPU_SELECTOR);
|
||||
Aml *is_enabled = aml_name("%s.%s", cphp_res_path, CPU_ENABLED);
|
||||
+ Aml *is_present = aml_name("%s.%s", cphp_res_path, CPU_PRESENT);
|
||||
Aml *cpu_cmd = aml_name("%s.%s", cphp_res_path, CPU_COMMAND);
|
||||
Aml *cpu_data = aml_name("%s.%s", cphp_res_path, CPU_DATA);
|
||||
Aml *ins_evt = aml_name("%s.%s", cphp_res_path, CPU_INSERT_EVENT);
|
||||
@@ -458,13 +486,26 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
{
|
||||
Aml *idx = aml_arg(0);
|
||||
Aml *sta = aml_local(0);
|
||||
+ Aml *ifctx2;
|
||||
+ Aml *else_ctx;
|
||||
|
||||
aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
|
||||
aml_append(method, aml_store(idx, cpu_selector));
|
||||
aml_append(method, aml_store(zero, sta));
|
||||
- ifctx = aml_if(aml_equal(is_enabled, one));
|
||||
+ ifctx = aml_if(aml_equal(is_present, one));
|
||||
{
|
||||
- aml_append(ifctx, aml_store(aml_int(0xF), sta));
|
||||
+ ifctx2 = aml_if(aml_equal(is_enabled, one));
|
||||
+ {
|
||||
+ /* cpu is present and enabled */
|
||||
+ aml_append(ifctx2, aml_store(aml_int(0xF), sta));
|
||||
+ }
|
||||
+ aml_append(ifctx, ifctx2);
|
||||
+ else_ctx = aml_else();
|
||||
+ {
|
||||
+ /* cpu is present but disabled */
|
||||
+ aml_append(else_ctx, aml_store(aml_int(0xD), sta));
|
||||
+ }
|
||||
+ aml_append(ifctx, else_ctx);
|
||||
}
|
||||
aml_append(method, ifctx);
|
||||
aml_append(method, aml_release(ctrl_lock));
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index d2fa1d0e4a..b84602b238 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -319,6 +319,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,
|
||||
@@ -367,6 +377,7 @@ static const VMStateDescription vmstate_acpi_ged = {
|
||||
},
|
||||
.subsections = (const VMStateDescription * []) {
|
||||
&vmstate_memhp_state,
|
||||
+ &vmstate_cpuhp_state,
|
||||
&vmstate_ghes_state,
|
||||
NULL
|
||||
}
|
||||
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
||||
index b31a2e50d9..fced952152 100644
|
||||
--- a/include/hw/acpi/cpu.h
|
||||
+++ b/include/hw/acpi/cpu.h
|
||||
@@ -23,6 +23,8 @@ typedef struct AcpiCpuStatus {
|
||||
uint64_t arch_id;
|
||||
bool is_inserting;
|
||||
bool is_removing;
|
||||
+ bool is_present;
|
||||
+ bool is_enabled;
|
||||
bool fw_remove;
|
||||
uint32_t ost_event;
|
||||
uint32_t ost_status;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
34
hw-acpi-Add-ACPI-CPU-hotplug-init-stub.patch
Normal file
34
hw-acpi-Add-ACPI-CPU-hotplug-init-stub.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From e442d0f8670dc4218ab4beebe645e369f925410d Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 19 Aug 2023 00:26:20 +0000
|
||||
Subject: [PATCH] hw/acpi: Add ACPI CPU hotplug init stub
|
||||
|
||||
ACPI CPU hotplug related initialization should only happend if ACPI_CPU_HOTPLUG
|
||||
support has been enabled for particular architecture. Add cpu_hotplug_hw_init()
|
||||
stub to avoid compilation break.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/acpi-cpu-hotplug-stub.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
|
||||
index 3fc4b14c26..c6c61bb9cd 100644
|
||||
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
|
||||
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
|
||||
@@ -19,6 +19,12 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
|
||||
return;
|
||||
}
|
||||
|
||||
+void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
||||
+ CPUHotplugState *state, hwaddr base_addr)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
|
||||
{
|
||||
return;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
81
hw-acpi-Init-GED-framework-with-cpu-hotplug-events.patch
Normal file
81
hw-acpi-Init-GED-framework-with-cpu-hotplug-events.patch
Normal file
@ -0,0 +1,81 @@
|
||||
From de1c8d6be3de67ff9854e9b008a000e1898aaacb Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Mon, 8 Jun 2020 21:50:08 +0100
|
||||
Subject: [PATCH] hw/acpi: Init GED framework with cpu hotplug events
|
||||
|
||||
ACPI GED(as described in the ACPI 6.2 spec) can be used to generate ACPI events
|
||||
when OSPM/guest receives an interrupt listed in the _CRS object of GED. OSPM
|
||||
then maps or demultiplexes the event by evaluating _EVT method.
|
||||
|
||||
This change adds the support of cpu hotplug event initialization in the
|
||||
existing GED framework.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 8 ++++++++
|
||||
include/hw/acpi/generic_event_device.h | 5 +++++
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index a3d31631fe..d2fa1d0e4a 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -25,6 +25,7 @@ static const uint32_t ged_supported_events[] = {
|
||||
ACPI_GED_MEM_HOTPLUG_EVT,
|
||||
ACPI_GED_PWR_DOWN_EVT,
|
||||
ACPI_GED_NVDIMM_HOTPLUG_EVT,
|
||||
+ ACPI_GED_CPU_HOTPLUG_EVT,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -400,6 +401,13 @@ static void acpi_ged_initfn(Object *obj)
|
||||
memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st,
|
||||
TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT);
|
||||
sysbus_init_mmio(sbd, &ged_st->regs);
|
||||
+
|
||||
+ s->cpuhp.device = OBJECT(s);
|
||||
+ memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container",
|
||||
+ ACPI_CPU_HOTPLUG_REG_LEN);
|
||||
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &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/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
||||
index ba84ce0214..a803ea818e 100644
|
||||
--- a/include/hw/acpi/generic_event_device.h
|
||||
+++ b/include/hw/acpi/generic_event_device.h
|
||||
@@ -60,6 +60,7 @@
|
||||
#define HW_ACPI_GENERIC_EVENT_DEVICE_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
+#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/acpi/ghes.h"
|
||||
#include "qom/object.h"
|
||||
@@ -95,6 +96,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
|
||||
#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
|
||||
#define ACPI_GED_PWR_DOWN_EVT 0x2
|
||||
#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
|
||||
+#define ACPI_GED_CPU_HOTPLUG_EVT 0x8
|
||||
|
||||
typedef struct GEDState {
|
||||
MemoryRegion evt;
|
||||
@@ -106,6 +108,9 @@ struct AcpiGedState {
|
||||
SysBusDevice parent_obj;
|
||||
MemHotplugState memhp_state;
|
||||
MemoryRegion container_memhp;
|
||||
+ CPUHotplugState cpuhp_state;
|
||||
+ MemoryRegion container_cpuhp;
|
||||
+ AcpiCpuHotplug cpuhp;
|
||||
GEDState ged_state;
|
||||
uint32_t ged_event_bitmap;
|
||||
qemu_irq irq;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
41
hw-acpi-Make-_MAT-method-optional.patch
Normal file
41
hw-acpi-Make-_MAT-method-optional.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From e9b0d476172e872bf695780a9ffa8072faeb3cd0 Mon Sep 17 00:00:00 2001
|
||||
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
Date: Mon, 25 Apr 2022 17:40:57 +0100
|
||||
Subject: [PATCH] hw/acpi: Make _MAT method optional
|
||||
|
||||
The GICC interface on arm64 vCPUs is statically defined in the MADT, and
|
||||
doesn't require a _MAT entry. Although the GICC is indicated as present
|
||||
by the MADT entry, it can only be used from vCPU sysregs, which aren't
|
||||
accessible until hot-add.
|
||||
|
||||
Co-developed-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
Co-developed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
|
||||
Signed-off-by: Jonathan Cameron <jonathan.cameron@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index 991f1d4181..c922c380aa 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -720,9 +720,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
aml_append(dev, method);
|
||||
|
||||
/* build _MAT object */
|
||||
- build_madt_cpu(i, arch_ids, madt_buf, true); /* set enabled flag */
|
||||
- aml_append(dev, aml_name_decl("_MAT",
|
||||
- aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
|
||||
+ if (build_madt_cpu) {
|
||||
+ build_madt_cpu(i, arch_ids, madt_buf, true); /* set enabled flag */
|
||||
+ aml_append(dev, aml_name_decl("_MAT",
|
||||
+ aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
|
||||
+ }
|
||||
g_array_free(madt_buf, true);
|
||||
|
||||
if (CPU(arch_ids->cpus[i].cpu) != first_cpu) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
52
hw-acpi-Move-CPU-ctrl-dev-MMIO-region-len-macro-to-c.patch
Normal file
52
hw-acpi-Move-CPU-ctrl-dev-MMIO-region-len-macro-to-c.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From fd6e7e7278e1c0fb08e0a09d9e22157e11b36ece Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sun, 20 Aug 2023 17:11:04 +0000
|
||||
Subject: [PATCH] hw/acpi: Move CPU ctrl-dev MMIO region len macro to common
|
||||
header file
|
||||
|
||||
CPU ctrl-dev MMIO region length could be used in ACPI GED (common ACPI code
|
||||
across architectures) and various other architecture specific places. To make
|
||||
these code places independent of compilation order, ACPI_CPU_HOTPLUG_REG_LEN
|
||||
macro should be moved to a header file.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 2 +-
|
||||
include/hw/acpi/cpu_hotplug.h | 2 ++
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index 011d2c6c2d..4b24a25003 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/acpi/cpu.h"
|
||||
+#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-events-acpi.h"
|
||||
#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/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
|
||||
index 3b932abbbb..48b291e45e 100644
|
||||
--- a/include/hw/acpi/cpu_hotplug.h
|
||||
+++ b/include/hw/acpi/cpu_hotplug.h
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "hw/hotplug.h"
|
||||
#include "hw/acpi/cpu.h"
|
||||
|
||||
+#define ACPI_CPU_HOTPLUG_REG_LEN 12
|
||||
+
|
||||
typedef struct AcpiCpuHotplug {
|
||||
Object *device;
|
||||
MemoryRegion io;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
77
hw-acpi-Update-ACPI-GED-framework-to-support-vCPU-Ho.patch
Normal file
77
hw-acpi-Update-ACPI-GED-framework-to-support-vCPU-Ho.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From 0bdb1861985704af9b82e35053b5ab99f7880eb6 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Thu, 7 May 2020 21:30:09 +0100
|
||||
Subject: [PATCH] hw/acpi: Update ACPI GED framework to support vCPU Hotplug
|
||||
|
||||
ACPI GED shall be used to convey to the guest kernel about any CPU hot-(un)plug
|
||||
events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced
|
||||
to support CPU hotplug state and events.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index ad252e6a91..0266733a54 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
+#include "hw/acpi/cpu.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
@@ -239,6 +240,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
} else {
|
||||
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)));
|
||||
@@ -253,6 +256,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
|
||||
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
|
||||
acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "acpi: device unplug request for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -266,6 +271,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||
acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
+ acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "acpi: device unplug for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -277,6 +284,7 @@ static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
|
||||
AcpiGedState *s = ACPI_GED(adev);
|
||||
|
||||
acpi_memory_ospm_status(&s->memhp_state, list);
|
||||
+ acpi_cpu_ospm_status(&s->cpuhp_state, list);
|
||||
}
|
||||
|
||||
static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||
@@ -291,6 +299,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||
sel = ACPI_GED_PWR_DOWN_EVT;
|
||||
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
|
||||
sel = ACPI_GED_NVDIMM_HOTPLUG_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);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
118
hw-acpi-Update-CPUs-AML-with-cpu-ctrl-dev-change.patch
Normal file
118
hw-acpi-Update-CPUs-AML-with-cpu-ctrl-dev-change.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From 06059c960d863c21c7d9cf4829ad2078692ed9e1 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Fri, 8 May 2020 13:27:57 +0100
|
||||
Subject: [PATCH] hw/acpi: Update CPUs AML with cpu-(ctrl)dev change
|
||||
|
||||
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch is based on
|
||||
PCI and is IO port based and hence existing cpus AML code assumes _CRS objects
|
||||
would evaluate to a system resource which describes IO Port address. But on ARM
|
||||
arch CPUs control device(\\_SB.PRES) register interface is memory-mapped hence
|
||||
_CRS object should evaluate to system resource which describes memory-mapped
|
||||
base address.
|
||||
|
||||
This cpus AML code change updates the existing inerface of the build cpus AML
|
||||
function to accept both IO/MEMORY type regions and update the _CRS object
|
||||
correspondingly.
|
||||
|
||||
NOTE: Beside above CPU scan shall be triggered when OSPM evaluates _EVT method
|
||||
part of the GED framework which is covered in subsequent patch.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 23 ++++++++++++++++-------
|
||||
hw/i386/acpi-build.c | 3 ++-
|
||||
include/hw/acpi/cpu.h | 5 +++--
|
||||
3 files changed, 21 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index cabeb4e86b..cf0c7e8538 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -342,9 +342,10 @@ const VMStateDescription vmstate_cpu_hotplug = {
|
||||
#define CPU_FW_EJECT_EVENT "CEJF"
|
||||
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
- build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
|
||||
+ build_madt_cpu_fn build_madt_cpu, hwaddr base_addr,
|
||||
const char *res_root,
|
||||
- const char *event_handler_method)
|
||||
+ const char *event_handler_method,
|
||||
+ AmlRegionSpace rs)
|
||||
{
|
||||
Aml *ifctx;
|
||||
Aml *field;
|
||||
@@ -369,13 +370,19 @@ 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,
|
||||
+ if (rs == AML_SYSTEM_IO) {
|
||||
+ aml_append(crs, aml_io(AML_DECODE16, base_addr, base_addr, 1,
|
||||
ACPI_CPU_HOTPLUG_REG_LEN));
|
||||
+ } else {
|
||||
+ aml_append(crs, aml_memory32_fixed(base_addr,
|
||||
+ 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(base_addr),
|
||||
ACPI_CPU_HOTPLUG_REG_LEN));
|
||||
|
||||
field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
|
||||
@@ -699,9 +706,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 80db183b78..db4ca8a66a 100644
|
||||
--- a/hw/i386/acpi-build.c
|
||||
+++ b/hw/i386/acpi-build.c
|
||||
@@ -1546,7 +1546,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
.fw_unplugs_cpu = pm->smi_on_cpu_unplug,
|
||||
};
|
||||
build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
|
||||
- pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02");
|
||||
+ pm->cpu_hp_io_base, "\\_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 209e1773f8..76bc7eb251 100644
|
||||
--- a/include/hw/acpi/cpu.h
|
||||
+++ b/include/hw/acpi/cpu.h
|
||||
@@ -60,9 +60,10 @@ typedef void (*build_madt_cpu_fn)(int uid, const CPUArchIdList *apic_ids,
|
||||
GArray *entry, bool force_enabled);
|
||||
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
- build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
|
||||
+ build_madt_cpu_fn build_madt_cpu, hwaddr base_addr,
|
||||
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.27.0
|
||||
|
||||
53
hw-acpi-Update-GED-_EVT-method-AML-with-cpu-scan.patch
Normal file
53
hw-acpi-Update-GED-_EVT-method-AML-with-cpu-scan.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From cfdb0f24431ae0f5115f905a1411509c01a50e88 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 9 Jun 2020 00:50:36 +0100
|
||||
Subject: [PATCH] hw/acpi: Update GED _EVT method AML with cpu scan
|
||||
|
||||
OSPM evaluates _EVT method to map the event. The cpu hotplug event eventually
|
||||
results in start of the cpu scan. Scan figures out the cpu and the kind of
|
||||
event(plug/unplug) and notifies it back to the guest.
|
||||
|
||||
The change in this patch updates the GED AML _EVT method with the call to
|
||||
\\_SB.CPUS.CSCN which will do above.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 4 ++++
|
||||
include/hw/acpi/cpu_hotplug.h | 2 ++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index b84602b238..ad252e6a91 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -108,6 +108,10 @@ 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_CPU_HOTPLUG_EVT:
|
||||
+ aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "."
|
||||
+ ACPI_CPU_SCAN_METHOD));
|
||||
+ break;
|
||||
case ACPI_GED_PWR_DOWN_EVT:
|
||||
aml_append(if_ctx,
|
||||
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
||||
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
|
||||
index 48b291e45e..ef631750b4 100644
|
||||
--- a/include/hw/acpi/cpu_hotplug.h
|
||||
+++ b/include/hw/acpi/cpu_hotplug.h
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "hw/acpi/cpu.h"
|
||||
|
||||
#define ACPI_CPU_HOTPLUG_REG_LEN 12
|
||||
+#define ACPI_CPU_SCAN_METHOD "CSCN"
|
||||
+#define ACPI_CPU_CONTAINER "\\_SB.CPUS"
|
||||
|
||||
typedef struct AcpiCpuHotplug {
|
||||
Object *device;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
37
hw-acpi-Use-qemu_present_cpu-API-in-ACPI-CPU-hotplug.patch
Normal file
37
hw-acpi-Use-qemu_present_cpu-API-in-ACPI-CPU-hotplug.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 576a2a88625978f1befde11f0823f32bbc54cad1 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Mon, 28 Aug 2023 20:00:08 +0000
|
||||
Subject: [PATCH] hw/acpi: Use qemu_present_cpu() API in ACPI CPU hotplug init
|
||||
|
||||
ACPI CPU Hotplug code assumes a virtual CPU is unplugged if the CPUState object
|
||||
is absent in the list of ths possible CPUs(CPUArchIdList *possible_cpus)
|
||||
maintained on per-machine basis. Use the earlier introduced qemu_present_cpu()
|
||||
API to check this state.
|
||||
|
||||
This change should have no bearing on the functionality of any architecture and
|
||||
is mere a representational change.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/acpi/cpu.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index 4b24a25003..cabeb4e86b 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -226,7 +226,10 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
||||
state->dev_count = id_list->len;
|
||||
state->devs = g_new0(typeof(*state->devs), state->dev_count);
|
||||
for (i = 0; i < id_list->len; i++) {
|
||||
- state->devs[i].cpu = CPU(id_list->cpus[i].cpu);
|
||||
+ struct CPUState *cpu = CPU(id_list->cpus[i].cpu);
|
||||
+ if (qemu_present_cpu(cpu)) {
|
||||
+ state->devs[i].cpu = cpu;
|
||||
+ }
|
||||
state->devs[i].arch_id = id_list->cpus[i].arch_id;
|
||||
}
|
||||
memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
111
hw-arm-Changes-required-for-reset-and-to-support-nex.patch
Normal file
111
hw-arm-Changes-required-for-reset-and-to-support-nex.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From 3e5f043c493fa4765c5637bec66be2bd620bc53f Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 9 May 2020 18:10:24 +0100
|
||||
Subject: [PATCH] hw/arm: Changes required for reset and to support next boot
|
||||
|
||||
Updates the firmware config with the next boot cpus information and also
|
||||
registers the reset callback to be called when guest reboots to reset the cpu.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/boot.c | 2 +-
|
||||
hw/arm/virt.c | 18 +++++++++++++++---
|
||||
include/hw/arm/boot.h | 2 ++
|
||||
include/hw/arm/virt.h | 1 +
|
||||
4 files changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
|
||||
index d1671e1d42..345c7cfa19 100644
|
||||
--- a/hw/arm/boot.c
|
||||
+++ b/hw/arm/boot.c
|
||||
@@ -683,7 +683,7 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static void do_cpu_reset(void *opaque)
|
||||
+void do_cpu_reset(void *opaque)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 60cd560ab9..eedff8e525 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/runstate.h"
|
||||
+#include "sysemu/reset.h"
|
||||
+#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tpm.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/kvm.h"
|
||||
@@ -1453,7 +1455,7 @@ static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
|
||||
char *nodename;
|
||||
|
||||
fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16, as);
|
||||
- fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
|
||||
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
|
||||
|
||||
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
@@ -3276,7 +3278,13 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
- /* TODO: register cpu for reset & update F/W info for the next boot */
|
||||
+ /* register this cpu for reset & update F/W info for the next boot */
|
||||
+ qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
|
||||
+ }
|
||||
+
|
||||
+ vms->boot_cpus++;
|
||||
+ if (vms->fw_cfg) {
|
||||
+ fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
|
||||
}
|
||||
|
||||
cs->disabled = false;
|
||||
@@ -3351,7 +3359,11 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
unwire_gic_cpu_irqs(vms, cs);
|
||||
virt_update_gic(vms, cs);
|
||||
|
||||
- /* TODO: unregister cpu for reset & update F/W info for the next boot */
|
||||
+ qemu_unregister_reset(do_cpu_reset, ARM_CPU(cs));
|
||||
+ vms->boot_cpus--;
|
||||
+ if (vms->fw_cfg) {
|
||||
+ fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
|
||||
+ }
|
||||
|
||||
qobject_unref(dev->opts);
|
||||
dev->opts = NULL;
|
||||
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
|
||||
index 80c492d742..f81326a1dc 100644
|
||||
--- a/include/hw/arm/boot.h
|
||||
+++ b/include/hw/arm/boot.h
|
||||
@@ -178,6 +178,8 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
|
||||
int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
||||
hwaddr addr_limit, AddressSpace *as, MachineState *ms);
|
||||
|
||||
+void do_cpu_reset(void *opaque);
|
||||
+
|
||||
/* Write a secure board setup routine with a dummy handler for SMCs */
|
||||
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info,
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index 069c9f2a09..ae0f5beb26 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -167,6 +167,7 @@ struct VirtMachineState {
|
||||
MemMapEntry *memmap;
|
||||
char *pciehb_nodename;
|
||||
const int *irqmap;
|
||||
+ uint16_t boot_cpus;
|
||||
int fdt_size;
|
||||
uint32_t clock_phandle;
|
||||
uint32_t gic_phandle;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
98
hw-arm-MADT-Tbl-change-to-size-the-guest-with-possib.patch
Normal file
98
hw-arm-MADT-Tbl-change-to-size-the-guest-with-possib.patch
Normal file
@ -0,0 +1,98 @@
|
||||
From 8e1b8d624128523654786953b381557c82654a57 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Wed, 6 May 2020 18:03:11 +0100
|
||||
Subject: [PATCH] hw/arm: MADT Tbl change to size the guest with possible vCPUs
|
||||
|
||||
Changes required during building of MADT Table by QEMU to accomodate disabled
|
||||
possible vCPUs. This info shall be used by the guest kernel to size up its
|
||||
resources during boot time. This pre-sizing of the guest kernel done on
|
||||
possible vCPUs will facilitate hotplug of the disabled vCPUs.
|
||||
|
||||
This change also caters ACPI MADT GIC CPU Interface flag related changes
|
||||
recently introduced in the UEFI ACPI 6.5 Specification which allows deferred
|
||||
virtual CPU online'ing in the Guest Kernel.
|
||||
|
||||
Link: https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#gic-cpu-interface-gicc-structure
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 36 ++++++++++++++++++++++++++++++------
|
||||
1 file changed, 30 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index d88f3cded1..2870c1ec5a 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -779,6 +779,29 @@ static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
|
||||
build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
|
||||
}
|
||||
|
||||
+static uint32_t virt_acpi_get_gicc_flags(CPUState *cpu)
|
||||
+{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
+
|
||||
+ /* can only exist in 'enabled' state */
|
||||
+ if (!mc->has_hotpluggable_cpus) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * ARM GIC CPU Interface can be 'online-capable' or 'enabled' at boot
|
||||
+ * We MUST set 'online-capable' Bit for all hotpluggable CPUs except the
|
||||
+ * first/boot CPU. Cold-booted CPUs without 'Id' can also be unplugged.
|
||||
+ * Though as-of-now this is only used as a debugging feature.
|
||||
+ *
|
||||
+ * UEFI ACPI Specification 6.5
|
||||
+ * Section: 5.2.12.14. GIC CPU Interface (GICC) Structure
|
||||
+ * Table: 5.37 GICC CPU Interface Flags
|
||||
+ * Link: https://uefi.org/specs/ACPI/6.5
|
||||
+ */
|
||||
+ return cpu && !cpu->cpu_index ? 1 : (1 << 3);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
@@ -805,12 +828,13 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_append_int_noprefix(table_data, vms->gic_version, 1);
|
||||
build_append_int_noprefix(table_data, 0, 3); /* Reserved */
|
||||
|
||||
- for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
|
||||
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
|
||||
+ for (i = 0; i < MACHINE(vms)->smp.max_cpus; i++) {
|
||||
+ CPUState *cpu = qemu_get_possible_cpu(i);
|
||||
uint64_t physical_base_address = 0, gich = 0, gicv = 0;
|
||||
uint32_t vgic_interrupt = vms->virt ? ARCH_GIC_MAINT_IRQ : 0;
|
||||
- uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
|
||||
- VIRTUAL_PMU_IRQ : 0;
|
||||
+ uint32_t pmu_interrupt = vms->pmu ? VIRTUAL_PMU_IRQ : 0;
|
||||
+ uint32_t flags = virt_acpi_get_gicc_flags(cpu);
|
||||
+ uint64_t mpidr = qemu_get_cpu_archid(i);
|
||||
|
||||
if (vms->gic_version == VIRT_GIC_VERSION_2) {
|
||||
physical_base_address = memmap[VIRT_GIC_CPU].base;
|
||||
@@ -825,7 +849,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_append_int_noprefix(table_data, i, 4); /* GIC ID */
|
||||
build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
|
||||
/* Flags */
|
||||
- build_append_int_noprefix(table_data, 1, 4); /* Enabled */
|
||||
+ build_append_int_noprefix(table_data, flags, 4);
|
||||
/* Parking Protocol Version */
|
||||
build_append_int_noprefix(table_data, 0, 4);
|
||||
/* Performance Interrupt GSIV */
|
||||
@@ -839,7 +863,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_append_int_noprefix(table_data, vgic_interrupt, 4);
|
||||
build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/
|
||||
/* MPIDR */
|
||||
- build_append_int_noprefix(table_data, armcpu->mp_affinity, 8);
|
||||
+ build_append_int_noprefix(table_data, mpidr, 8);
|
||||
/* Processor Power Efficiency Class */
|
||||
build_append_int_noprefix(table_data, 0, 1);
|
||||
/* Reserved */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
128
hw-arm-Support-hotplug-capability-check-using-_OSC-m.patch
Normal file
128
hw-arm-Support-hotplug-capability-check-using-_OSC-m.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From c5dfec0bfd78f7e8f84a527a1aa73896f69b2367 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Thu, 10 Aug 2023 01:15:31 +0000
|
||||
Subject: [PATCH] hw/arm: Support hotplug capability check using _OSC method
|
||||
|
||||
Physical CPU hotplug results in (un)setting of ACPI _STA.Present bit. AARCH64
|
||||
platforms do not support physical CPU hotplug. Virtual CPU hotplug support being
|
||||
implemented toggles ACPI _STA.Enabled Bit to achieve hotplug functionality. This
|
||||
is not same as physical CPU hotplug support.
|
||||
|
||||
In future, if ARM architecture supports physical CPU hotplug then the current
|
||||
design of virtual CPU hotplug can be used unchanged. Hence, there is a need for
|
||||
firmware/VMM/Qemu to support evaluation of platform wide capabilitiy related to
|
||||
the *type* of CPU hotplug support present on the platform. OSPM might need this
|
||||
during boot time to correctly initialize the CPUs and other related components
|
||||
in the kernel.
|
||||
|
||||
NOTE: This implementation will be improved to add the support of *query* in the
|
||||
subsequent versions. This is very minimal support to assist kernel.
|
||||
|
||||
ASL for the implemented _OSC method:
|
||||
|
||||
Method (_OSC, 4, NotSerialized) // _OSC: Operating System Capabilities
|
||||
{
|
||||
CreateDWordField (Arg3, Zero, CDW1)
|
||||
If ((Arg0 == ToUUID ("0811b06e-4a27-44f9-8d60-3cbbc22e7b48") /* Platform-wide Capabilities */))
|
||||
{
|
||||
CreateDWordField (Arg3, 0x04, CDW2)
|
||||
Local0 = CDW2 /* \_SB_._OSC.CDW2 */
|
||||
If ((Arg1 != One))
|
||||
{
|
||||
CDW1 |= 0x08
|
||||
}
|
||||
|
||||
Local0 &= 0x00800000
|
||||
If ((CDW2 != Local0))
|
||||
{
|
||||
CDW1 |= 0x10
|
||||
}
|
||||
|
||||
CDW2 = Local0
|
||||
}
|
||||
Else
|
||||
{
|
||||
CDW1 |= 0x04
|
||||
}
|
||||
|
||||
Return (Arg3)
|
||||
}
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 52 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 52 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 2870c1ec5a..c402e102c4 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -940,6 +940,55 @@ static void build_fadt_rev6(GArray *table_data, BIOSLinker *linker,
|
||||
build_fadt(table_data, linker, &fadt, vms->oem_id, vms->oem_table_id);
|
||||
}
|
||||
|
||||
+static void build_virt_osc_method(Aml *scope, VirtMachineState *vms)
|
||||
+{
|
||||
+ Aml *if_uuid, *else_uuid, *if_rev, *if_caps_masked, *method;
|
||||
+ Aml *a_cdw1 = aml_name("CDW1");
|
||||
+ Aml *a_cdw2 = aml_local(0);
|
||||
+
|
||||
+ method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
|
||||
+ aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
|
||||
+
|
||||
+ /* match UUID */
|
||||
+ if_uuid = aml_if(aml_equal(
|
||||
+ aml_arg(0), aml_touuid("0811B06E-4A27-44F9-8D60-3CBBC22E7B48")));
|
||||
+
|
||||
+ aml_append(if_uuid, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
|
||||
+ aml_append(if_uuid, aml_store(aml_name("CDW2"), a_cdw2));
|
||||
+
|
||||
+ /* check unknown revision in arg(1) */
|
||||
+ if_rev = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
|
||||
+ /* set revision error bits, DWORD1 Bit[3] */
|
||||
+ aml_append(if_rev, aml_or(a_cdw1, aml_int(0x08), a_cdw1));
|
||||
+ aml_append(if_uuid, if_rev);
|
||||
+
|
||||
+ /*
|
||||
+ * check support for vCPU hotplug type(=enabled) platform-wide capability
|
||||
+ * in DWORD2 as sepcified in the below ACPI Specification ECR,
|
||||
+ * # https://bugzilla.tianocore.org/show_bug.cgi?id=4481
|
||||
+ */
|
||||
+ if (vms->acpi_dev) {
|
||||
+ aml_append(if_uuid, aml_and(a_cdw2, aml_int(0x800000), a_cdw2));
|
||||
+ /* check if OSPM specified hotplug capability bits were masked */
|
||||
+ if_caps_masked = aml_if(aml_lnot(aml_equal(aml_name("CDW2"), a_cdw2)));
|
||||
+ aml_append(if_caps_masked, aml_or(a_cdw1, aml_int(0x10), a_cdw1));
|
||||
+ aml_append(if_uuid, if_caps_masked);
|
||||
+ }
|
||||
+ aml_append(if_uuid, aml_store(a_cdw2, aml_name("CDW2")));
|
||||
+
|
||||
+ aml_append(method, if_uuid);
|
||||
+ else_uuid = aml_else();
|
||||
+
|
||||
+ /* set unrecognized UUID error bits, DWORD1 Bit[2] */
|
||||
+ aml_append(else_uuid, aml_or(a_cdw1, aml_int(4), a_cdw1));
|
||||
+ aml_append(method, else_uuid);
|
||||
+
|
||||
+ aml_append(method, aml_return(aml_arg(3)));
|
||||
+ aml_append(scope, method);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
/* DSDT */
|
||||
static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
@@ -974,6 +1023,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
} else {
|
||||
acpi_dsdt_add_cpus(scope, vms);
|
||||
}
|
||||
+
|
||||
+ build_virt_osc_method(scope, vms);
|
||||
+
|
||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
||||
if (vmc->acpi_expose_flash) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
267
hw-arm-gicv3-Changes-to-update-GIC-with-vCPU-hot-plu.patch
Normal file
267
hw-arm-gicv3-Changes-to-update-GIC-with-vCPU-hot-plu.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From 8ad397f33f8b7d82c0ef72608ef8dc3e0ecba1c2 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 9 May 2020 14:38:38 +0100
|
||||
Subject: [PATCH] hw/arm,gicv3: Changes to update GIC with vCPU hot-plug
|
||||
notification
|
||||
|
||||
vCPU hot-(un)plug events MUST be notified to the GIC. Introduce a notfication
|
||||
mechanism to update any such events to GIC so that it can update its vCPU to GIC
|
||||
CPU interface association.
|
||||
|
||||
This is required to implement a workaround to the limitations posed by the ARM
|
||||
architecture. For details about the constraints and workarounds please check
|
||||
below slides:
|
||||
|
||||
Link: https://kvm-forum.qemu.org/2023/talk/9SMPDQ/
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 27 +++++++++++++--
|
||||
hw/intc/arm_gicv3_common.c | 54 +++++++++++++++++++++++++++++-
|
||||
hw/intc/arm_gicv3_cpuif_common.c | 5 +++
|
||||
hw/intc/gicv3_internal.h | 1 +
|
||||
include/hw/arm/virt.h | 1 +
|
||||
include/hw/intc/arm_gicv3_common.h | 22 ++++++++++++
|
||||
6 files changed, 107 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 97bf4cca11..0312fa366d 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -750,6 +750,16 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
return dev;
|
||||
}
|
||||
|
||||
+static void virt_add_gic_cpuhp_notifier(VirtMachineState *vms)
|
||||
+{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(vms);
|
||||
+
|
||||
+ if (mc->has_hotpluggable_cpus) {
|
||||
+ Notifier *cpuhp_notifier = gicv3_cpuhp_notifier(vms->gic);
|
||||
+ notifier_list_add(&vms->cpuhp_notifiers, cpuhp_notifier);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void create_its(VirtMachineState *vms)
|
||||
{
|
||||
const char *itsclass = its_class_name();
|
||||
@@ -997,6 +1007,9 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
|
||||
} else if (vms->gic_version == VIRT_GIC_VERSION_2) {
|
||||
create_v2m(vms);
|
||||
}
|
||||
+
|
||||
+ /* add GIC CPU hot(un)plug update notifier */
|
||||
+ virt_add_gic_cpuhp_notifier(vms);
|
||||
}
|
||||
|
||||
static void create_uart(const VirtMachineState *vms, int uart,
|
||||
@@ -2481,6 +2494,8 @@ static void machvirt_init(MachineState *machine)
|
||||
create_fdt(vms);
|
||||
qemu_log("cpu init start\n");
|
||||
|
||||
+ notifier_list_init(&vms->cpuhp_notifiers);
|
||||
+ possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
assert(possible_cpus->len == max_cpus);
|
||||
for (n = 0; n < possible_cpus->len; n++) {
|
||||
Object *cpuobj;
|
||||
@@ -3133,6 +3148,14 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
|
||||
dev, &error_abort);
|
||||
}
|
||||
|
||||
+static void virt_update_gic(VirtMachineState *vms, CPUState *cs)
|
||||
+{
|
||||
+ GICv3CPUHotplugInfo gic_info = { .gic = vms->gic, .cpu = cs };
|
||||
+
|
||||
+ /* notify gic to stitch GICC to this new cpu */
|
||||
+ notifier_list_notify(&vms->cpuhp_notifiers, &gic_info);
|
||||
+}
|
||||
+
|
||||
static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -3215,7 +3238,7 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
* vCPUs have their GIC state initialized during machvit_init().
|
||||
*/
|
||||
if (vms->acpi_dev) {
|
||||
- /* TODO: update GIC about this hotplug change here */
|
||||
+ virt_update_gic(vms, cs);
|
||||
wire_gic_cpu_irqs(vms, cs);
|
||||
}
|
||||
|
||||
@@ -3301,7 +3324,7 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
/* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
|
||||
|
||||
unwire_gic_cpu_irqs(vms, cs);
|
||||
- /* TODO: update the GIC about this hot unplug change */
|
||||
+ virt_update_gic(vms, cs);
|
||||
|
||||
/* TODO: unregister cpu for reset & update F/W info for the next boot */
|
||||
|
||||
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
|
||||
index ebd99af610..fc87fa9369 100644
|
||||
--- a/hw/intc/arm_gicv3_common.c
|
||||
+++ b/hw/intc/arm_gicv3_common.c
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "hw/arm/linux-boot-if.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
-
|
||||
static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs)
|
||||
{
|
||||
if (cs->gicd_no_migration_shift_bug) {
|
||||
@@ -322,6 +321,56 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
|
||||
}
|
||||
}
|
||||
|
||||
+static int arm_gicv3_get_proc_num(GICv3State *s, CPUState *cpu)
|
||||
+{
|
||||
+ uint64_t mp_affinity;
|
||||
+ uint64_t gicr_typer;
|
||||
+ uint64_t cpu_affid;
|
||||
+ int i;
|
||||
+
|
||||
+ mp_affinity = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
|
||||
+ /* match the cpu mp-affinity to get the gic cpuif number */
|
||||
+ for (i = 0; i < s->num_cpu; i++) {
|
||||
+ gicr_typer = s->cpu[i].gicr_typer;
|
||||
+ cpu_affid = (gicr_typer >> 32) & 0xFFFFFF;
|
||||
+ if (cpu_affid == mp_affinity) {
|
||||
+ return i;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static void arm_gicv3_cpu_update_notifier(Notifier *notifier, void * data)
|
||||
+{
|
||||
+ GICv3CPUHotplugInfo *gic_info = (GICv3CPUHotplugInfo *)data;
|
||||
+ CPUState *cpu = gic_info->cpu;
|
||||
+ int gic_cpuif_num;
|
||||
+ GICv3State *s;
|
||||
+
|
||||
+ s = ARM_GICV3_COMMON(gic_info->gic);
|
||||
+
|
||||
+ /* this shall get us mapped gicv3 cpuif corresponding to mpidr */
|
||||
+ gic_cpuif_num = arm_gicv3_get_proc_num(s, cpu);
|
||||
+ if (gic_cpuif_num < 0) {
|
||||
+ error_report("Failed to associate cpu %d with any GIC cpuif",
|
||||
+ cpu->cpu_index);
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ /* check if update is for vcpu hot-unplug */
|
||||
+ if (qemu_enabled_cpu(cpu)) {
|
||||
+ s->cpu[gic_cpuif_num].cpu = NULL;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* re-stitch the gic cpuif to this new cpu */
|
||||
+ gicv3_set_gicv3state(cpu, &s->cpu[gic_cpuif_num]);
|
||||
+ gicv3_set_cpustate(&s->cpu[gic_cpuif_num], cpu);
|
||||
+
|
||||
+ /* TODO: initialize the registers info for this newly added cpu */
|
||||
+}
|
||||
+
|
||||
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
GICv3State *s = ARM_GICV3_COMMON(dev);
|
||||
@@ -444,6 +493,8 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
s->cpu[cpuidx - 1].gicr_typer |= GICR_TYPER_LAST;
|
||||
}
|
||||
|
||||
+ s->cpu_update_notifier.notify = arm_gicv3_cpu_update_notifier;
|
||||
+
|
||||
s->itslist = g_ptr_array_new();
|
||||
}
|
||||
|
||||
@@ -451,6 +502,7 @@ static void arm_gicv3_finalize(Object *obj)
|
||||
{
|
||||
GICv3State *s = ARM_GICV3_COMMON(obj);
|
||||
|
||||
+ notifier_remove(&s->cpu_update_notifier);
|
||||
g_free(s->redist_region_count);
|
||||
}
|
||||
|
||||
diff --git a/hw/intc/arm_gicv3_cpuif_common.c b/hw/intc/arm_gicv3_cpuif_common.c
|
||||
index ff1239f65d..381cf2754b 100644
|
||||
--- a/hw/intc/arm_gicv3_cpuif_common.c
|
||||
+++ b/hw/intc/arm_gicv3_cpuif_common.c
|
||||
@@ -20,3 +20,8 @@ void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
|
||||
|
||||
env->gicv3state = (void *)s;
|
||||
};
|
||||
+
|
||||
+void gicv3_set_cpustate(GICv3CPUState *s, CPUState *cpu)
|
||||
+{
|
||||
+ s->cpu = cpu;
|
||||
+}
|
||||
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
|
||||
index 29d5cdc1b6..9d4c1209bd 100644
|
||||
--- a/hw/intc/gicv3_internal.h
|
||||
+++ b/hw/intc/gicv3_internal.h
|
||||
@@ -848,5 +848,6 @@ static inline void gicv3_cache_all_target_cpustates(GICv3State *s)
|
||||
}
|
||||
|
||||
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s);
|
||||
+void gicv3_set_cpustate(GICv3CPUState *s, CPUState *cpu);
|
||||
|
||||
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index 5de0185063..069c9f2a09 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -180,6 +180,7 @@ struct VirtMachineState {
|
||||
PCIBus *bus;
|
||||
char *oem_id;
|
||||
char *oem_table_id;
|
||||
+ NotifierList cpuhp_notifiers;
|
||||
};
|
||||
|
||||
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
|
||||
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
|
||||
index 4e2fb518e7..97a48f44b9 100644
|
||||
--- a/include/hw/intc/arm_gicv3_common.h
|
||||
+++ b/include/hw/intc/arm_gicv3_common.h
|
||||
@@ -280,6 +280,7 @@ struct GICv3State {
|
||||
GICv3CPUState *gicd_irouter_target[GICV3_MAXIRQ];
|
||||
uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)];
|
||||
|
||||
+ Notifier cpu_update_notifier;
|
||||
GICv3CPUState *cpu;
|
||||
/* List of all ITSes connected to this GIC */
|
||||
GPtrArray *itslist;
|
||||
@@ -328,6 +329,27 @@ struct ARMGICv3CommonClass {
|
||||
|
||||
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
|
||||
const MemoryRegionOps *ops);
|
||||
+/**
|
||||
+ * Structure used by GICv3 CPU hotplug notifier
|
||||
+ */
|
||||
+typedef struct GICv3CPUHotplugInfo {
|
||||
+ DeviceState *gic; /* GICv3State */
|
||||
+ CPUState *cpu;
|
||||
+} GICv3CPUHotplugInfo;
|
||||
+
|
||||
+/**
|
||||
+ * gicv3_cpuhp_notifier
|
||||
+ *
|
||||
+ * Returns CPU hotplug notifier which could be used to update GIC about any
|
||||
+ * CPU hot(un)plug events.
|
||||
+ *
|
||||
+ * Returns: Notifier initialized with CPU Hot(un)plug update function
|
||||
+ */
|
||||
+static inline Notifier *gicv3_cpuhp_notifier(DeviceState *dev)
|
||||
+{
|
||||
+ GICv3State *s = ARM_GICV3_COMMON(dev);
|
||||
+ return &s->cpu_update_notifier;
|
||||
+}
|
||||
|
||||
/**
|
||||
* gicv3_class_name
|
||||
--
|
||||
2.27.0
|
||||
|
||||
107
hw-arm-virt-Expose-cold-booted-CPUs-as-MADT-GICC-Ena.patch
Normal file
107
hw-arm-virt-Expose-cold-booted-CPUs-as-MADT-GICC-Ena.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 837b04877be49b930a2d437f55e2ae15ff820421 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 23 Sep 2023 22:31:49 +0000
|
||||
Subject: [PATCH] hw/arm/virt: Expose cold-booted CPUs as MADT GICC Enabled
|
||||
|
||||
Hotpluggable CPUs MUST be exposed as 'online-capable' as per the new change. But
|
||||
cold booted CPUs if made 'online-capable' during boot time might not get
|
||||
detected in the legacy OS. Hence, can cause compatibility problems.
|
||||
|
||||
Original Change Link: https://bugzilla.tianocore.org/show_bug.cgi?id=3706
|
||||
|
||||
Specification change might take time and hence disabling the support of
|
||||
unplugging any cold booted CPUs to preserve the compatibility with legacy OS.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt-acpi-build.c | 19 ++++++++++++++-----
|
||||
hw/arm/virt.c | 16 ++++++++++++++++
|
||||
include/hw/core/cpu.h | 2 ++
|
||||
3 files changed, 32 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index c402e102c4..590afcfa98 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -789,17 +789,26 @@ static uint32_t virt_acpi_get_gicc_flags(CPUState *cpu)
|
||||
}
|
||||
|
||||
/*
|
||||
- * ARM GIC CPU Interface can be 'online-capable' or 'enabled' at boot
|
||||
- * We MUST set 'online-capable' Bit for all hotpluggable CPUs except the
|
||||
- * first/boot CPU. Cold-booted CPUs without 'Id' can also be unplugged.
|
||||
- * Though as-of-now this is only used as a debugging feature.
|
||||
+ * ARM GIC CPU Interface can be 'online-capable' or 'enabled' at boot. We
|
||||
+ * MUST set 'online-capable' bit for all hotpluggable CPUs.
|
||||
+ * Change Link: https://bugzilla.tianocore.org/show_bug.cgi?id=3706
|
||||
*
|
||||
* UEFI ACPI Specification 6.5
|
||||
* Section: 5.2.12.14. GIC CPU Interface (GICC) Structure
|
||||
* Table: 5.37 GICC CPU Interface Flags
|
||||
* Link: https://uefi.org/specs/ACPI/6.5
|
||||
+ *
|
||||
+ * Cold-booted CPUs, except for the first/boot CPU, SHOULD be allowed to be
|
||||
+ * hot(un)plug as well but for this to happen these MUST have
|
||||
+ * 'online-capable' bit set. Later creates compatibility problem with legacy
|
||||
+ * OS as it might ignore online-capable' bits during boot time and hence
|
||||
+ * some CPUs might not get detected. To fix this MADT GIC CPU interface flag
|
||||
+ * should be allowed to have both bits set i.e. 'online-capable' and
|
||||
+ * 'Enabled' bits together. This change will require UEFI ACPI standard
|
||||
+ * change. Till this happens exposing all cold-booted CPUs as 'enabled' only
|
||||
+ *
|
||||
*/
|
||||
- return cpu && !cpu->cpu_index ? 1 : (1 << 3);
|
||||
+ return cpu && cpu->cold_booted ? 1 : (1 << 3);
|
||||
}
|
||||
|
||||
static void
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index eedff8e525..ed437ce0e8 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3250,6 +3250,10 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
* This shall be used during the init of ACPI Hotplug state and hot-unplug
|
||||
*/
|
||||
cs->acpi_persistent = true;
|
||||
+
|
||||
+ if (!dev->hotplugged) {
|
||||
+ cs->cold_booted = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
@@ -3313,6 +3317,18 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * UEFI ACPI standard change is required to make both 'enabled' and the
|
||||
+ * 'online-capable' bit co-exist instead of being mutually exclusive.
|
||||
+ * check virt_acpi_get_gicc_flags() for more details.
|
||||
+ *
|
||||
+ * Disable the unplugging of cold-booted vCPUs as a temporary mitigation.
|
||||
+ */
|
||||
+ if (cs->cold_booted) {
|
||||
+ error_setg(errp, "Hot-unplug of cold-booted CPU not supported!");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (cs->cpu_index == first_cpu->cpu_index) {
|
||||
error_setg(errp, "Boot CPU(id%d=%d:%d:%d:%d) hot-unplug not supported",
|
||||
first_cpu->cpu_index, cpu->socket_id, cpu->cluster_id,
|
||||
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
||||
index 6dbe163548..ee04ee44c2 100644
|
||||
--- a/include/hw/core/cpu.h
|
||||
+++ b/include/hw/core/cpu.h
|
||||
@@ -565,6 +565,8 @@ struct CPUState {
|
||||
uint32_t halted;
|
||||
int32_t exception_index;
|
||||
|
||||
+ bool cold_booted;
|
||||
+
|
||||
AccelCPUState *accel;
|
||||
/* shared by kvm and hvf */
|
||||
bool vcpu_dirty;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
311
hw-arm-virt-Move-setting-of-common-CPU-properties-in.patch
Normal file
311
hw-arm-virt-Move-setting-of-common-CPU-properties-in.patch
Normal file
@ -0,0 +1,311 @@
|
||||
From 8daa90ad502b79e232377f831f67df456a743304 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 26 Aug 2023 01:29:37 +0000
|
||||
Subject: [PATCH] hw/arm/virt: Move setting of common CPU properties in a
|
||||
function
|
||||
|
||||
Factor out CPU properties code common for {hot,cold}-plugged CPUs. This allows
|
||||
code reuse.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/arm/virt.c | 220 ++++++++++++++++++++++++++----------------
|
||||
include/hw/arm/virt.h | 4 +
|
||||
2 files changed, 140 insertions(+), 84 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 94481d45d4..8f647422d8 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -2113,16 +2113,130 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
}
|
||||
}
|
||||
|
||||
+static void virt_cpu_set_properties(Object *cpuobj, const CPUArchId *cpu_slot,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(ms);
|
||||
+ Error *local_err = NULL;
|
||||
+ VirtMachineClass *vmc;
|
||||
+
|
||||
+ vmc = VIRT_MACHINE_GET_CLASS(ms);
|
||||
+
|
||||
+ /* now, set the cpu object property values */
|
||||
+ numa_cpu_pre_plug(cpu_slot, DEVICE(cpuobj), &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ object_property_set_int(cpuobj, "mp-affinity", cpu_slot->arch_id, NULL);
|
||||
+
|
||||
+ if (!vms->secure) {
|
||||
+ object_property_set_bool(cpuobj, "has_el3", false, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (!vms->virt && object_property_find(cpuobj, "has_el2")) {
|
||||
+ object_property_set_bool(cpuobj, "has_el2", false, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (vmc->kvm_no_adjvtime &&
|
||||
+ object_property_find(cpuobj, "kvm-no-adjvtime")) {
|
||||
+ object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (vmc->no_kvm_steal_time &&
|
||||
+ object_property_find(cpuobj, "kvm-steal-time")) {
|
||||
+ object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) {
|
||||
+ object_property_set_bool(cpuobj, "pmu", false, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) {
|
||||
+ object_property_set_bool(cpuobj, "lpa2", false, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
+ object_property_set_int(cpuobj, "reset-cbar",
|
||||
+ vms->memmap[VIRT_CPUPERIPHS].base,
|
||||
+ &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* link already initialized {secure,tag}-memory regions to this cpu */
|
||||
+ object_property_set_link(cpuobj, "memory", OBJECT(vms->sysmem), &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (vms->secure) {
|
||||
+ object_property_set_link(cpuobj, "secure-memory",
|
||||
+ OBJECT(vms->secure_sysmem), &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (vms->mte) {
|
||||
+ if (!object_property_find(cpuobj, "tag-memory")) {
|
||||
+ error_setg(&local_err, "MTE requested, but not supported "
|
||||
+ "by the guest CPU");
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ object_property_set_link(cpuobj, "tag-memory", OBJECT(vms->tag_sysmem),
|
||||
+ &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (vms->secure) {
|
||||
+ object_property_set_link(cpuobj, "secure-tag-memory",
|
||||
+ OBJECT(vms->secure_tag_sysmem),
|
||||
+ &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * RFC: Question: this must only be called for the hotplugged cpus. For the
|
||||
+ * cold booted secondary cpus this is being taken care in arm_load_kernel()
|
||||
+ * in boot.c. Perhaps we should remove that code now?
|
||||
+ */
|
||||
+ if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
|
||||
+ object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit,
|
||||
+ NULL);
|
||||
+
|
||||
+ /* Secondary CPUs start in PSCI powered-down state */
|
||||
+ if (CPU(cpuobj)->cpu_index > 0) {
|
||||
+ object_property_set_bool(cpuobj, "start-powered-off", true, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static void machvirt_init(MachineState *machine)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
const CPUArchIdList *possible_cpus;
|
||||
- MemoryRegion *sysmem = get_system_memory();
|
||||
+ MemoryRegion *secure_tag_sysmem = NULL;
|
||||
MemoryRegion *secure_sysmem = NULL;
|
||||
MemoryRegion *tag_sysmem = NULL;
|
||||
- MemoryRegion *secure_tag_sysmem = NULL;
|
||||
+ MemoryRegion *sysmem;
|
||||
int n, virt_max_cpus;
|
||||
bool firmware_loaded;
|
||||
bool aarch64 = true;
|
||||
@@ -2166,6 +2280,8 @@ static void machvirt_init(MachineState *machine)
|
||||
*/
|
||||
finalize_gic_version(vms);
|
||||
|
||||
+ sysmem = vms->sysmem = get_system_memory();
|
||||
+
|
||||
if (vms->secure) {
|
||||
/*
|
||||
* The Secure view of the world is the same as the NonSecure,
|
||||
@@ -2173,7 +2289,7 @@ static void machvirt_init(MachineState *machine)
|
||||
* containing the system memory at low priority; any secure-only
|
||||
* devices go in at higher priority and take precedence.
|
||||
*/
|
||||
- secure_sysmem = g_new(MemoryRegion, 1);
|
||||
+ secure_sysmem = vms->secure_sysmem = g_new(MemoryRegion, 1);
|
||||
memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
|
||||
UINT64_MAX);
|
||||
memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
|
||||
@@ -2246,6 +2362,23 @@ static void machvirt_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+ if (vms->mte) {
|
||||
+ /* Create the memory region only once, but link to all cpus later */
|
||||
+ tag_sysmem = vms->tag_sysmem = g_new(MemoryRegion, 1);
|
||||
+ memory_region_init(tag_sysmem, OBJECT(machine),
|
||||
+ "tag-memory", UINT64_MAX / 32);
|
||||
+
|
||||
+ if (vms->secure) {
|
||||
+ secure_tag_sysmem = vms->secure_tag_sysmem = g_new(MemoryRegion, 1);
|
||||
+ memory_region_init(secure_tag_sysmem, OBJECT(machine),
|
||||
+ "secure-tag-memory", UINT64_MAX / 32);
|
||||
+
|
||||
+ /* As with ram, secure-tag takes precedence over tag. */
|
||||
+ memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
|
||||
+ tag_sysmem, -1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
create_fdt(vms);
|
||||
qemu_log("cpu init start\n");
|
||||
|
||||
@@ -2259,15 +2392,10 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
|
||||
cpuobj = object_new(possible_cpus->cpus[n].type);
|
||||
- object_property_set_int(cpuobj, "mp-affinity",
|
||||
- possible_cpus->cpus[n].arch_id, 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);
|
||||
object_property_set_int(cpuobj, "socket-id",
|
||||
virt_get_socket_id(machine, n), NULL);
|
||||
@@ -2278,82 +2406,6 @@ static void machvirt_init(MachineState *machine)
|
||||
object_property_set_int(cpuobj, "thread-id",
|
||||
virt_get_thread_id(machine, n), NULL);
|
||||
|
||||
- if (!vms->secure) {
|
||||
- object_property_set_bool(cpuobj, "has_el3", false, NULL);
|
||||
- }
|
||||
-
|
||||
- if (!vms->virt && object_property_find(cpuobj, "has_el2")) {
|
||||
- object_property_set_bool(cpuobj, "has_el2", false, NULL);
|
||||
- }
|
||||
-
|
||||
- if (vmc->kvm_no_adjvtime &&
|
||||
- object_property_find(cpuobj, "kvm-no-adjvtime")) {
|
||||
- object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL);
|
||||
- }
|
||||
-
|
||||
- if (vmc->no_kvm_steal_time &&
|
||||
- object_property_find(cpuobj, "kvm-steal-time")) {
|
||||
- object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL);
|
||||
- }
|
||||
-
|
||||
- if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) {
|
||||
- object_property_set_bool(cpuobj, "pmu", false, NULL);
|
||||
- }
|
||||
-
|
||||
- if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) {
|
||||
- object_property_set_bool(cpuobj, "lpa2", false, NULL);
|
||||
- }
|
||||
-
|
||||
- if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
- object_property_set_int(cpuobj, "reset-cbar",
|
||||
- vms->memmap[VIRT_CPUPERIPHS].base,
|
||||
- &error_abort);
|
||||
- }
|
||||
-
|
||||
- object_property_set_link(cpuobj, "memory", OBJECT(sysmem),
|
||||
- &error_abort);
|
||||
- if (vms->secure) {
|
||||
- object_property_set_link(cpuobj, "secure-memory",
|
||||
- OBJECT(secure_sysmem), &error_abort);
|
||||
- }
|
||||
-
|
||||
- if (vms->mte) {
|
||||
- /* Create the memory region only once, but link to all cpus. */
|
||||
- if (!tag_sysmem) {
|
||||
- /*
|
||||
- * The property exists only if MemTag is supported.
|
||||
- * If it is, we must allocate the ram to back that up.
|
||||
- */
|
||||
- if (!object_property_find(cpuobj, "tag-memory")) {
|
||||
- error_report("MTE requested, but not supported "
|
||||
- "by the guest CPU");
|
||||
- exit(1);
|
||||
- }
|
||||
-
|
||||
- tag_sysmem = g_new(MemoryRegion, 1);
|
||||
- memory_region_init(tag_sysmem, OBJECT(machine),
|
||||
- "tag-memory", UINT64_MAX / 32);
|
||||
-
|
||||
- if (vms->secure) {
|
||||
- secure_tag_sysmem = g_new(MemoryRegion, 1);
|
||||
- memory_region_init(secure_tag_sysmem, OBJECT(machine),
|
||||
- "secure-tag-memory", UINT64_MAX / 32);
|
||||
-
|
||||
- /* As with ram, secure-tag takes precedence over tag. */
|
||||
- memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
|
||||
- tag_sysmem, -1);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem),
|
||||
- &error_abort);
|
||||
- if (vms->secure) {
|
||||
- object_property_set_link(cpuobj, "secure-tag-memory",
|
||||
- OBJECT(secure_tag_sysmem),
|
||||
- &error_abort);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
||||
object_unref(cpuobj);
|
||||
}
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index e944d434c4..49d1ec8656 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -139,6 +139,10 @@ struct VirtMachineState {
|
||||
DeviceState *platform_bus_dev;
|
||||
FWCfgState *fw_cfg;
|
||||
PFlashCFI01 *flash[2];
|
||||
+ MemoryRegion *sysmem;
|
||||
+ MemoryRegion *secure_sysmem;
|
||||
+ MemoryRegion *tag_sysmem;
|
||||
+ MemoryRegion *secure_tag_sysmem;
|
||||
bool secure;
|
||||
bool highmem;
|
||||
bool highmem_compact;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
352
hw-arm64-add-vcpu-cache-info-support.patch
Normal file
352
hw-arm64-add-vcpu-cache-info-support.patch
Normal file
@ -0,0 +1,352 @@
|
||||
From 7d3d37d3af4278aee627952d6a81b63dec6ac62b Mon Sep 17 00:00:00 2001
|
||||
From: Ying Fang <fangying1@huawei.com>
|
||||
Date: Sun, 17 Mar 2024 18:56:09 +0800
|
||||
Subject: [PATCH] hw/arm64: add vcpu cache info support
|
||||
|
||||
Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache.
|
||||
|
||||
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
|
||||
Signed-off-by: Honghao <honghao5@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/acpi/aml-build.c | 158 ++++++++++++++++++++++++++++++++++++
|
||||
hw/arm/virt.c | 72 ++++++++++++++++
|
||||
include/hw/acpi/aml-build.h | 47 +++++++++++
|
||||
3 files changed, 277 insertions(+)
|
||||
|
||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
||||
index af66bde0f5..2968df5562 100644
|
||||
--- a/hw/acpi/aml-build.c
|
||||
+++ b/hw/acpi/aml-build.c
|
||||
@@ -1994,6 +1994,163 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef __aarch64__
|
||||
+/*
|
||||
+ * ACPI spec, Revision 6.3
|
||||
+ * 5.2.29.2 Cache Type Structure (Type 1)
|
||||
+ */
|
||||
+static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level,
|
||||
+ uint32_t cache_type)
|
||||
+{
|
||||
+ build_append_byte(tbl, 1);
|
||||
+ build_append_byte(tbl, 24);
|
||||
+ build_append_int_noprefix(tbl, 0, 2);
|
||||
+ build_append_int_noprefix(tbl, 127, 4);
|
||||
+ build_append_int_noprefix(tbl, next_level, 4);
|
||||
+
|
||||
+ switch (cache_type) {
|
||||
+ case ARM_L1D_CACHE: /* L1 dcache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L1I_CACHE: /* L1 icache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L2_CACHE: /* L2 cache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L3_CACHE: /* L3 cache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ default:
|
||||
+ build_append_int_noprefix(tbl, 0, 4);
|
||||
+ build_append_int_noprefix(tbl, 0, 4);
|
||||
+ build_append_byte(tbl, 0);
|
||||
+ build_append_byte(tbl, 0);
|
||||
+ build_append_int_noprefix(tbl, 0, 2);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * ACPI spec, Revision 6.3
|
||||
+ * 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
+ */
|
||||
+void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
+ const char *oem_id, const char *oem_table_id)
|
||||
+{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
+ GQueue *list = g_queue_new();
|
||||
+ guint pptt_start = table_data->len;
|
||||
+ guint parent_offset;
|
||||
+ guint length, i;
|
||||
+ int uid = 0;
|
||||
+ int socket;
|
||||
+ AcpiTable table = { .sig = "PPTT", .rev = 2,
|
||||
+ .oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
+
|
||||
+ acpi_table_begin(&table, table_data);
|
||||
+
|
||||
+ for (socket = 0; socket < ms->smp.sockets; socket++) {
|
||||
+ uint32_t l3_cache_offset = table_data->len - pptt_start;
|
||||
+ build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE);
|
||||
+
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ /*
|
||||
+ * Physical package - represents the boundary
|
||||
+ * of a physical package
|
||||
+ */
|
||||
+ (1 << 0),
|
||||
+ 0, socket, &l3_cache_offset, 1);
|
||||
+ }
|
||||
+
|
||||
+ if (mc->smp_props.clusters_supported) {
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int cluster;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (0 << 0), /* not a physical package */
|
||||
+ parent_offset, cluster, NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int core;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (core = 0; core < ms->smp.cores; core++) {
|
||||
+ uint32_t priv_rsrc[3] = {};
|
||||
+ priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */
|
||||
+ build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE);
|
||||
+
|
||||
+ priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */
|
||||
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE);
|
||||
+
|
||||
+ priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */
|
||||
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE);
|
||||
+
|
||||
+ if (ms->smp.threads > 1) {
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (0 << 0), /* not a physical package */
|
||||
+ parent_offset, core, priv_rsrc, 3);
|
||||
+ } else {
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (1 << 1) | /* ACPI Processor ID valid */
|
||||
+ (1 << 3), /* Node is a Leaf */
|
||||
+ parent_offset, uid++, priv_rsrc, 3);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int thread;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (thread = 0; thread < ms->smp.threads; thread++) {
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (1 << 1) | /* ACPI Processor ID valid */
|
||||
+ (1 << 2) | /* Processor is a Thread */
|
||||
+ (1 << 3), /* Node is a Leaf */
|
||||
+ parent_offset, uid++, NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_queue_free(list);
|
||||
+ acpi_table_end(linker, &table);
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
/*
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
@@ -2069,6 +2226,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* build rev1/rev3/rev5.1/rev6.0 FADT */
|
||||
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 500a15aa5b..b82bd1b8c8 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -379,6 +379,72 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
|
||||
INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
|
||||
}
|
||||
|
||||
+static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
|
||||
+{
|
||||
+ int i;
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads;
|
||||
+ int sockets = (ms->smp.cpus + cpus_per_socket - 1) / cpus_per_socket;
|
||||
+
|
||||
+ for (i = 0; i < sockets; i++) {
|
||||
+ char *nodename = g_strdup_printf("/cpus/l3-cache%d", i);
|
||||
+
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true");
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x2000000);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 128);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 2048);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
|
||||
+ qemu_fdt_alloc_phandle(ms->fdt));
|
||||
+ g_free(nodename);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
|
||||
+{
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads;
|
||||
+ int cpu;
|
||||
+
|
||||
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
||||
+ char *next_path = g_strdup_printf("/cpus/l3-cache%d",
|
||||
+ cpu / cpus_per_socket);
|
||||
+ char *nodename = g_strdup_printf("/cpus/l2-cache%d", cpu);
|
||||
+
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x80000);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 64);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 1024);
|
||||
+ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
|
||||
+ next_path);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
|
||||
+ qemu_fdt_alloc_phandle(ms->fdt));
|
||||
+
|
||||
+ g_free(next_path);
|
||||
+ g_free(nodename);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void fdt_add_l1cache_prop(const VirtMachineState *vms,
|
||||
+ char *nodename, int cpu)
|
||||
+{
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu);
|
||||
+
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", 0x10000);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", 64);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", 256);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", 0x10000);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", 64);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", 256);
|
||||
+ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
|
||||
+ cachename);
|
||||
+ g_free(cachename);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
|
||||
{
|
||||
int cpu;
|
||||
@@ -413,6 +479,11 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
|
||||
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells);
|
||||
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
|
||||
|
||||
+ if (!vmc->no_cpu_topology) {
|
||||
+ fdt_add_l3cache_nodes(vms);
|
||||
+ fdt_add_l2cache_nodes(vms);
|
||||
+ }
|
||||
+
|
||||
for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
|
||||
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
|
||||
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
|
||||
@@ -442,6 +513,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
|
||||
}
|
||||
|
||||
if (!vmc->no_cpu_topology) {
|
||||
+ fdt_add_l1cache_prop(vms, nodename, cpu);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
|
||||
qemu_fdt_alloc_phandle(ms->fdt));
|
||||
}
|
||||
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
||||
index ff2a310270..84ded2ecd3 100644
|
||||
--- a/include/hw/acpi/aml-build.h
|
||||
+++ b/include/hw/acpi/aml-build.h
|
||||
@@ -221,6 +221,53 @@ struct AcpiBuildTables {
|
||||
BIOSLinker *linker;
|
||||
} AcpiBuildTables;
|
||||
|
||||
+#ifdef __aarch64__
|
||||
+/* Definitions of the hardcoded cache info*/
|
||||
+
|
||||
+typedef enum {
|
||||
+ ARM_L1D_CACHE,
|
||||
+ ARM_L1I_CACHE,
|
||||
+ ARM_L2_CACHE,
|
||||
+ ARM_L3_CACHE
|
||||
+} ArmCacheType;
|
||||
+
|
||||
+/* L1 data cache: */
|
||||
+#define ARM_L1DCACHE_SIZE 65536
|
||||
+#define ARM_L1DCACHE_SETS 256
|
||||
+#define ARM_L1DCACHE_ASSOCIATIVITY 4
|
||||
+#define ARM_L1DCACHE_ATTRIBUTES 2
|
||||
+#define ARM_L1DCACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* L1 instruction cache: */
|
||||
+#define ARM_L1ICACHE_SIZE 65536
|
||||
+#define ARM_L1ICACHE_SETS 256
|
||||
+#define ARM_L1ICACHE_ASSOCIATIVITY 4
|
||||
+#define ARM_L1ICACHE_ATTRIBUTES 4
|
||||
+#define ARM_L1ICACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* Level 2 unified cache: */
|
||||
+#define ARM_L2CACHE_SIZE 524288
|
||||
+#define ARM_L2CACHE_SETS 1024
|
||||
+#define ARM_L2CACHE_ASSOCIATIVITY 8
|
||||
+#define ARM_L2CACHE_ATTRIBUTES 10
|
||||
+#define ARM_L2CACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* Level 3 unified cache: */
|
||||
+#define ARM_L3CACHE_SIZE 33554432
|
||||
+#define ARM_L3CACHE_SETS 2048
|
||||
+#define ARM_L3CACHE_ASSOCIATIVITY 15
|
||||
+#define ARM_L3CACHE_ATTRIBUTES 10
|
||||
+#define ARM_L3CACHE_LINE_SIZE 128
|
||||
+
|
||||
+struct offset_status {
|
||||
+ uint32_t parent;
|
||||
+ uint32_t l2_offset;
|
||||
+ uint32_t l1d_offset;
|
||||
+ uint32_t l1i_offset;
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
typedef
|
||||
struct CrsRangeEntry {
|
||||
uint64_t base;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
403
hw-intc-arm-gicv3-Changes-required-to-re-init-the-vC.patch
Normal file
403
hw-intc-arm-gicv3-Changes-required-to-re-init-the-vC.patch
Normal file
@ -0,0 +1,403 @@
|
||||
From 4e0a4443b7c36608fc30dcaaf0db120220111dd2 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sat, 9 May 2020 15:26:27 +0100
|
||||
Subject: [PATCH] hw/intc/arm-gicv3*: Changes required to (re)init the vCPU
|
||||
register info
|
||||
|
||||
vCPU register info needs to be re-initialized each time vCPU is hot-plugged.
|
||||
This has to be done both for emulation/TCG and KVM case. This is done in
|
||||
context to the GIC update notification for any vCPU hot-(un)plug events. This
|
||||
change adds that support and re-factors existing to maximize the code re-use.
|
||||
|
||||
Co-developed-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
hw/intc/arm_gicv3.c | 1 +
|
||||
hw/intc/arm_gicv3_common.c | 7 +-
|
||||
hw/intc/arm_gicv3_cpuif.c | 257 +++++++++++++++--------------
|
||||
hw/intc/arm_gicv3_kvm.c | 7 +-
|
||||
hw/intc/gicv3_internal.h | 1 +
|
||||
include/hw/intc/arm_gicv3_common.h | 1 +
|
||||
6 files changed, 150 insertions(+), 124 deletions(-)
|
||||
|
||||
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
|
||||
index 0b8f79a122..e1c7c8c4bc 100644
|
||||
--- a/hw/intc/arm_gicv3.c
|
||||
+++ b/hw/intc/arm_gicv3.c
|
||||
@@ -410,6 +410,7 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data)
|
||||
ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
|
||||
|
||||
agcc->post_load = arm_gicv3_post_load;
|
||||
+ agcc->init_cpu_reginfo = gicv3_init_cpu_reginfo;
|
||||
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 fc87fa9369..d051024a30 100644
|
||||
--- a/hw/intc/arm_gicv3_common.c
|
||||
+++ b/hw/intc/arm_gicv3_common.c
|
||||
@@ -345,10 +345,12 @@ static void arm_gicv3_cpu_update_notifier(Notifier *notifier, void * data)
|
||||
{
|
||||
GICv3CPUHotplugInfo *gic_info = (GICv3CPUHotplugInfo *)data;
|
||||
CPUState *cpu = gic_info->cpu;
|
||||
+ ARMGICv3CommonClass *c;
|
||||
int gic_cpuif_num;
|
||||
GICv3State *s;
|
||||
|
||||
s = ARM_GICV3_COMMON(gic_info->gic);
|
||||
+ c = ARM_GICV3_COMMON_GET_CLASS(s);
|
||||
|
||||
/* this shall get us mapped gicv3 cpuif corresponding to mpidr */
|
||||
gic_cpuif_num = arm_gicv3_get_proc_num(s, cpu);
|
||||
@@ -368,7 +370,10 @@ static void arm_gicv3_cpu_update_notifier(Notifier *notifier, void * data)
|
||||
gicv3_set_gicv3state(cpu, &s->cpu[gic_cpuif_num]);
|
||||
gicv3_set_cpustate(&s->cpu[gic_cpuif_num], cpu);
|
||||
|
||||
- /* TODO: initialize the registers info for this newly added cpu */
|
||||
+ /* initialize the registers info for this newly added cpu */
|
||||
+ if (c->init_cpu_reginfo) {
|
||||
+ c->init_cpu_reginfo(cpu);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
|
||||
index 0d0eb2f62f..a013510074 100644
|
||||
--- a/hw/intc/arm_gicv3_cpuif.c
|
||||
+++ b/hw/intc/arm_gicv3_cpuif.c
|
||||
@@ -2782,6 +2782,127 @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
|
||||
},
|
||||
};
|
||||
|
||||
+void gicv3_init_cpu_reginfo(CPUState *cs)
|
||||
+{
|
||||
+ ARMCPU *cpu = ARM_CPU(cs);
|
||||
+ GICv3CPUState *gcs = icc_cs_from_env(&cpu->env);
|
||||
+
|
||||
+ /*
|
||||
+ * If the CPU doesn't define a GICv3 configuration, probably because
|
||||
+ * in real hardware it doesn't have one, then we use default values
|
||||
+ * matching the one used by most Arm CPUs. This applies to:
|
||||
+ * cpu->gic_num_lrs
|
||||
+ * cpu->gic_vpribits
|
||||
+ * cpu->gic_vprebits
|
||||
+ * cpu->gic_pribits
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ * 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);
|
||||
+
|
||||
+ /*
|
||||
+ * The CPU implementation specifies the number of supported
|
||||
+ * bits of physical priority. For backwards compatibility
|
||||
+ * of migration, we have a compat property that forces use
|
||||
+ * of 8 priority bits regardless of what the CPU really has.
|
||||
+ */
|
||||
+ if (gcs->gic->force_8bit_prio) {
|
||||
+ gcs->pribits = 8;
|
||||
+ } else {
|
||||
+ gcs->pribits = cpu->gic_pribits ?: 5;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The GICv3 has separate ID register fields for virtual priority
|
||||
+ * and preemption bit values, but only a single ID register field
|
||||
+ * for the physical priority bits. The preemption bit count is
|
||||
+ * always the same as the priority bit count, except that 8 bits
|
||||
+ * of priority means 7 preemption bits. We precalculate the
|
||||
+ * preemption bits because it simplifies the code and makes the
|
||||
+ * parallels between the virtual and physical bits of the GIC
|
||||
+ * a bit clearer.
|
||||
+ */
|
||||
+ gcs->prebits = gcs->pribits;
|
||||
+ if (gcs->prebits == 8) {
|
||||
+ gcs->prebits--;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Check that CPU code defining pribits didn't violate
|
||||
+ * architectural constraints our implementation relies on.
|
||||
+ */
|
||||
+ g_assert(gcs->pribits >= 4 && gcs->pribits <= 8);
|
||||
+
|
||||
+ /*
|
||||
+ * gicv3_cpuif_reginfo[] defines ICC_AP*R0_EL1; add definitions
|
||||
+ * for ICC_AP*R{1,2,3}_EL1 if the prebits value requires them.
|
||||
+ */
|
||||
+ if (gcs->prebits >= 6) {
|
||||
+ define_arm_cp_regs(cpu, gicv3_cpuif_icc_apxr1_reginfo);
|
||||
+ }
|
||||
+ if (gcs->prebits == 7) {
|
||||
+ define_arm_cp_regs(cpu, gicv3_cpuif_icc_apxr23_reginfo);
|
||||
+ }
|
||||
+
|
||||
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
|
||||
+ int j;
|
||||
+
|
||||
+ gcs->num_list_regs = cpu->gic_num_lrs ?: 4;
|
||||
+ gcs->vpribits = cpu->gic_vpribits ?: 5;
|
||||
+ gcs->vprebits = cpu->gic_vprebits ?: 5;
|
||||
+
|
||||
+ /*
|
||||
+ * 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(gcs->vprebits <= gcs->vpribits);
|
||||
+ g_assert(gcs->vprebits >= 5 && gcs->vprebits <= 7);
|
||||
+ g_assert(gcs->vpribits >= 5 && gcs->vpribits <= 8);
|
||||
+
|
||||
+ define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
|
||||
+
|
||||
+ for (j = 0; j < gcs->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,
|
||||
+ },
|
||||
+ };
|
||||
+ define_arm_cp_regs(cpu, lr_regset);
|
||||
+ }
|
||||
+ if (gcs->vprebits >= 6) {
|
||||
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo);
|
||||
+ }
|
||||
+ if (gcs->vprebits == 7) {
|
||||
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
|
||||
{
|
||||
GICv3CPUState *cs = opaque;
|
||||
@@ -2804,131 +2925,23 @@ void gicv3_init_cpuif(GICv3State *s)
|
||||
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
|
||||
- GICv3CPUState *cs = &s->cpu[i];
|
||||
-
|
||||
- /*
|
||||
- * If the CPU doesn't define a GICv3 configuration, probably because
|
||||
- * in real hardware it doesn't have one, then we use default values
|
||||
- * matching the one used by most Arm CPUs. This applies to:
|
||||
- * cpu->gic_num_lrs
|
||||
- * cpu->gic_vpribits
|
||||
- * cpu->gic_vprebits
|
||||
- * cpu->gic_pribits
|
||||
- */
|
||||
-
|
||||
- /* 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.
|
||||
- *
|
||||
- * These CP regs callbacks can be called from either TCG or HVF code.
|
||||
- */
|
||||
- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
|
||||
-
|
||||
- /*
|
||||
- * The CPU implementation specifies the number of supported
|
||||
- * bits of physical priority. For backwards compatibility
|
||||
- * of migration, we have a compat property that forces use
|
||||
- * of 8 priority bits regardless of what the CPU really has.
|
||||
- */
|
||||
- if (s->force_8bit_prio) {
|
||||
- cs->pribits = 8;
|
||||
- } else {
|
||||
- cs->pribits = cpu->gic_pribits ?: 5;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * The GICv3 has separate ID register fields for virtual priority
|
||||
- * and preemption bit values, but only a single ID register field
|
||||
- * for the physical priority bits. The preemption bit count is
|
||||
- * always the same as the priority bit count, except that 8 bits
|
||||
- * of priority means 7 preemption bits. We precalculate the
|
||||
- * preemption bits because it simplifies the code and makes the
|
||||
- * parallels between the virtual and physical bits of the GIC
|
||||
- * a bit clearer.
|
||||
- */
|
||||
- cs->prebits = cs->pribits;
|
||||
- if (cs->prebits == 8) {
|
||||
- cs->prebits--;
|
||||
- }
|
||||
- /*
|
||||
- * Check that CPU code defining pribits didn't violate
|
||||
- * architectural constraints our implementation relies on.
|
||||
- */
|
||||
- g_assert(cs->pribits >= 4 && cs->pribits <= 8);
|
||||
|
||||
- /*
|
||||
- * gicv3_cpuif_reginfo[] defines ICC_AP*R0_EL1; add definitions
|
||||
- * for ICC_AP*R{1,2,3}_EL1 if the prebits value requires them.
|
||||
- */
|
||||
- if (cs->prebits >= 6) {
|
||||
- define_arm_cp_regs(cpu, gicv3_cpuif_icc_apxr1_reginfo);
|
||||
- }
|
||||
- if (cs->prebits == 7) {
|
||||
- define_arm_cp_regs(cpu, gicv3_cpuif_icc_apxr23_reginfo);
|
||||
- }
|
||||
-
|
||||
- if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
|
||||
- int j;
|
||||
-
|
||||
- cs->num_list_regs = cpu->gic_num_lrs ?: 4;
|
||||
- cs->vpribits = cpu->gic_vpribits ?: 5;
|
||||
- cs->vprebits = cpu->gic_vprebits ?: 5;
|
||||
-
|
||||
- /* 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);
|
||||
-
|
||||
- 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).
|
||||
+ if (qemu_enabled_cpu(CPU(cpu))) {
|
||||
+ GICv3CPUState *cs = icc_cs_from_env(&cpu->env);
|
||||
+ gicv3_init_cpu_reginfo(CPU(cpu));
|
||||
+ if (tcg_enabled() || qtest_enabled()) {
|
||||
+ /*
|
||||
+ * We can only trap EL changes with TCG. However the GIC
|
||||
+ * interrupt state only changes on EL changes involving EL2 or
|
||||
+ * EL3, so for the non-TCG case this is OK, as EL2 and EL3 can't
|
||||
+ * exist.
|
||||
*/
|
||||
- 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,
|
||||
- },
|
||||
- };
|
||||
- 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);
|
||||
+ } else {
|
||||
+ assert(!arm_feature(&cpu->env, ARM_FEATURE_EL2));
|
||||
+ assert(!arm_feature(&cpu->env, ARM_FEATURE_EL3));
|
||||
}
|
||||
}
|
||||
- if (tcg_enabled() || qtest_enabled()) {
|
||||
- /*
|
||||
- * We can only trap EL changes with TCG. However the GIC interrupt
|
||||
- * state only changes on EL changes involving EL2 or EL3, so for
|
||||
- * the non-TCG case this is OK, as EL2 and EL3 can't exist.
|
||||
- */
|
||||
- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
|
||||
- } else {
|
||||
- assert(!arm_feature(&cpu->env, ARM_FEATURE_EL2));
|
||||
- assert(!arm_feature(&cpu->env, ARM_FEATURE_EL3));
|
||||
- }
|
||||
}
|
||||
}
|
||||
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
|
||||
index db06c75e2b..dd2a60fa20 100644
|
||||
--- a/hw/intc/arm_gicv3_kvm.c
|
||||
+++ b/hw/intc/arm_gicv3_kvm.c
|
||||
@@ -804,6 +804,10 @@ static void vm_change_state_handler(void *opaque, bool running,
|
||||
}
|
||||
}
|
||||
|
||||
+static void kvm_gicv3_init_cpu_reginfo(CPUState *cs)
|
||||
+{
|
||||
+ define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
|
||||
+}
|
||||
|
||||
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -837,7 +841,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
CPUState *cs = qemu_get_cpu(i);
|
||||
if (qemu_enabled_cpu(cs)) {
|
||||
- define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
|
||||
+ kvm_gicv3_init_cpu_reginfo(cs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,6 +929,7 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
agcc->pre_save = kvm_arm_gicv3_get;
|
||||
agcc->post_load = kvm_arm_gicv3_put;
|
||||
+ agcc->init_cpu_reginfo = kvm_gicv3_init_cpu_reginfo;
|
||||
device_class_set_parent_realize(dc, kvm_arm_gicv3_realize,
|
||||
&kgc->parent_realize);
|
||||
resettable_class_set_parent_phases(rc, NULL, kvm_arm_gicv3_reset_hold, NULL,
|
||||
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
|
||||
index 9d4c1209bd..0bed0f6e2a 100644
|
||||
--- a/hw/intc/gicv3_internal.h
|
||||
+++ b/hw/intc/gicv3_internal.h
|
||||
@@ -709,6 +709,7 @@ void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr);
|
||||
|
||||
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
|
||||
void gicv3_init_cpuif(GICv3State *s);
|
||||
+void gicv3_init_cpu_reginfo(CPUState *cs);
|
||||
|
||||
/**
|
||||
* gicv3_cpuif_update:
|
||||
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
|
||||
index 97a48f44b9..b5f8ba17ff 100644
|
||||
--- a/include/hw/intc/arm_gicv3_common.h
|
||||
+++ b/include/hw/intc/arm_gicv3_common.h
|
||||
@@ -325,6 +325,7 @@ struct ARMGICv3CommonClass {
|
||||
|
||||
void (*pre_save)(GICv3State *s);
|
||||
void (*post_load)(GICv3State *s);
|
||||
+ void (*init_cpu_reginfo)(CPUState *cs);
|
||||
};
|
||||
|
||||
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
|
||||
--
|
||||
2.27.0
|
||||
|
||||
40
hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch
Normal file
40
hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From c3f204e02eacdd3e9ec6ac55396ccc7f115ad63e Mon Sep 17 00:00:00 2001
|
||||
From: Qiang Ning <ningqiang1@huawei.com>
|
||||
Date: Mon, 12 Jul 2021 17:30:45 +0800
|
||||
Subject: [PATCH] hw/net/rocker_of_dpa: fix double free bug of rocker device
|
||||
|
||||
The of_dpa_cmd_add_l2_flood function of the rocker device
|
||||
releases the memory of group->l2_flood.group_ids before
|
||||
applying for new memory. If the l2_group configured by
|
||||
the guest does not match the input group->l2_flood.group_ids,
|
||||
the err_out branch is redirected to release the memory of the
|
||||
group->l2_flood.group_ids branch. The pointer is not set to
|
||||
NULL after the memory is freed. When the guest accesses the
|
||||
of_dpa_cmd_add_l2_flood function again, the memory of
|
||||
group->l2_flood.group_ids is released again. As a result,
|
||||
the memory is double free.
|
||||
|
||||
Fix that by setting group->l2_flood.group_ids to NULL after free.
|
||||
|
||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
||||
Signed-off-by: Qiang Ning <ningqiang1@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
hw/net/rocker/rocker_of_dpa.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
|
||||
index 5e16056be6..c25438cccc 100644
|
||||
--- a/hw/net/rocker/rocker_of_dpa.c
|
||||
+++ b/hw/net/rocker/rocker_of_dpa.c
|
||||
@@ -2070,6 +2070,7 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group,
|
||||
err_out:
|
||||
group->l2_flood.group_count = 0;
|
||||
g_free(group->l2_flood.group_ids);
|
||||
+ group->l2_flood.group_ids = NULL;
|
||||
g_free(tlvs);
|
||||
|
||||
return err;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
459
hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch
Normal file
459
hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch
Normal file
@ -0,0 +1,459 @@
|
||||
From dc7e40b2841132b0bc43d25c2c31f41ae3fa2c68 Mon Sep 17 00:00:00 2001
|
||||
From: eillon <yezhenyu2@huawei.com>
|
||||
Date: Tue, 8 Feb 2022 22:43:59 -0500
|
||||
Subject: [PATCH] hw/usb: reduce the vpcu cost of UHCI when VNC disconnect
|
||||
|
||||
Reduce the vpcu cost by set a lower FRAME_TIMER_FREQ of the UHCI
|
||||
when VNC client disconnected. This can reduce about 3% cost of
|
||||
vcpu thread.
|
||||
|
||||
Signed-off-by: eillon <yezhenyu2@huawei.com>
|
||||
---
|
||||
hw/usb/core.c | 5 ++--
|
||||
hw/usb/desc.c | 7 +++--
|
||||
hw/usb/dev-hid.c | 2 +-
|
||||
hw/usb/hcd-uhci.c | 63 ++++++++++++++++++++++++++++++++++------
|
||||
hw/usb/hcd-uhci.h | 1 +
|
||||
hw/usb/host-libusb.c | 32 ++++++++++++++++++++
|
||||
include/hw/usb.h | 1 +
|
||||
include/qemu/timer.h | 28 ++++++++++++++++++
|
||||
ui/vnc.c | 4 +++
|
||||
util/qemu-timer.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
10 files changed, 197 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/hw/usb/core.c b/hw/usb/core.c
|
||||
index 975f76250a..51b36126ca 100644
|
||||
--- a/hw/usb/core.c
|
||||
+++ b/hw/usb/core.c
|
||||
@@ -87,7 +87,7 @@ void usb_device_reset(USBDevice *dev)
|
||||
return;
|
||||
}
|
||||
usb_device_handle_reset(dev);
|
||||
- dev->remote_wakeup = 0;
|
||||
+ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP;
|
||||
dev->addr = 0;
|
||||
dev->state = USB_STATE_DEFAULT;
|
||||
}
|
||||
@@ -105,7 +105,8 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
- if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
|
||||
+ if ((dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP)
|
||||
+ && dev->port && dev->port->ops->wakeup) {
|
||||
dev->port->ops->wakeup(dev->port);
|
||||
}
|
||||
if (bus->ops->wakeup_endpoint) {
|
||||
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
|
||||
index f2bdc05a95..333f73fff1 100644
|
||||
--- a/hw/usb/desc.c
|
||||
+++ b/hw/usb/desc.c
|
||||
@@ -752,7 +752,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
if (config->bmAttributes & USB_CFG_ATT_SELFPOWER) {
|
||||
data[0] |= 1 << USB_DEVICE_SELF_POWERED;
|
||||
}
|
||||
- if (dev->remote_wakeup) {
|
||||
+ if (dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) {
|
||||
data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
|
||||
}
|
||||
data[1] = 0x00;
|
||||
@@ -762,14 +762,15 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
}
|
||||
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
- dev->remote_wakeup = 0;
|
||||
+ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP;
|
||||
ret = 0;
|
||||
}
|
||||
trace_usb_clear_device_feature(dev->addr, value, ret);
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE:
|
||||
+ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED;
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
- dev->remote_wakeup = 1;
|
||||
+ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP;
|
||||
ret = 0;
|
||||
}
|
||||
trace_usb_set_device_feature(dev->addr, value, ret);
|
||||
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
|
||||
index bdd6d1ffaf..cc68d1ce9e 100644
|
||||
--- a/hw/usb/dev-hid.c
|
||||
+++ b/hw/usb/dev-hid.c
|
||||
@@ -745,7 +745,7 @@ static int usb_ptr_post_load(void *opaque, int version_id)
|
||||
{
|
||||
USBHIDState *s = opaque;
|
||||
|
||||
- if (s->dev.remote_wakeup) {
|
||||
+ if (s->dev.remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) {
|
||||
hid_pointer_activate(&s->hid);
|
||||
}
|
||||
return 0;
|
||||
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
|
||||
index 6975966c3f..a92581ff5f 100644
|
||||
--- a/hw/usb/hcd-uhci.c
|
||||
+++ b/hw/usb/hcd-uhci.c
|
||||
@@ -44,6 +44,8 @@
|
||||
#include "hcd-uhci.h"
|
||||
|
||||
#define FRAME_TIMER_FREQ 1000
|
||||
+#define FRAME_TIMER_FREQ_LAZY 10
|
||||
+#define USB_DEVICE_NEED_NORMAL_FREQ "QEMU USB Tablet"
|
||||
|
||||
#define FRAME_MAX_LOOPS 256
|
||||
|
||||
@@ -109,6 +111,22 @@ static void uhci_async_cancel(UHCIAsync *async);
|
||||
static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
|
||||
static void uhci_resume(void *opaque);
|
||||
|
||||
+static int64_t uhci_frame_timer_freq = FRAME_TIMER_FREQ_LAZY;
|
||||
+
|
||||
+static void uhci_set_frame_freq(int freq)
|
||||
+{
|
||||
+ if (freq <= 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ uhci_frame_timer_freq = freq;
|
||||
+}
|
||||
+
|
||||
+static qemu_usb_controller qemu_uhci = {
|
||||
+ .name = "uhci",
|
||||
+ .qemu_set_freq = uhci_set_frame_freq,
|
||||
+};
|
||||
+
|
||||
static inline int32_t uhci_queue_token(UHCI_TD *td)
|
||||
{
|
||||
if ((td->token & (0xf << 15)) == 0) {
|
||||
@@ -351,7 +369,7 @@ static int uhci_post_load(void *opaque, int version_id)
|
||||
|
||||
if (version_id < 2) {
|
||||
s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||
- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ);
|
||||
+ (NANOSECONDS_PER_SECOND / uhci_frame_timer_freq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -392,8 +410,29 @@ static void uhci_port_write(void *opaque, hwaddr addr,
|
||||
if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
|
||||
/* start frame processing */
|
||||
trace_usb_uhci_schedule_start();
|
||||
- s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||
- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ);
|
||||
+
|
||||
+ /*
|
||||
+ * If the frequency of frame_timer is too slow, Guest OS (Win2012) would become
|
||||
+ * blue-screen after hotplugging some vcpus.
|
||||
+ * If this USB device support the remote-wakeup, the UHCI controller
|
||||
+ * will enter global suspend mode when there is no input for several seconds.
|
||||
+ * In this case, Qemu will delete the frame_timer. Since the frame_timer has been deleted,
|
||||
+ * there is no influence to the performance of Vms. So, we can change the frequency to 1000.
|
||||
+ * After that the frequency will be safe when we trigger the frame_timer again.
|
||||
+ * Excepting this, there are two ways to change the frequency:
|
||||
+ * 1)VNC connect/disconnect;2)attach/detach USB device.
|
||||
+ */
|
||||
+ if ((uhci_frame_timer_freq != FRAME_TIMER_FREQ)
|
||||
+ && (s->ports[0].port.dev)
|
||||
+ && (!memcmp(s->ports[0].port.dev->product_desc,
|
||||
+ USB_DEVICE_NEED_NORMAL_FREQ, strlen(USB_DEVICE_NEED_NORMAL_FREQ)))
|
||||
+ && (s->ports[0].port.dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED)) {
|
||||
+ qemu_log("turn up the frequency of UHCI controller to %d\n", FRAME_TIMER_FREQ);
|
||||
+ uhci_frame_timer_freq = FRAME_TIMER_FREQ;
|
||||
+ }
|
||||
+
|
||||
+ s->frame_time = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ;
|
||||
+ s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->frame_time;
|
||||
timer_mod(s->frame_timer, s->expire_time);
|
||||
s->status &= ~UHCI_STS_HCHALTED;
|
||||
} else if (!(val & UHCI_CMD_RS)) {
|
||||
@@ -1083,7 +1122,6 @@ static void uhci_frame_timer(void *opaque)
|
||||
UHCIState *s = opaque;
|
||||
uint64_t t_now, t_last_run;
|
||||
int i, frames;
|
||||
- const uint64_t frame_t = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ;
|
||||
|
||||
s->completions_only = false;
|
||||
qemu_bh_cancel(s->bh);
|
||||
@@ -1099,14 +1137,14 @@ static void uhci_frame_timer(void *opaque)
|
||||
}
|
||||
|
||||
/* We still store expire_time in our state, for migration */
|
||||
- t_last_run = s->expire_time - frame_t;
|
||||
+ t_last_run = s->expire_time - s->frame_time;
|
||||
t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
/* Process up to MAX_FRAMES_PER_TICK frames */
|
||||
- frames = (t_now - t_last_run) / frame_t;
|
||||
+ frames = (t_now - t_last_run) / s->frame_time;
|
||||
if (frames > s->maxframes) {
|
||||
int skipped = frames - s->maxframes;
|
||||
- s->expire_time += skipped * frame_t;
|
||||
+ s->expire_time += skipped * s->frame_time;
|
||||
s->frnum = (s->frnum + skipped) & 0x7ff;
|
||||
frames -= skipped;
|
||||
}
|
||||
@@ -1123,7 +1161,7 @@ static void uhci_frame_timer(void *opaque)
|
||||
/* The spec says frnum is the frame currently being processed, and
|
||||
* the guest must look at frnum - 1 on interrupt, so inc frnum now */
|
||||
s->frnum = (s->frnum + 1) & 0x7ff;
|
||||
- s->expire_time += frame_t;
|
||||
+ s->expire_time += s->frame_time;
|
||||
}
|
||||
|
||||
/* Complete the previous frame(s) */
|
||||
@@ -1134,7 +1172,12 @@ static void uhci_frame_timer(void *opaque)
|
||||
}
|
||||
s->pending_int_mask = 0;
|
||||
|
||||
- timer_mod(s->frame_timer, t_now + frame_t);
|
||||
+ /* expire_time is calculated from last frame_time, we should calculate it
|
||||
+ * according to new frame_time which equals to
|
||||
+ * NANOSECONDS_PER_SECOND / uhci_frame_timer_freq */
|
||||
+ s->expire_time -= s->frame_time - NANOSECONDS_PER_SECOND / uhci_frame_timer_freq;
|
||||
+ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq;
|
||||
+ timer_mod(s->frame_timer, t_now + s->frame_time);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps uhci_ioport_ops = {
|
||||
@@ -1195,8 +1238,10 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
|
||||
s->bh = qemu_bh_new_guarded(uhci_bh, s, &DEVICE(dev)->mem_reentrancy_guard);
|
||||
s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s);
|
||||
s->num_ports_vmstate = NB_PORTS;
|
||||
+ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq;
|
||||
QTAILQ_INIT(&s->queues);
|
||||
|
||||
+ qemu_register_usb_controller(&qemu_uhci, QEMU_USB_CONTROLLER_UHCI);
|
||||
memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s,
|
||||
"uhci", 0x20);
|
||||
|
||||
diff --git a/hw/usb/hcd-uhci.h b/hw/usb/hcd-uhci.h
|
||||
index 69f8b40c49..0918719911 100644
|
||||
--- a/hw/usb/hcd-uhci.h
|
||||
+++ b/hw/usb/hcd-uhci.h
|
||||
@@ -50,6 +50,7 @@ typedef struct UHCIState {
|
||||
uint16_t status;
|
||||
uint16_t intr; /* interrupt enable register */
|
||||
uint16_t frnum; /* frame number */
|
||||
+ uint64_t frame_time; /* frame time in ns */
|
||||
uint32_t fl_base_addr; /* frame list base address */
|
||||
uint8_t sof_timing;
|
||||
uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
|
||||
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
|
||||
index d7060a42d5..dba469c1ef 100644
|
||||
--- a/hw/usb/host-libusb.c
|
||||
+++ b/hw/usb/host-libusb.c
|
||||
@@ -945,6 +945,30 @@ static void usb_host_ep_update(USBHostDevice *s)
|
||||
libusb_free_config_descriptor(conf);
|
||||
}
|
||||
|
||||
+static unsigned int usb_get_controller_type(int speed)
|
||||
+{
|
||||
+ unsigned int type = MAX_USB_CONTROLLER_TYPES;
|
||||
+
|
||||
+ switch (speed) {
|
||||
+ case USB_SPEED_SUPER:
|
||||
+ type = QEMU_USB_CONTROLLER_XHCI;
|
||||
+ break;
|
||||
+ case USB_SPEED_HIGH:
|
||||
+ type = QEMU_USB_CONTROLLER_EHCI;
|
||||
+ break;
|
||||
+ case USB_SPEED_FULL:
|
||||
+ type = QEMU_USB_CONTROLLER_UHCI;
|
||||
+ break;
|
||||
+ case USB_SPEED_LOW:
|
||||
+ type = QEMU_USB_CONTROLLER_OHCI;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return type;
|
||||
+}
|
||||
+
|
||||
static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
|
||||
{
|
||||
USBDevice *udev = USB_DEVICE(s);
|
||||
@@ -1054,6 +1078,12 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
|
||||
}
|
||||
|
||||
trace_usb_host_open_success(bus_num, addr);
|
||||
+
|
||||
+ /* change ehci frame time freq when USB passthrough */
|
||||
+ qemu_log("usb host speed is %d\n", udev->speed);
|
||||
+ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE,
|
||||
+ usb_get_controller_type(udev->speed));
|
||||
+
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -1129,6 +1159,8 @@ static int usb_host_close(USBHostDevice *s)
|
||||
}
|
||||
|
||||
usb_host_auto_check(NULL);
|
||||
+ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE,
|
||||
+ usb_get_controller_type(udev->speed));
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/include/hw/usb.h b/include/hw/usb.h
|
||||
index 32c23a5ca2..911179158d 100644
|
||||
--- a/include/hw/usb.h
|
||||
+++ b/include/hw/usb.h
|
||||
@@ -142,6 +142,7 @@
|
||||
|
||||
#define USB_DEVICE_SELF_POWERED 0
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1
|
||||
+#define USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED 2
|
||||
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
|
||||
index 9a366e551f..475c2a3f18 100644
|
||||
--- a/include/qemu/timer.h
|
||||
+++ b/include/qemu/timer.h
|
||||
@@ -91,6 +91,34 @@ struct QEMUTimer {
|
||||
int scale;
|
||||
};
|
||||
|
||||
+#define QEMU_USB_NORMAL_FREQ 1000
|
||||
+#define QEMU_USB_LAZY_FREQ 10
|
||||
+#define MAX_USB_CONTROLLER_TYPES 4
|
||||
+#define QEMU_USB_CONTROLLER_OHCI 0
|
||||
+#define QEMU_USB_CONTROLLER_UHCI 1
|
||||
+#define QEMU_USB_CONTROLLER_EHCI 2
|
||||
+#define QEMU_USB_CONTROLLER_XHCI 3
|
||||
+
|
||||
+typedef void (*QEMUSetFreqHandler) (int freq);
|
||||
+
|
||||
+typedef struct qemu_usb_controller {
|
||||
+ const char *name;
|
||||
+ QEMUSetFreqHandler qemu_set_freq;
|
||||
+} qemu_usb_controller;
|
||||
+
|
||||
+typedef qemu_usb_controller* qemu_usb_controller_ptr;
|
||||
+
|
||||
+enum qemu_timer_mode {
|
||||
+ QEMU_TIMER_USB_NORMAL_MODE = 1 << 0, /* Set when VNC connect or
|
||||
+ * with usb dev passthrough
|
||||
+ */
|
||||
+ QEMU_TIMER_USB_LAZY_MODE = 1 << 1, /* Set when VNC disconnect */
|
||||
+};
|
||||
+
|
||||
+int qemu_register_usb_controller(qemu_usb_controller_ptr controller,
|
||||
+ unsigned int type);
|
||||
+int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type);
|
||||
+
|
||||
extern QEMUTimerListGroup main_loop_tlg;
|
||||
|
||||
/*
|
||||
diff --git a/ui/vnc.c b/ui/vnc.c
|
||||
index 4f23a0fa79..5dd77e73cb 100644
|
||||
--- a/ui/vnc.c
|
||||
+++ b/ui/vnc.c
|
||||
@@ -1365,6 +1365,8 @@ void vnc_disconnect_finish(VncState *vs)
|
||||
g_free(vs->zrle);
|
||||
g_free(vs->tight);
|
||||
g_free(vs);
|
||||
+
|
||||
+ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE, QEMU_USB_CONTROLLER_UHCI);
|
||||
}
|
||||
|
||||
size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err)
|
||||
@@ -3341,6 +3343,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE, QEMU_USB_CONTROLLER_UHCI);
|
||||
}
|
||||
|
||||
void vnc_start_protocol(VncState *vs)
|
||||
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
|
||||
index 6a0de33dd2..dc891cc557 100644
|
||||
--- a/util/qemu-timer.c
|
||||
+++ b/util/qemu-timer.c
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/lockable.h"
|
||||
@@ -75,6 +76,74 @@ struct QEMUTimerList {
|
||||
QemuEvent timers_done_ev;
|
||||
};
|
||||
|
||||
+typedef struct qemu_controller_timer_state {
|
||||
+ qemu_usb_controller_ptr controller;
|
||||
+ int refs;
|
||||
+} controller_timer_state;
|
||||
+
|
||||
+typedef controller_timer_state* controller_timer_state_ptr;
|
||||
+
|
||||
+static controller_timer_state uhci_timer_state = {
|
||||
+ .controller = NULL,
|
||||
+ .refs = 0,
|
||||
+};
|
||||
+
|
||||
+static controller_timer_state_ptr \
|
||||
+ qemu_usb_controller_tab[MAX_USB_CONTROLLER_TYPES] = {NULL,
|
||||
+ &uhci_timer_state,
|
||||
+ NULL, NULL};
|
||||
+
|
||||
+int qemu_register_usb_controller(qemu_usb_controller_ptr controller,
|
||||
+ unsigned int type)
|
||||
+{
|
||||
+ if (type != QEMU_USB_CONTROLLER_UHCI) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* for companion EHCI controller will create three UHCI controllers,
|
||||
+ * we init it only once.
|
||||
+ */
|
||||
+ if (!qemu_usb_controller_tab[type]->controller) {
|
||||
+ qemu_log("the usb controller (%d) registed frame handler\n", type);
|
||||
+ qemu_usb_controller_tab[type]->controller = controller;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type)
|
||||
+{
|
||||
+ if (type != QEMU_USB_CONTROLLER_UHCI) {
|
||||
+ qemu_log("the usb controller (%d) no need change frame frep\n", type);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (!qemu_usb_controller_tab[type]->controller) {
|
||||
+ qemu_log("the usb controller (%d) not registed yet\n", type);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (mode == QEMU_TIMER_USB_NORMAL_MODE) {
|
||||
+ if (qemu_usb_controller_tab[type]->refs++ > 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ qemu_usb_controller_tab[type]->controller->
|
||||
+ qemu_set_freq(QEMU_USB_NORMAL_FREQ);
|
||||
+ qemu_log("Set the controller (%d) of freq %d HZ,\n",
|
||||
+ type, QEMU_USB_NORMAL_FREQ);
|
||||
+ } else {
|
||||
+ if (--qemu_usb_controller_tab[type]->refs > 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ qemu_usb_controller_tab[type]->controller->
|
||||
+ qemu_set_freq(QEMU_USB_LAZY_FREQ);
|
||||
+ qemu_log("Set the controller(type:%d) of freq %d HZ,\n",
|
||||
+ type, QEMU_USB_LAZY_FREQ);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* qemu_clock_ptr:
|
||||
* @type: type of clock
|
||||
--
|
||||
2.27.0
|
||||
|
||||
65
i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch
Normal file
65
i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From ff43e9201aba8f4047e6fd5edb93a4861cc8fed2 Mon Sep 17 00:00:00 2001
|
||||
From: Yanan Wang <wangyanan55@huawei.com>
|
||||
Date: Thu, 28 Mar 2024 18:57:56 +0800
|
||||
Subject: [PATCH] i386: cache passthrough: Update AMD 8000_001D.EAX[25:14]
|
||||
based on vCPU topo
|
||||
|
||||
On AMD target, when host cache passthrough is disabled we will
|
||||
emulate the guest caches with default values and initialize the
|
||||
shared cpu list of the caches based on vCPU topology. However
|
||||
when host cache passthrough is enabled, the shared cpu list is
|
||||
consistent with host regardless what the vCPU topology is.
|
||||
|
||||
For example, when cache passthrough is enabled, running a guest
|
||||
with vThreads=1 on a host with pThreads=2, we will get that there
|
||||
are every *two* logical vCPUs sharing a L1/L2 cache, which is not
|
||||
consistent with the vCPU topology (vThreads=1).
|
||||
|
||||
So let's reinitialize BITs[25:14] of AMD CPUID 8000_001D.EAX
|
||||
based on the actual vCPU topology instead of host pCPU topology.
|
||||
|
||||
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
target/i386/cpu.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index f94405c02b..491cf40cc7 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -6597,9 +6597,31 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
}
|
||||
break;
|
||||
case 0x8000001D:
|
||||
+ /* Populate AMD Processor Cache Information */
|
||||
*eax = 0;
|
||||
if (cpu->cache_info_passthrough) {
|
||||
x86_cpu_get_cache_cpuid(index, count, eax, ebx, ecx, edx);
|
||||
+
|
||||
+ /*
|
||||
+ * Clear BITs[25:14] and then update them based on the guest
|
||||
+ * vCPU topology, like what we do in encode_cache_cpuid8000001d
|
||||
+ * when cache_info_passthrough is not enabled.
|
||||
+ */
|
||||
+ *eax &= ~0x03FFC000;
|
||||
+ switch (count) {
|
||||
+ case 0: /* L1 dcache info */
|
||||
+ case 1: /* L1 icache info */
|
||||
+ case 2: /* L2 cache info */
|
||||
+ *eax |= ((topo_info.threads_per_core - 1) << 14);
|
||||
+ break;
|
||||
+ case 3: /* L3 cache info */
|
||||
+ *eax |= ((topo_info.cores_per_die *
|
||||
+ topo_info.threads_per_core - 1) << 14);
|
||||
+ break;
|
||||
+ default: /* end of info */
|
||||
+ *eax = *ebx = *ecx = *edx = 0;
|
||||
+ break;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
switch (count) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
42
i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch
Normal file
42
i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 06fc5eb48668a1c83e6a4e76c1a71403917b1835 Mon Sep 17 00:00:00 2001
|
||||
From: Jinhua Cao <caojinhua1@huawei.com>
|
||||
Date: Fri, 11 Feb 2022 20:33:47 +0800
|
||||
Subject: [PATCH] i6300esb watchdog: bugfix: Add a runstate transition
|
||||
|
||||
QEMU will abort() for the reasons now:
|
||||
|
||||
invalid runstate transition: 'prelaunch' -> 'postmigrate'
|
||||
Aborted
|
||||
|
||||
This happens when:
|
||||
|<- watchdog timeout happened, then sets reset_requested to
|
||||
| SHUTDOWN_CAUSE_GUEST_RESET;
|
||||
|<- hot-migration thread sets vm state to RUN_STATE_FINISH_MIGRATE
|
||||
| before the last time of migration;
|
||||
|<- main thread gets the change of reset_requested and triggers
|
||||
| reset, then sets vm state to RUN_STATE_PRELAUNCH;
|
||||
|<- hot-migration thread sets vm state to RUN_STATE_POSTMIGRATE.
|
||||
|
||||
Then 'prelaunch' -> 'postmigrate' runstate transition will happen.
|
||||
It is legal so add this transition to runstate_transitions_def.
|
||||
|
||||
Signed-off-by: Jinhua Cao <caojinhua1@huawei.com>
|
||||
---
|
||||
system/runstate.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/system/runstate.c b/system/runstate.c
|
||||
index ea9d6c2a32..9d3f627fee 100644
|
||||
--- a/system/runstate.c
|
||||
+++ b/system/runstate.c
|
||||
@@ -116,6 +116,7 @@ static const RunStateTransition runstate_transitions_def[] = {
|
||||
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
|
||||
{ RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
|
||||
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
|
||||
+ { RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE },
|
||||
|
||||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
|
||||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
|
||||
--
|
||||
2.27.0
|
||||
|
||||
42
ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch
Normal file
42
ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 6689eebbb520dc75bc65e0914c4e05e40a4efc1d Mon Sep 17 00:00:00 2001
|
||||
From: Prasad J Pandit <address@hidden>
|
||||
Date: Mon, 21 Jun 2021 09:22:35 +0800
|
||||
Subject: [PATCH] ide: ahci: add check to avoid null dereference
|
||||
(CVE-2019-12067)
|
||||
|
||||
Fix CVE-2019-12067
|
||||
|
||||
AHCI emulator while committing DMA buffer in ahci_commit_buf()
|
||||
may do a NULL dereference if the command header 'ad->cur_cmd'
|
||||
is null. Add check to avoid it.
|
||||
|
||||
Reported-by: Bugs SysSec <address@hidden>
|
||||
Signed-off-by: Prasad J Pandit <address@hidden>
|
||||
|
||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
Signed-off-by: Adttil <yangtao286@huawei.com>
|
||||
---
|
||||
hw/ide/ahci.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
|
||||
index afdc44b8e0..8062e1743c 100644
|
||||
--- a/hw/ide/ahci.c
|
||||
+++ b/hw/ide/ahci.c
|
||||
@@ -1519,8 +1519,10 @@ static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes)
|
||||
{
|
||||
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
|
||||
|
||||
- tx_bytes += le32_to_cpu(ad->cur_cmd->status);
|
||||
- ad->cur_cmd->status = cpu_to_le32(tx_bytes);
|
||||
+ if (ad->cur_cmd) {
|
||||
+ tx_bytes += le32_to_cpu(ad->cur_cmd->status);
|
||||
+ ad->cur_cmd->status = cpu_to_le32(tx_bytes);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
70
intc-gicv3-Fixes-for-vcpu-hotplug.patch
Normal file
70
intc-gicv3-Fixes-for-vcpu-hotplug.patch
Normal file
@ -0,0 +1,70 @@
|
||||
From 343b61303152b06f9e1ba6d09a405faeaa3fcc98 Mon Sep 17 00:00:00 2001
|
||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Date: Tue, 26 Mar 2024 22:12:58 +0800
|
||||
Subject: [PATCH] intc/gicv3: Fixes for vcpu hotplug
|
||||
|
||||
1. Some types of machine don't support possible_cpus
|
||||
callback.
|
||||
2. The cpu_update_notifier is register only when machine
|
||||
support vcpu hotplug, so do notifier_remove() unconditi-
|
||||
onally is wrong.
|
||||
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
---
|
||||
cpu-common.c | 4 ++++
|
||||
hw/intc/arm_gicv3_common.c | 9 +++++++--
|
||||
2 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cpu-common.c b/cpu-common.c
|
||||
index da52e45760..54e63b3f77 100644
|
||||
--- a/cpu-common.c
|
||||
+++ b/cpu-common.c
|
||||
@@ -113,6 +113,10 @@ CPUState *qemu_get_possible_cpu(int index)
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
const CPUArchIdList *possible_cpus = ms->possible_cpus;
|
||||
|
||||
+ if (possible_cpus == NULL) {
|
||||
+ return qemu_get_cpu(index);
|
||||
+ }
|
||||
+
|
||||
assert((index >= 0) && (index < possible_cpus->len));
|
||||
|
||||
return CPU(possible_cpus->cpus[index].cpu);
|
||||
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
|
||||
index d051024a30..5667d9f40b 100644
|
||||
--- a/hw/intc/arm_gicv3_common.c
|
||||
+++ b/hw/intc/arm_gicv3_common.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
+#include "hw/boards.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "hw/intc/arm_gicv3_common.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@@ -446,7 +447,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
|
||||
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
- CPUState *cpu = qemu_get_possible_cpu(i);
|
||||
+ CPUState *cpu = qemu_get_possible_cpu(i) ? : qemu_get_cpu(i);
|
||||
uint64_t cpu_affid;
|
||||
|
||||
if (qemu_enabled_cpu(cpu)) {
|
||||
@@ -506,8 +507,12 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
||||
static void arm_gicv3_finalize(Object *obj)
|
||||
{
|
||||
GICv3State *s = ARM_GICV3_COMMON(obj);
|
||||
+ Object *ms = qdev_get_machine();
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
|
||||
- notifier_remove(&s->cpu_update_notifier);
|
||||
+ if (mc->has_hotpluggable_cpus) {
|
||||
+ notifier_remove(&s->cpu_update_notifier);
|
||||
+ }
|
||||
g_free(s->redist_region_count);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
62
iotests-adapt-to-output-change-for-recently-introduc.patch
Normal file
62
iotests-adapt-to-output-change-for-recently-introduc.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From 7212ca27f0dc957f83fe29858430ee2927e0175c Mon Sep 17 00:00:00 2001
|
||||
From: root <root@localhost.localdomain>
|
||||
Date: Mon, 25 Mar 2024 21:31:32 +0800
|
||||
Subject: [PATCH] =?UTF-8?q?iotests:=20adapt=20to=20output=20change=20for?=
|
||||
=?UTF-8?q?=20recently=20introduced=20'detached=20hea=E2=80=A6?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from 39a94d7c34ce9d222fa9c0c99a14e20a567456d7
|
||||
|
||||
…der' field
|
||||
|
||||
Failure was noticed when running the tests for the qcow2 image format.
|
||||
|
||||
Fixes: 0bd779e ("crypto: Introduce 'detached-header' field in QCryptoBlockInfoLUKS")
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Message-ID: <20240216101415.293769-1-f.ebner@proxmox.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
tests/qemu-iotests/198.out | 2 ++
|
||||
tests/qemu-iotests/206.out | 1 +
|
||||
2 files changed, 3 insertions(+)
|
||||
|
||||
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
|
||||
index 805494916f..62fb73fa3e 100644
|
||||
--- a/tests/qemu-iotests/198.out
|
||||
+++ b/tests/qemu-iotests/198.out
|
||||
@@ -39,6 +39,7 @@ Format specific information:
|
||||
compression type: COMPRESSION_TYPE
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
+ detached header: false
|
||||
hash alg: sha256
|
||||
cipher alg: aes-256
|
||||
uuid: 00000000-0000-0000-0000-000000000000
|
||||
@@ -84,6 +85,7 @@ Format specific information:
|
||||
compression type: COMPRESSION_TYPE
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
+ detached header: false
|
||||
hash alg: sha256
|
||||
cipher alg: aes-256
|
||||
uuid: 00000000-0000-0000-0000-000000000000
|
||||
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
|
||||
index 7e95694777..979f00f9bf 100644
|
||||
--- a/tests/qemu-iotests/206.out
|
||||
+++ b/tests/qemu-iotests/206.out
|
||||
@@ -114,6 +114,7 @@ Format specific information:
|
||||
refcount bits: 16
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
+ detached header: false
|
||||
hash alg: sha1
|
||||
cipher alg: aes-128
|
||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
--
|
||||
2.27.0
|
||||
|
||||
82
linux-headers-update-against-5.10-and-manual-clear-v.patch
Normal file
82
linux-headers-update-against-5.10-and-manual-clear-v.patch
Normal file
@ -0,0 +1,82 @@
|
||||
From 2ccd1ec0d18070727ad9b9647da6b6937f16de2a Mon Sep 17 00:00:00 2001
|
||||
From: Zenghui Yu <yuzenghui@huawei.com>
|
||||
Date: Sat, 8 May 2021 17:31:03 +0800
|
||||
Subject: [PATCH] linux-headers: update against 5.10 and manual clear vfio
|
||||
dirty log series
|
||||
|
||||
The new capability VFIO_DIRTY_LOG_MANUAL_CLEAR and the new ioctl
|
||||
VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP_NOCLEAR and
|
||||
VFIO_IOMMU_DIRTY_PAGES_FLAG_CLEAR_BITMAP have been introduced in
|
||||
the kernel, update the header to add them.
|
||||
|
||||
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
|
||||
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
|
||||
---
|
||||
linux-headers/linux/vfio.h | 36 +++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 35 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
|
||||
index 8e175ece31..956154e509 100644
|
||||
--- a/linux-headers/linux/vfio.h
|
||||
+++ b/linux-headers/linux/vfio.h
|
||||
@@ -56,6 +56,16 @@
|
||||
*/
|
||||
#define VFIO_UPDATE_VADDR 10
|
||||
|
||||
+/*
|
||||
+ * The vfio_iommu driver may support user clears dirty log manually, which means
|
||||
+ * dirty log can be requested to not cleared automatically after dirty log is
|
||||
+ * copied to userspace, it's user's duty to clear dirty log.
|
||||
+ *
|
||||
+ * Note: please refer to VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP_NOCLEAR and
|
||||
+ * VFIO_IOMMU_DIRTY_PAGES_FLAG_CLEAR_BITMAP.
|
||||
+ */
|
||||
+#define VFIO_DIRTY_LOG_MANUAL_CLEAR 11
|
||||
+
|
||||
/*
|
||||
* The IOCTL interface is designed for extensibility by embedding the
|
||||
* structure length (argsz) and flags into structures passed between
|
||||
@@ -1651,8 +1661,30 @@ struct vfio_iommu_type1_dma_unmap {
|
||||
* actual bitmap. If dirty pages logging is not enabled, an error will be
|
||||
* returned.
|
||||
*
|
||||
- * Only one of the flags _START, _STOP and _GET may be specified at a time.
|
||||
+ * The VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP_NOCLEAR flag is almost same as
|
||||
+ * VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP, except that it requires underlying
|
||||
+ * dirty bitmap is not cleared automatically. The user can clear it manually by
|
||||
+ * calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_CLEAR_BITMAP flag set.
|
||||
*
|
||||
+ * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_CLEAR_BITMAP flag set,
|
||||
+ * instructs the IOMMU driver to clear the dirty status of pages in a bitmap
|
||||
+ * for IOMMU container for a given IOVA range. The user must specify the IOVA
|
||||
+ * range, the bitmap and the pgsize through the structure
|
||||
+ * vfio_iommu_type1_dirty_bitmap_get in the data[] portion. This interface
|
||||
+ * supports clearing a bitmap of the smallest supported pgsize only and can be
|
||||
+ * modified in future to clear a bitmap of any specified supported pgsize. The
|
||||
+ * user must provide a memory area for the bitmap memory and specify its size
|
||||
+ * in bitmap.size. One bit is used to represent one page consecutively starting
|
||||
+ * from iova offset. The user should provide page size in bitmap.pgsize field.
|
||||
+ * A bit set in the bitmap indicates that the page at that offset from iova is
|
||||
+ * cleared the dirty status, and dirty tracking is re-enabled for that page. The
|
||||
+ * caller must set argsz to a value including the size of structure
|
||||
+ * vfio_iommu_dirty_bitmap_get, but excluing the size of the actual bitmap. If
|
||||
+ * dirty pages logging is not enabled, an error will be returned. Note: user
|
||||
+ * should clear dirty log before handle corresponding dirty pages.
|
||||
+ *
|
||||
+ * Only one of the flags _START, _STOP, _GET, _GET_NOCLEAR_, and _CLEAR may be
|
||||
+ * specified at a time.
|
||||
*/
|
||||
struct vfio_iommu_type1_dirty_bitmap {
|
||||
__u32 argsz;
|
||||
@@ -1660,6 +1692,8 @@ struct vfio_iommu_type1_dirty_bitmap {
|
||||
#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0)
|
||||
#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1)
|
||||
#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2)
|
||||
+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP_NOCLEAR (1 << 3)
|
||||
+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_CLEAR_BITMAP (1 << 4)
|
||||
__u8 data[];
|
||||
};
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
68
log-Add-log-at-boot-cpu-init-for-aarch64.patch
Normal file
68
log-Add-log-at-boot-cpu-init-for-aarch64.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 16c4b8946903985e3dfd470d0e04b79d473505bc Mon Sep 17 00:00:00 2001
|
||||
From: "wanghaibin.wang" <wanghaibin.wang@huawei.com>
|
||||
Date: Sun, 17 Mar 2024 15:53:57 +0800
|
||||
Subject: [PATCH] log: Add log at boot & cpu init for aarch64
|
||||
|
||||
Add log at boot & cpu init for aarch64
|
||||
|
||||
Signed-off-by: miaoyubo <miaoyubo@huawei.com>
|
||||
Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/arm/boot.c | 4 ++++
|
||||
hw/arm/virt.c | 3 +++
|
||||
2 files changed, 7 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
|
||||
index 84ea6a807a..d1671e1d42 100644
|
||||
--- a/hw/arm/boot.c
|
||||
+++ b/hw/arm/boot.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
+#include "qemu/log.h"
|
||||
#include <libfdt.h>
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/linux-boot-if.h"
|
||||
@@ -1226,6 +1227,9 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
|
||||
* doesn't support secure.
|
||||
*/
|
||||
assert(!(info->secure_board_setup && kvm_enabled()));
|
||||
+
|
||||
+ qemu_log("load the kernel\n");
|
||||
+
|
||||
info->kernel_filename = ms->kernel_filename;
|
||||
info->kernel_cmdline = ms->kernel_cmdline;
|
||||
info->initrd_filename = ms->initrd_filename;
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index c19cacec8b..f4c3d47f30 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/option.h"
|
||||
+#include "qemu/log.h"
|
||||
#include "monitor/qdev.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/arm/boot.h"
|
||||
@@ -1020,6 +1021,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
|
||||
{
|
||||
VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier);
|
||||
|
||||
+ qemu_log("send powerdown to vm.\n");
|
||||
if (s->acpi_dev) {
|
||||
acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS);
|
||||
} else {
|
||||
@@ -2240,6 +2242,7 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
|
||||
create_fdt(vms);
|
||||
+ qemu_log("cpu init start\n");
|
||||
|
||||
assert(possible_cpus->len == max_cpus);
|
||||
for (n = 0; n < possible_cpus->len; n++) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
126
memory-backup-Modify-the-VM-s-physical-bits-value-se.patch
Normal file
126
memory-backup-Modify-the-VM-s-physical-bits-value-se.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 65435e107fc8eee37c61a3a7d1adebd013ad466f Mon Sep 17 00:00:00 2001
|
||||
From: Ming Yang <yangming73@huawei.com>
|
||||
Date: Sat, 23 Mar 2024 16:18:03 +0800
|
||||
Subject: [PATCH] memory: [backup] Modify the VM's physical bits value set
|
||||
policy.
|
||||
|
||||
backup code from qemu-6.2 to qemu-8.2
|
||||
old info:
|
||||
commit id :
|
||||
a09c3928b33b0c53831bd9eeb56f8171c26057bc
|
||||
messages:
|
||||
target-i386: Modify the VM's physical bits value set policy.
|
||||
|
||||
To resolve the problem that a VM with large memory capacity fails
|
||||
to be live migrated, determine whether the VM is a large memory
|
||||
capacity based on the memory size (4 TB). If yes, set the bus width
|
||||
of the VM address to 46 bits. If no, set the bus width to 42 bits.
|
||||
|
||||
Signed-off-by: Jinhua Cao <caojinhua1@huawei.com>
|
||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
||||
|
||||
Signed-off-by: Ming Yang <yangming73@huawei.com>
|
||||
---
|
||||
target/i386/cpu.c | 20 +++++++++++++++++++-
|
||||
target/i386/cpu.h | 6 ++++++
|
||||
target/i386/host-cpu.c | 13 +++++++------
|
||||
3 files changed, 32 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index a66e5a357b..fc61a84b1e 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -7666,6 +7666,24 @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
cpu->env.eip = value;
|
||||
}
|
||||
|
||||
+
|
||||
+/* At present, we check the vm is *LARGE* or not, i.e. whether
|
||||
+ * the memory size is more than 4T or not.
|
||||
+ */
|
||||
+const uint64_t large_vm_mem_size = 0x40000000000UL;
|
||||
+void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu)
|
||||
+{
|
||||
+ /* If there is not a large vm, we set the phys_bits to 42 bits,
|
||||
+ * otherwise, we increase the phys_bits to 46 bits.
|
||||
+ */
|
||||
+ if (ram_size < large_vm_mem_size) {
|
||||
+ cpu->phys_bits = DEFAULT_VM_CPU_PHYS_BITS;
|
||||
+ } else {
|
||||
+ cpu->phys_bits = LARGE_VM_CPU_PHYS_BITS;
|
||||
+ cpu->fill_mtrr_mask = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static vaddr x86_cpu_get_pc(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
@@ -7868,7 +7886,7 @@ static Property x86_cpu_properties[] = {
|
||||
DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0),
|
||||
DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),
|
||||
DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0),
|
||||
- DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true),
|
||||
+ DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, false),
|
||||
DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7,
|
||||
UINT32_MAX),
|
||||
DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX),
|
||||
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
|
||||
index ef987f344c..6993552cd9 100644
|
||||
--- a/target/i386/cpu.h
|
||||
+++ b/target/i386/cpu.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "cpu-qom.h"
|
||||
#include "kvm/hyperv-proto.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
+#include "exec/cpu-common.h"
|
||||
#include "qapi/qapi-types-common.h"
|
||||
#include "qemu/cpu-float.h"
|
||||
#include "qemu/timer.h"
|
||||
@@ -2081,6 +2082,11 @@ struct X86CPUClass {
|
||||
extern const VMStateDescription vmstate_x86_cpu;
|
||||
#endif
|
||||
|
||||
+#define DEFAULT_VM_CPU_PHYS_BITS 42
|
||||
+#define LARGE_VM_CPU_PHYS_BITS 46
|
||||
+
|
||||
+void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu);
|
||||
+
|
||||
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
|
||||
|
||||
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
|
||||
diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
|
||||
index 92ecb7254b..07738bf857 100644
|
||||
--- a/target/i386/host-cpu.c
|
||||
+++ b/target/i386/host-cpu.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
+#include "hw/boards.h"
|
||||
|
||||
/* Note: Only safe for use on x86(-64) hosts */
|
||||
static uint32_t host_cpu_phys_bits(void)
|
||||
@@ -57,14 +58,14 @@ static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu)
|
||||
uint32_t phys_bits = cpu->phys_bits;
|
||||
static bool warned;
|
||||
|
||||
- /*
|
||||
- * Print a warning if the user set it to a value that's not the
|
||||
- * host value.
|
||||
- */
|
||||
- if (phys_bits != host_phys_bits && phys_bits != 0 &&
|
||||
+ /* adjust x86 cpu phys_bits according to ram_size. */
|
||||
+ x86_cpu_adjuest_by_ram_size(current_machine->ram_size, cpu);
|
||||
+
|
||||
+ /* Print a warning if the host value less than the user set. */
|
||||
+ if (phys_bits > host_phys_bits && phys_bits != 0 &&
|
||||
!warned) {
|
||||
warn_report("Host physical bits (%u)"
|
||||
- " does not match phys-bits property (%u)",
|
||||
+ " less than phys-bits property (%u)",
|
||||
host_phys_bits, phys_bits);
|
||||
warned = true;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
68
migration-Add-compress_level-sanity-check.patch
Normal file
68
migration-Add-compress_level-sanity-check.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 79863c5ccdd4c635657d2e32e91bc02aa49655e0 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 16:23:15 +0800
|
||||
Subject: [PATCH] migration: Add compress_level sanity check
|
||||
|
||||
Zlib compression has level from 1 to 9. However Zstd compression has level
|
||||
from 1 to 22 (level >= 20 not recommanded). Let's do sanity check here
|
||||
to make sure a vaild compress_level is given by user.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
migration/options.c | 32 ++++++++++++++++++++++++++++----
|
||||
1 file changed, 28 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/migration/options.c b/migration/options.c
|
||||
index 6aaee702dc..9b68962a65 100644
|
||||
--- a/migration/options.c
|
||||
+++ b/migration/options.c
|
||||
@@ -1065,16 +1065,40 @@ void migrate_params_init(MigrationParameters *params)
|
||||
params->has_mode = true;
|
||||
}
|
||||
|
||||
+static bool compress_level_check(MigrationParameters *params, Error **errp)
|
||||
+{
|
||||
+ switch (params->compress_method) {
|
||||
+ case COMPRESS_METHOD_ZLIB:
|
||||
+ if (params->compress_level > 9 || params->compress_level < 1) {
|
||||
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
|
||||
+ "a value in the range of 0 to 9 for Zlib method");
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+ case COMPRESS_METHOD_ZSTD:
|
||||
+ if (params->compress_level > 19 || params->compress_level < 1) {
|
||||
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
|
||||
+ "a value in the range of 1 to 19 for Zstd method");
|
||||
+ return false;
|
||||
+ }
|
||||
+ break;
|
||||
+#endif
|
||||
+ default:
|
||||
+ error_setg(errp, "Checking compress_level failed for unknown reason");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Check whether the parameters are valid. Error will be put into errp
|
||||
* (if provided). Return true if valid, otherwise false.
|
||||
*/
|
||||
bool migrate_params_check(MigrationParameters *params, Error **errp)
|
||||
{
|
||||
- if (params->has_compress_level &&
|
||||
- (params->compress_level > 9)) {
|
||||
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
|
||||
- "a value between 0 and 9");
|
||||
+ if (params->has_compress_level && !compress_level_check(params, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
292
migration-Add-multi-thread-compress-method.patch
Normal file
292
migration-Add-multi-thread-compress-method.patch
Normal file
@ -0,0 +1,292 @@
|
||||
From c2402b63ecb10b9a25695b710f2664dbcbc01ec4 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 14:57:54 +0800
|
||||
Subject: [PATCH] migration: Add multi-thread compress method
|
||||
|
||||
A multi-thread compress method parameter is added to hold the method we
|
||||
are going to use. By default the 'zlib' method is used to maintain the
|
||||
compatibility as before.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
hw/core/qdev-properties-system.c | 11 +++++++++++
|
||||
include/hw/qdev-properties.h | 4 ++++
|
||||
migration/migration-hmp-cmds.c | 13 +++++++++++++
|
||||
migration/options.c | 15 +++++++++++++++
|
||||
monitor/hmp-cmds.c | 1 +
|
||||
qapi/migration.json | 32 ++++++++++++++++++++++++++++++--
|
||||
util/oslib-posix.c | 2 +-
|
||||
7 files changed, 75 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
|
||||
index f2e2718c74..cd5571fcfb 100644
|
||||
--- a/hw/core/qdev-properties-system.c
|
||||
+++ b/hw/core/qdev-properties-system.c
|
||||
@@ -1202,6 +1202,17 @@ const PropertyInfo qdev_prop_uuid = {
|
||||
.set_default_value = set_default_uuid_auto,
|
||||
};
|
||||
|
||||
+/* --- CompressMethod --- */
|
||||
+const PropertyInfo qdev_prop_compress_method = {
|
||||
+ .name = "CompressMethod",
|
||||
+ .description = "multi-thread compression method, "
|
||||
+ "zlib",
|
||||
+ .enum_table = &CompressMethod_lookup,
|
||||
+ .get = qdev_propinfo_get_enum,
|
||||
+ .set = qdev_propinfo_set_enum,
|
||||
+ .set_default_value = qdev_propinfo_set_default_value_enum,
|
||||
+};
|
||||
+
|
||||
/* --- s390 cpu entitlement policy --- */
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(CpuS390Entitlement) != sizeof(int));
|
||||
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
|
||||
index 25743a29a0..63602c2c74 100644
|
||||
--- a/include/hw/qdev-properties.h
|
||||
+++ b/include/hw/qdev-properties.h
|
||||
@@ -60,6 +60,7 @@ extern const PropertyInfo qdev_prop_int64;
|
||||
extern const PropertyInfo qdev_prop_size;
|
||||
extern const PropertyInfo qdev_prop_string;
|
||||
extern const PropertyInfo qdev_prop_on_off_auto;
|
||||
+extern const PropertyInfo qdev_prop_compress_method;
|
||||
extern const PropertyInfo qdev_prop_size32;
|
||||
extern const PropertyInfo qdev_prop_array;
|
||||
extern const PropertyInfo qdev_prop_link;
|
||||
@@ -168,6 +169,9 @@ extern const PropertyInfo qdev_prop_link;
|
||||
DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
|
||||
#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
|
||||
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
|
||||
+#define DEFINE_PROP_COMPRESS_METHOD(_n, _s, _f, _d) \
|
||||
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_compress_method, \
|
||||
+ CompressMethod)
|
||||
#define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \
|
||||
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t)
|
||||
|
||||
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
|
||||
index 86ae832176..261ec1e35c 100644
|
||||
--- a/migration/migration-hmp-cmds.c
|
||||
+++ b/migration/migration-hmp-cmds.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "qapi/qapi-commands-migration.h"
|
||||
#include "qapi/qapi-visit-migration.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
+#include "qapi/qapi-visit-migration.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qemu/cutils.h"
|
||||
@@ -291,6 +292,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_DECOMPRESS_THREADS),
|
||||
params->decompress_threads);
|
||||
assert(params->has_throttle_trigger_threshold);
|
||||
+ monitor_printf(mon, "%s: %s\n",
|
||||
+ MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_METHOD),
|
||||
+ CompressMethod_str(params->compress_method));
|
||||
monitor_printf(mon, "%s: %u\n",
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD),
|
||||
params->throttle_trigger_threshold);
|
||||
@@ -519,6 +523,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||
MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
|
||||
uint64_t valuebw = 0;
|
||||
uint64_t cache_size;
|
||||
+ CompressMethod compress_method;
|
||||
Error *err = NULL;
|
||||
int val, ret;
|
||||
|
||||
@@ -544,6 +549,14 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||
p->has_decompress_threads = true;
|
||||
visit_type_uint8(v, param, &p->decompress_threads, &err);
|
||||
break;
|
||||
+ case MIGRATION_PARAMETER_COMPRESS_METHOD:
|
||||
+ p->has_compress_method = true;
|
||||
+ visit_type_CompressMethod(v, param, &compress_method, &err);
|
||||
+ if (err) {
|
||||
+ break;
|
||||
+ }
|
||||
+ p->compress_method = compress_method;
|
||||
+ break;
|
||||
case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD:
|
||||
p->has_throttle_trigger_threshold = true;
|
||||
visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err);
|
||||
diff --git a/migration/options.c b/migration/options.c
|
||||
index 8d8ec73ad9..af7ea7b346 100644
|
||||
--- a/migration/options.c
|
||||
+++ b/migration/options.c
|
||||
@@ -47,6 +47,7 @@
|
||||
#define DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT 2
|
||||
/*0: means nocompress, 1: best speed, ... 9: best compress ratio */
|
||||
#define DEFAULT_MIGRATE_COMPRESS_LEVEL 1
|
||||
+#define DEFAULT_MIGRATE_COMPRESS_METHOD COMPRESS_METHOD_ZLIB
|
||||
/* Define default autoconverge cpu throttle migration parameters */
|
||||
#define DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD 50
|
||||
#define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20
|
||||
@@ -113,6 +114,9 @@ Property migration_properties[] = {
|
||||
DEFINE_PROP_UINT8("x-decompress-threads", MigrationState,
|
||||
parameters.decompress_threads,
|
||||
DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT),
|
||||
+ DEFINE_PROP_COMPRESS_METHOD("compress-method", MigrationState,
|
||||
+ parameters.compress_method,
|
||||
+ DEFAULT_MIGRATE_COMPRESS_METHOD),
|
||||
DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState,
|
||||
parameters.throttle_trigger_threshold,
|
||||
DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD),
|
||||
@@ -953,6 +957,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
|
||||
params->compress_wait_thread = s->parameters.compress_wait_thread;
|
||||
params->has_decompress_threads = true;
|
||||
params->decompress_threads = s->parameters.decompress_threads;
|
||||
+ params->has_compress_method = true;
|
||||
+ params->compress_method = s->parameters.compress_method;
|
||||
params->has_throttle_trigger_threshold = true;
|
||||
params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
|
||||
params->has_cpu_throttle_initial = true;
|
||||
@@ -1025,6 +1031,7 @@ void migrate_params_init(MigrationParameters *params)
|
||||
params->has_compress_threads = true;
|
||||
params->has_compress_wait_thread = true;
|
||||
params->has_decompress_threads = true;
|
||||
+ params->has_compress_method = true;
|
||||
params->has_throttle_trigger_threshold = true;
|
||||
params->has_cpu_throttle_initial = true;
|
||||
params->has_cpu_throttle_increment = true;
|
||||
@@ -1259,6 +1266,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
|
||||
dest->decompress_threads = params->decompress_threads;
|
||||
}
|
||||
|
||||
+ if (params->has_compress_method) {
|
||||
+ dest->compress_method = params->compress_method;
|
||||
+ }
|
||||
+
|
||||
if (params->has_throttle_trigger_threshold) {
|
||||
dest->throttle_trigger_threshold = params->throttle_trigger_threshold;
|
||||
}
|
||||
@@ -1380,6 +1391,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
||||
s->parameters.decompress_threads = params->decompress_threads;
|
||||
}
|
||||
|
||||
+ if (params->has_compress_method) {
|
||||
+ s->parameters.compress_method = params->compress_method;
|
||||
+ }
|
||||
+
|
||||
if (params->has_throttle_trigger_threshold) {
|
||||
s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold;
|
||||
}
|
||||
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
|
||||
index 871898ac46..5bb3c9cd46 100644
|
||||
--- a/monitor/hmp-cmds.c
|
||||
+++ b/monitor/hmp-cmds.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "qapi/qapi-commands-control.h"
|
||||
#include "qapi/qapi-commands-misc.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
+#include "qapi/qapi-visit-migration.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/intc/intc.h"
|
||||
#include "qemu/log.h"
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index eb2f883513..cafaa5ccb3 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -708,6 +708,19 @@
|
||||
'bitmaps': [ 'BitmapMigrationBitmapAlias' ]
|
||||
} }
|
||||
|
||||
+##
|
||||
+# @CompressMethod:
|
||||
+#
|
||||
+# An enumeration of multi-thread compression methods.
|
||||
+#
|
||||
+# @zlib: use zlib compression method.
|
||||
+#
|
||||
+# Since: 5.0
|
||||
+#
|
||||
+##
|
||||
+{ 'enum': 'CompressMethod',
|
||||
+ 'data': [ 'zlib' ] }
|
||||
+
|
||||
##
|
||||
# @MigrationParameter:
|
||||
#
|
||||
@@ -746,6 +759,9 @@
|
||||
# fast as compression, so set the decompress-threads to the number
|
||||
# about 1/4 of compress-threads is adequate.
|
||||
#
|
||||
+# @compress-method: Which multi-thread compression method to use.
|
||||
+# Defaults to none. (Since 5.0)
|
||||
+#
|
||||
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and
|
||||
# bytes_xfer_period to trigger throttling. It is expressed as
|
||||
# percentage. The default value is 50. (Since 5.0)
|
||||
@@ -892,6 +908,7 @@
|
||||
{ 'name': 'compress-level', 'features': [ 'deprecated' ] },
|
||||
{ 'name': 'compress-threads', 'features': [ 'deprecated' ] },
|
||||
{ 'name': 'decompress-threads', 'features': [ 'deprecated' ] },
|
||||
+ { 'name': 'compress-method', 'features': [ 'deprecated' ] },
|
||||
{ 'name': 'compress-wait-thread', 'features': [ 'deprecated' ] },
|
||||
'throttle-trigger-threshold',
|
||||
'cpu-throttle-initial', 'cpu-throttle-increment',
|
||||
@@ -935,6 +952,9 @@
|
||||
#
|
||||
# @decompress-threads: decompression thread count
|
||||
#
|
||||
+# @compress-method: Set compression method to use in multi-thread compression.
|
||||
+# Defaults to none. (Since 5.0)
|
||||
+#
|
||||
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and
|
||||
# bytes_xfer_period to trigger throttling. It is expressed as
|
||||
# percentage. The default value is 50. (Since 5.0)
|
||||
@@ -1066,8 +1086,9 @@
|
||||
#
|
||||
# @deprecated: Member @block-incremental is deprecated. Use
|
||||
# blockdev-mirror with NBD instead. Members @compress-level,
|
||||
-# @compress-threads, @decompress-threads and @compress-wait-thread
|
||||
-# are deprecated because @compression is deprecated.
|
||||
+# @compress-threads, @decompress-threads, @compress-method
|
||||
+# and @compress-wait-thread are deprecated because
|
||||
+# @compression is deprecated.
|
||||
#
|
||||
# @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period
|
||||
# are experimental.
|
||||
@@ -1090,6 +1111,8 @@
|
||||
'features': [ 'deprecated' ] },
|
||||
'*decompress-threads': { 'type': 'uint8',
|
||||
'features': [ 'deprecated' ] },
|
||||
+ '*compress-method': { 'type': 'CompressMethod',
|
||||
+ 'features': [ 'deprecated' ] },
|
||||
'*throttle-trigger-threshold': 'uint8',
|
||||
'*cpu-throttle-initial': 'uint8',
|
||||
'*cpu-throttle-increment': 'uint8',
|
||||
@@ -1161,6 +1184,9 @@
|
||||
#
|
||||
# @decompress-threads: decompression thread count
|
||||
#
|
||||
+# @compress-method: Which multi-thread compression method to use.
|
||||
+# Defaults to none. (Since 5.0)
|
||||
+#
|
||||
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and
|
||||
# bytes_xfer_period to trigger throttling. It is expressed as
|
||||
# percentage. The default value is 50. (Since 5.0)
|
||||
@@ -1315,6 +1341,8 @@
|
||||
'features': [ 'deprecated' ] },
|
||||
'*decompress-threads': { 'type': 'uint8',
|
||||
'features': [ 'deprecated' ] },
|
||||
+ '*compress-method': { 'type': 'CompressMethod',
|
||||
+ 'features': [ 'deprecated' ] },
|
||||
'*throttle-trigger-threshold': 'uint8',
|
||||
'*cpu-throttle-initial': 'uint8',
|
||||
'*cpu-throttle-increment': 'uint8',
|
||||
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
|
||||
index 9ca3fee2b8..43af077fed 100644
|
||||
--- a/util/oslib-posix.c
|
||||
+++ b/util/oslib-posix.c
|
||||
@@ -346,7 +346,7 @@ static void *do_touch_pages(void *arg)
|
||||
}
|
||||
qemu_mutex_unlock(&page_mutex);
|
||||
|
||||
- while (started_num_threads != memset_args->context.num_threads) {
|
||||
+ while (started_num_threads != memset_args->context->num_threads) {
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
493
migration-Add-multi-thread-compress-ops.patch
Normal file
493
migration-Add-multi-thread-compress-ops.patch
Normal file
@ -0,0 +1,493 @@
|
||||
From 5896dedf32c7e4417bd7f3e889ca41a34b06f5db Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 15:57:31 +0800
|
||||
Subject: [PATCH] migration: Add multi-thread compress ops
|
||||
|
||||
Add the MigrationCompressOps and MigrationDecompressOps structures to make
|
||||
the compression method configurable for multi-thread compression migration.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
migration/options.c | 9 ++
|
||||
migration/options.h | 1 +
|
||||
migration/ram-compress.c | 261 ++++++++++++++++++++++++++-------------
|
||||
migration/ram-compress.h | 31 ++++-
|
||||
migration/ram.c | 4 +-
|
||||
5 files changed, 215 insertions(+), 91 deletions(-)
|
||||
|
||||
diff --git a/migration/options.c b/migration/options.c
|
||||
index af7ea7b346..6aaee702dc 100644
|
||||
--- a/migration/options.c
|
||||
+++ b/migration/options.c
|
||||
@@ -799,6 +799,15 @@ int migrate_decompress_threads(void)
|
||||
return s->parameters.decompress_threads;
|
||||
}
|
||||
|
||||
+CompressMethod migrate_compress_method(void)
|
||||
+{
|
||||
+ MigrationState *s;
|
||||
+
|
||||
+ s = migrate_get_current();
|
||||
+
|
||||
+ return s->parameters.compress_method;
|
||||
+}
|
||||
+
|
||||
uint64_t migrate_downtime_limit(void)
|
||||
{
|
||||
MigrationState *s = migrate_get_current();
|
||||
diff --git a/migration/options.h b/migration/options.h
|
||||
index 246c160aee..9aca5e41ad 100644
|
||||
--- a/migration/options.h
|
||||
+++ b/migration/options.h
|
||||
@@ -78,6 +78,7 @@ uint8_t migrate_cpu_throttle_increment(void);
|
||||
uint8_t migrate_cpu_throttle_initial(void);
|
||||
bool migrate_cpu_throttle_tailslow(void);
|
||||
int migrate_decompress_threads(void);
|
||||
+CompressMethod migrate_compress_method(void);
|
||||
uint64_t migrate_downtime_limit(void);
|
||||
uint8_t migrate_max_cpu_throttle(void);
|
||||
uint64_t migrate_max_bandwidth(void);
|
||||
diff --git a/migration/ram-compress.c b/migration/ram-compress.c
|
||||
index 2be344acbc..6e37b22492 100644
|
||||
--- a/migration/ram-compress.c
|
||||
+++ b/migration/ram-compress.c
|
||||
@@ -65,26 +65,167 @@ static QemuThread *compress_threads;
|
||||
static QemuMutex comp_done_lock;
|
||||
static QemuCond comp_done_cond;
|
||||
|
||||
-struct DecompressParam {
|
||||
- bool done;
|
||||
- bool quit;
|
||||
- QemuMutex mutex;
|
||||
- QemuCond cond;
|
||||
- void *des;
|
||||
- uint8_t *compbuf;
|
||||
- int len;
|
||||
- z_stream stream;
|
||||
-};
|
||||
-typedef struct DecompressParam DecompressParam;
|
||||
-
|
||||
static QEMUFile *decomp_file;
|
||||
static DecompressParam *decomp_param;
|
||||
static QemuThread *decompress_threads;
|
||||
+MigrationCompressOps *compress_ops;
|
||||
+MigrationDecompressOps *decompress_ops;
|
||||
static QemuMutex decomp_done_lock;
|
||||
static QemuCond decomp_done_cond;
|
||||
|
||||
static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block);
|
||||
|
||||
+static int zlib_save_setup(CompressParam *param)
|
||||
+{
|
||||
+ if (deflateInit(¶m->stream,
|
||||
+ migrate_compress_level()) != Z_OK) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t zlib_compress_data(CompressParam *param, size_t size)
|
||||
+{
|
||||
+ int err;
|
||||
+ uint8_t *dest = NULL;
|
||||
+ z_stream *stream = ¶m->stream;
|
||||
+ uint8_t *p = param->originbuf;
|
||||
+ QEMUFile *f = f = param->file;
|
||||
+ ssize_t blen = qemu_put_compress_start(f, &dest);
|
||||
+
|
||||
+ if (blen < compressBound(size)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ err = deflateReset(stream);
|
||||
+ if (err != Z_OK) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ stream->avail_in = size;
|
||||
+ stream->next_in = p;
|
||||
+ stream->avail_out = blen;
|
||||
+ stream->next_out = dest;
|
||||
+
|
||||
+ err = deflate(stream, Z_FINISH);
|
||||
+ if (err != Z_STREAM_END) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ blen = stream->next_out - dest;
|
||||
+ if (blen < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ qemu_put_compress_end(f, blen);
|
||||
+ return blen + sizeof(int32_t);
|
||||
+}
|
||||
+
|
||||
+static void zlib_save_cleanup(CompressParam *param)
|
||||
+{
|
||||
+ deflateEnd(¶m->stream);
|
||||
+}
|
||||
+
|
||||
+static int zlib_load_setup(DecompressParam *param)
|
||||
+{
|
||||
+ if (inflateInit(¶m->stream) != Z_OK) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+zlib_decompress_data(DecompressParam *param, uint8_t *dest, size_t size)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ z_stream *stream = ¶m->stream;
|
||||
+
|
||||
+ err = inflateReset(stream);
|
||||
+ if (err != Z_OK) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ stream->avail_in = param->len;
|
||||
+ stream->next_in = param->compbuf;
|
||||
+ stream->avail_out = size;
|
||||
+ stream->next_out = dest;
|
||||
+
|
||||
+ err = inflate(stream, Z_NO_FLUSH);
|
||||
+ if (err != Z_STREAM_END) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return stream->total_out;
|
||||
+}
|
||||
+
|
||||
+static void zlib_load_cleanup(DecompressParam *param)
|
||||
+{
|
||||
+ inflateEnd(¶m->stream);
|
||||
+}
|
||||
+
|
||||
+static int zlib_check_len(int len)
|
||||
+{
|
||||
+ return len < 0 || len > compressBound(TARGET_PAGE_SIZE);
|
||||
+}
|
||||
+
|
||||
+static int set_compress_ops(void)
|
||||
+{
|
||||
+ compress_ops = g_new0(MigrationCompressOps, 1);
|
||||
+
|
||||
+ switch (migrate_compress_method()) {
|
||||
+ case COMPRESS_METHOD_ZLIB:
|
||||
+ compress_ops->save_setup = zlib_save_setup;
|
||||
+ compress_ops->save_cleanup = zlib_save_cleanup;
|
||||
+ compress_ops->compress_data = zlib_compress_data;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int set_decompress_ops(void)
|
||||
+{
|
||||
+ decompress_ops = g_new0(MigrationDecompressOps, 1);
|
||||
+
|
||||
+ switch (migrate_compress_method()) {
|
||||
+ case COMPRESS_METHOD_ZLIB:
|
||||
+ decompress_ops->load_setup = zlib_load_setup;
|
||||
+ decompress_ops->load_cleanup = zlib_load_cleanup;
|
||||
+ decompress_ops->decompress_data = zlib_decompress_data;
|
||||
+ decompress_ops->check_len = zlib_check_len;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void clean_compress_ops(void)
|
||||
+{
|
||||
+ compress_ops->save_setup = NULL;
|
||||
+ compress_ops->save_cleanup = NULL;
|
||||
+ compress_ops->compress_data = NULL;
|
||||
+
|
||||
+ g_free(compress_ops);
|
||||
+ compress_ops = NULL;
|
||||
+}
|
||||
+
|
||||
+static void clean_decompress_ops(void)
|
||||
+{
|
||||
+ decompress_ops->load_setup = NULL;
|
||||
+ decompress_ops->load_cleanup = NULL;
|
||||
+ decompress_ops->decompress_data = NULL;
|
||||
+
|
||||
+ g_free(decompress_ops);
|
||||
+ decompress_ops = NULL;
|
||||
+}
|
||||
+
|
||||
static void *do_data_compress(void *opaque)
|
||||
{
|
||||
CompressParam *param = opaque;
|
||||
@@ -141,7 +282,7 @@ void compress_threads_save_cleanup(void)
|
||||
qemu_thread_join(compress_threads + i);
|
||||
qemu_mutex_destroy(&comp_param[i].mutex);
|
||||
qemu_cond_destroy(&comp_param[i].cond);
|
||||
- deflateEnd(&comp_param[i].stream);
|
||||
+ compress_ops->save_cleanup(&comp_param[i]);
|
||||
g_free(comp_param[i].originbuf);
|
||||
qemu_fclose(comp_param[i].file);
|
||||
comp_param[i].file = NULL;
|
||||
@@ -152,6 +293,7 @@ void compress_threads_save_cleanup(void)
|
||||
g_free(comp_param);
|
||||
compress_threads = NULL;
|
||||
comp_param = NULL;
|
||||
+ clean_compress_ops();
|
||||
}
|
||||
|
||||
int compress_threads_save_setup(void)
|
||||
@@ -161,6 +303,12 @@ int compress_threads_save_setup(void)
|
||||
if (!migrate_compress()) {
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ if (set_compress_ops() < 0) {
|
||||
+ clean_compress_ops();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
thread_count = migrate_compress_threads();
|
||||
compress_threads = g_new0(QemuThread, thread_count);
|
||||
comp_param = g_new0(CompressParam, thread_count);
|
||||
@@ -172,8 +320,7 @@ int compress_threads_save_setup(void)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
- if (deflateInit(&comp_param[i].stream,
|
||||
- migrate_compress_level()) != Z_OK) {
|
||||
+ if (compress_ops->save_setup(&comp_param[i]) < 0) {
|
||||
g_free(comp_param[i].originbuf);
|
||||
goto exit;
|
||||
}
|
||||
@@ -198,50 +345,6 @@ exit:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Compress size bytes of data start at p and store the compressed
|
||||
- * data to the buffer of f.
|
||||
- *
|
||||
- * Since the file is dummy file with empty_ops, return -1 if f has no space to
|
||||
- * save the compressed data.
|
||||
- */
|
||||
-static ssize_t qemu_put_compression_data(CompressParam *param, size_t size)
|
||||
-{
|
||||
- int err;
|
||||
- uint8_t *dest = NULL;
|
||||
- z_stream *stream = ¶m->stream;
|
||||
- uint8_t *p = param->originbuf;
|
||||
- QEMUFile *f = f = param->file;
|
||||
- ssize_t blen = qemu_put_compress_start(f, &dest);
|
||||
-
|
||||
- if (blen < compressBound(size)) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- err = deflateReset(stream);
|
||||
- if (err != Z_OK) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- stream->avail_in = size;
|
||||
- stream->next_in = p;
|
||||
- stream->avail_out = blen;
|
||||
- stream->next_out = dest;
|
||||
-
|
||||
- err = deflate(stream, Z_FINISH);
|
||||
- if (err != Z_STREAM_END) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- blen = stream->next_out - dest;
|
||||
- if (blen < 0) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- qemu_put_compress_end(f, blen);
|
||||
- return blen + sizeof(int32_t);
|
||||
-}
|
||||
-
|
||||
static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block)
|
||||
{
|
||||
uint8_t *p = block->host + (param->offset & TARGET_PAGE_MASK);
|
||||
@@ -260,7 +363,7 @@ static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block
|
||||
* decompression
|
||||
*/
|
||||
memcpy(param->originbuf, p, page_size);
|
||||
- ret = qemu_put_compression_data(param, page_size);
|
||||
+ ret = compress_ops->compress_data(param, page_size);
|
||||
if (ret < 0) {
|
||||
qemu_file_set_error(migrate_get_current()->to_dst_file, ret);
|
||||
error_report("compressed data failed!");
|
||||
@@ -356,32 +459,6 @@ bool compress_page_with_multi_thread(RAMBlock *block, ram_addr_t offset,
|
||||
}
|
||||
}
|
||||
|
||||
-/* return the size after decompression, or negative value on error */
|
||||
-static int
|
||||
-qemu_uncompress_data(DecompressParam *param, uint8_t *dest, size_t pagesize)
|
||||
-{
|
||||
- int err;
|
||||
-
|
||||
- z_stream *stream = ¶m->stream;
|
||||
-
|
||||
- err = inflateReset(stream);
|
||||
- if (err != Z_OK) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- stream->avail_in = param->len;
|
||||
- stream->next_in = param->compbuf;
|
||||
- stream->avail_out = pagesize;
|
||||
- stream->next_out = dest;
|
||||
-
|
||||
- err = inflate(stream, Z_NO_FLUSH);
|
||||
- if (err != Z_STREAM_END) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- return stream->total_out;
|
||||
-}
|
||||
-
|
||||
static void *do_data_decompress(void *opaque)
|
||||
{
|
||||
DecompressParam *param = opaque;
|
||||
@@ -398,7 +475,7 @@ static void *do_data_decompress(void *opaque)
|
||||
|
||||
pagesize = qemu_target_page_size();
|
||||
|
||||
- ret = qemu_uncompress_data(param, des, pagesize);
|
||||
+ ret = decompress_ops->decompress_data(param, des, pagesize);
|
||||
if (ret < 0 && migrate_get_current()->decompress_error_check) {
|
||||
error_report("decompress data failed");
|
||||
qemu_file_set_error(decomp_file, ret);
|
||||
@@ -466,7 +543,7 @@ void compress_threads_load_cleanup(void)
|
||||
qemu_thread_join(decompress_threads + i);
|
||||
qemu_mutex_destroy(&decomp_param[i].mutex);
|
||||
qemu_cond_destroy(&decomp_param[i].cond);
|
||||
- inflateEnd(&decomp_param[i].stream);
|
||||
+ decompress_ops->load_cleanup(&decomp_param[i]);
|
||||
g_free(decomp_param[i].compbuf);
|
||||
decomp_param[i].compbuf = NULL;
|
||||
}
|
||||
@@ -475,6 +552,7 @@ void compress_threads_load_cleanup(void)
|
||||
decompress_threads = NULL;
|
||||
decomp_param = NULL;
|
||||
decomp_file = NULL;
|
||||
+ clean_decompress_ops();
|
||||
}
|
||||
|
||||
int compress_threads_load_setup(QEMUFile *f)
|
||||
@@ -485,6 +563,11 @@ int compress_threads_load_setup(QEMUFile *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if (set_decompress_ops() < 0) {
|
||||
+ clean_decompress_ops();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* set compression_counters memory to zero for a new migration
|
||||
*/
|
||||
@@ -497,7 +580,7 @@ int compress_threads_load_setup(QEMUFile *f)
|
||||
qemu_cond_init(&decomp_done_cond);
|
||||
decomp_file = f;
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
- if (inflateInit(&decomp_param[i].stream) != Z_OK) {
|
||||
+ if (decompress_ops->load_setup(&decomp_param[i]) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
diff --git a/migration/ram-compress.h b/migration/ram-compress.h
|
||||
index 0d89a2f55e..daf241987f 100644
|
||||
--- a/migration/ram-compress.h
|
||||
+++ b/migration/ram-compress.h
|
||||
@@ -39,6 +39,20 @@ enum CompressResult {
|
||||
};
|
||||
typedef enum CompressResult CompressResult;
|
||||
|
||||
+struct DecompressParam {
|
||||
+ bool done;
|
||||
+ bool quit;
|
||||
+ QemuMutex mutex;
|
||||
+ QemuCond cond;
|
||||
+ void *des;
|
||||
+ uint8_t *compbuf;
|
||||
+ int len;
|
||||
+
|
||||
+ /* for zlib compression */
|
||||
+ z_stream stream;
|
||||
+};
|
||||
+typedef struct DecompressParam DecompressParam;
|
||||
+
|
||||
struct CompressParam {
|
||||
bool done;
|
||||
bool quit;
|
||||
@@ -51,11 +65,26 @@ struct CompressParam {
|
||||
ram_addr_t offset;
|
||||
|
||||
/* internally used fields */
|
||||
- z_stream stream;
|
||||
uint8_t *originbuf;
|
||||
+
|
||||
+ /* for zlib compression */
|
||||
+ z_stream stream;
|
||||
};
|
||||
typedef struct CompressParam CompressParam;
|
||||
|
||||
+typedef struct {
|
||||
+ int (*save_setup)(CompressParam *param);
|
||||
+ void (*save_cleanup)(CompressParam *param);
|
||||
+ ssize_t (*compress_data)(CompressParam *param, size_t size);
|
||||
+} MigrationCompressOps;
|
||||
+
|
||||
+typedef struct {
|
||||
+ int (*load_setup)(DecompressParam *param);
|
||||
+ void (*load_cleanup)(DecompressParam *param);
|
||||
+ int (*decompress_data)(DecompressParam *param, uint8_t *dest, size_t size);
|
||||
+ int (*check_len)(int len);
|
||||
+} MigrationDecompressOps;
|
||||
+
|
||||
void compress_threads_save_cleanup(void);
|
||||
int compress_threads_save_setup(void);
|
||||
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 8c7886ab79..f9b2b9b985 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -96,6 +96,8 @@
|
||||
|
||||
XBZRLECacheStats xbzrle_counters;
|
||||
|
||||
+extern MigrationDecompressOps *decompress_ops;
|
||||
+
|
||||
/* used by the search for pages to send */
|
||||
struct PageSearchStatus {
|
||||
/* The migration channel used for a specific host page */
|
||||
@@ -3979,7 +3981,7 @@ static int ram_load_precopy(QEMUFile *f)
|
||||
|
||||
case RAM_SAVE_FLAG_COMPRESS_PAGE:
|
||||
len = qemu_get_be32(f);
|
||||
- if (len < 0 || len > compressBound(TARGET_PAGE_SIZE)) {
|
||||
+ if (decompress_ops->check_len(len)) {
|
||||
error_report("Invalid compressed data length: %d", len);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
229
migration-Add-zstd-support-in-multi-thread-compressi.patch
Normal file
229
migration-Add-zstd-support-in-multi-thread-compressi.patch
Normal file
@ -0,0 +1,229 @@
|
||||
From 8c9603270184d8dadf64ec6de263268e846f8c18 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 16:15:10 +0800
|
||||
Subject: [PATCH] migration: Add zstd support in multi-thread compression
|
||||
|
||||
This patch enables zstd option in multi-thread compression.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
hw/core/qdev-properties-system.c | 2 +-
|
||||
migration/ram-compress.c | 112 +++++++++++++++++++++++++++++++
|
||||
migration/ram-compress.h | 15 +++++
|
||||
qapi/migration.json | 3 +-
|
||||
4 files changed, 130 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
|
||||
index cd5571fcfb..c581d46f2e 100644
|
||||
--- a/hw/core/qdev-properties-system.c
|
||||
+++ b/hw/core/qdev-properties-system.c
|
||||
@@ -1206,7 +1206,7 @@ const PropertyInfo qdev_prop_uuid = {
|
||||
const PropertyInfo qdev_prop_compress_method = {
|
||||
.name = "CompressMethod",
|
||||
.description = "multi-thread compression method, "
|
||||
- "zlib",
|
||||
+ "zlib/zstd",
|
||||
.enum_table = &CompressMethod_lookup,
|
||||
.get = qdev_propinfo_get_enum,
|
||||
.set = qdev_propinfo_set_enum,
|
||||
diff --git a/migration/ram-compress.c b/migration/ram-compress.c
|
||||
index 6e37b22492..74703f0ec4 100644
|
||||
--- a/migration/ram-compress.c
|
||||
+++ b/migration/ram-compress.c
|
||||
@@ -171,6 +171,103 @@ static int zlib_check_len(int len)
|
||||
return len < 0 || len > compressBound(TARGET_PAGE_SIZE);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+static int zstd_save_setup(CompressParam *param)
|
||||
+{
|
||||
+ int res;
|
||||
+ param->zstd_cs = ZSTD_createCStream();
|
||||
+ if (!param->zstd_cs) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ res = ZSTD_initCStream(param->zstd_cs, migrate_compress_level());
|
||||
+ if (ZSTD_isError(res)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+static void zstd_save_cleanup(CompressParam *param)
|
||||
+{
|
||||
+ ZSTD_freeCStream(param->zstd_cs);
|
||||
+ param->zstd_cs = NULL;
|
||||
+}
|
||||
+static ssize_t zstd_compress_data(CompressParam *param, size_t size)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uint8_t *dest = NULL;
|
||||
+ uint8_t *p = param->originbuf;
|
||||
+ QEMUFile *f = f = param->file;
|
||||
+ ssize_t blen = qemu_put_compress_start(f, &dest);
|
||||
+ if (blen < ZSTD_compressBound(size)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ param->out.dst = dest;
|
||||
+ param->out.size = blen;
|
||||
+ param->out.pos = 0;
|
||||
+ param->in.src = p;
|
||||
+ param->in.size = size;
|
||||
+ param->in.pos = 0;
|
||||
+ do {
|
||||
+ ret = ZSTD_compressStream2(param->zstd_cs, ¶m->out,
|
||||
+ ¶m->in, ZSTD_e_end);
|
||||
+ } while (ret > 0 && (param->in.size - param->in.pos > 0)
|
||||
+ && (param->out.size - param->out.pos > 0));
|
||||
+ if (ret > 0 && (param->in.size - param->in.pos > 0)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (ZSTD_isError(ret)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ blen = param->out.pos;
|
||||
+ qemu_put_compress_end(f, blen);
|
||||
+ return blen + sizeof(int32_t);
|
||||
+}
|
||||
+
|
||||
+static int zstd_load_setup(DecompressParam *param)
|
||||
+{
|
||||
+ int ret;
|
||||
+ param->zstd_ds = ZSTD_createDStream();
|
||||
+ if (!param->zstd_ds) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ret = ZSTD_initDStream(param->zstd_ds);
|
||||
+ if (ZSTD_isError(ret)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+static void zstd_load_cleanup(DecompressParam *param)
|
||||
+{
|
||||
+ ZSTD_freeDStream(param->zstd_ds);
|
||||
+ param->zstd_ds = NULL;
|
||||
+}
|
||||
+static int
|
||||
+zstd_decompress_data(DecompressParam *param, uint8_t *dest, size_t size)
|
||||
+{
|
||||
+ int ret;
|
||||
+ param->out.dst = dest;
|
||||
+ param->out.size = size;
|
||||
+ param->out.pos = 0;
|
||||
+ param->in.src = param->compbuf;
|
||||
+ param->in.size = param->len;
|
||||
+ param->in.pos = 0;
|
||||
+ do {
|
||||
+ ret = ZSTD_decompressStream(param->zstd_ds, ¶m->out, ¶m->in);
|
||||
+ } while (ret > 0 && (param->in.size - param->in.pos > 0)
|
||||
+ && (param->out.size - param->out.pos > 0));
|
||||
+ if (ret > 0 && (param->in.size - param->in.pos > 0)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (ZSTD_isError(ret)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+static int zstd_check_len(int len)
|
||||
+{
|
||||
+ return len < 0 || len > ZSTD_compressBound(TARGET_PAGE_SIZE);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static int set_compress_ops(void)
|
||||
{
|
||||
compress_ops = g_new0(MigrationCompressOps, 1);
|
||||
@@ -181,6 +278,13 @@ static int set_compress_ops(void)
|
||||
compress_ops->save_cleanup = zlib_save_cleanup;
|
||||
compress_ops->compress_data = zlib_compress_data;
|
||||
break;
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+ case COMPRESS_METHOD_ZSTD:
|
||||
+ compress_ops->save_setup = zstd_save_setup;
|
||||
+ compress_ops->save_cleanup = zstd_save_cleanup;
|
||||
+ compress_ops->compress_data = zstd_compress_data;
|
||||
+ break;
|
||||
+#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -199,6 +303,14 @@ static int set_decompress_ops(void)
|
||||
decompress_ops->decompress_data = zlib_decompress_data;
|
||||
decompress_ops->check_len = zlib_check_len;
|
||||
break;
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+ case COMPRESS_METHOD_ZSTD:
|
||||
+ decompress_ops->load_setup = zstd_load_setup;
|
||||
+ decompress_ops->load_cleanup = zstd_load_cleanup;
|
||||
+ decompress_ops->decompress_data = zstd_decompress_data;
|
||||
+ decompress_ops->check_len = zstd_check_len;
|
||||
+ break;
|
||||
+#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
diff --git a/migration/ram-compress.h b/migration/ram-compress.h
|
||||
index daf241987f..e8700eb36f 100644
|
||||
--- a/migration/ram-compress.h
|
||||
+++ b/migration/ram-compress.h
|
||||
@@ -29,6 +29,10 @@
|
||||
#ifndef QEMU_MIGRATION_COMPRESS_H
|
||||
#define QEMU_MIGRATION_COMPRESS_H
|
||||
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+#include <zstd.h>
|
||||
+#include <zstd_errors.h>
|
||||
+#endif
|
||||
#include "qemu-file.h"
|
||||
#include "qapi/qapi-types-migration.h"
|
||||
|
||||
@@ -50,6 +54,11 @@ struct DecompressParam {
|
||||
|
||||
/* for zlib compression */
|
||||
z_stream stream;
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+ ZSTD_DStream *zstd_ds;
|
||||
+ ZSTD_inBuffer in;
|
||||
+ ZSTD_outBuffer out;
|
||||
+#endif
|
||||
};
|
||||
typedef struct DecompressParam DecompressParam;
|
||||
|
||||
@@ -69,6 +78,12 @@ struct CompressParam {
|
||||
|
||||
/* for zlib compression */
|
||||
z_stream stream;
|
||||
+
|
||||
+#ifdef CONFIG_ZSTD
|
||||
+ ZSTD_CStream *zstd_cs;
|
||||
+ ZSTD_inBuffer in;
|
||||
+ ZSTD_outBuffer out;
|
||||
+#endif
|
||||
};
|
||||
typedef struct CompressParam CompressParam;
|
||||
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index cafaa5ccb3..29af841f4e 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -714,12 +714,13 @@
|
||||
# An enumeration of multi-thread compression methods.
|
||||
#
|
||||
# @zlib: use zlib compression method.
|
||||
+# @zstd: use zstd compression method.
|
||||
#
|
||||
# Since: 5.0
|
||||
#
|
||||
##
|
||||
{ 'enum': 'CompressMethod',
|
||||
- 'data': [ 'zlib' ] }
|
||||
+ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
|
||||
|
||||
##
|
||||
# @MigrationParameter:
|
||||
--
|
||||
2.27.0
|
||||
|
||||
330
migration-Refactoring-multi-thread-compress-migratio.patch
Normal file
330
migration-Refactoring-multi-thread-compress-migratio.patch
Normal file
@ -0,0 +1,330 @@
|
||||
From cf6f31249817380e91cbc4e55b189216645fac18 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Sat, 30 Jan 2021 15:21:17 +0800
|
||||
Subject: [PATCH] migration: Refactoring multi-thread compress migration
|
||||
|
||||
Code refactor for the compression procedure which includes:
|
||||
|
||||
1. Move qemu_compress_data and qemu_put_compression_data from qemu-file.c to
|
||||
ram.c, for the reason that most part of the code logical has nothing to do
|
||||
with qemu-file. Besides, the decompression code is located at ram.c only.
|
||||
|
||||
2. Simplify the function input arguments for compression and decompression.
|
||||
Wrap the input into the param structure which already exists. This change also
|
||||
makes the function much more flexible for other compression methods.
|
||||
|
||||
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
---
|
||||
migration/meson.build | 4 +-
|
||||
migration/migration-hmp-cmds.c | 1 -
|
||||
migration/qemu-file.c | 61 +++++-------------------
|
||||
migration/qemu-file.h | 4 +-
|
||||
migration/ram-compress.c | 87 ++++++++++++++++++++++++----------
|
||||
5 files changed, 77 insertions(+), 80 deletions(-)
|
||||
|
||||
diff --git a/migration/meson.build b/migration/meson.build
|
||||
index 92b1cc4297..d9b46ef0df 100644
|
||||
--- a/migration/meson.build
|
||||
+++ b/migration/meson.build
|
||||
@@ -22,7 +22,6 @@ system_ss.add(files(
|
||||
'migration.c',
|
||||
'multifd.c',
|
||||
'multifd-zlib.c',
|
||||
- 'ram-compress.c',
|
||||
'options.c',
|
||||
'postcopy-ram.c',
|
||||
'savevm.c',
|
||||
@@ -43,4 +42,5 @@ system_ss.add(when: zstd, if_true: files('multifd-zstd.c'))
|
||||
|
||||
specific_ss.add(when: 'CONFIG_SYSTEM_ONLY',
|
||||
if_true: files('ram.c',
|
||||
- 'target.c'))
|
||||
+ 'target.c',
|
||||
+ 'ram-compress.c'))
|
||||
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
|
||||
index 261ec1e35c..1fa6a5f478 100644
|
||||
--- a/migration/migration-hmp-cmds.c
|
||||
+++ b/migration/migration-hmp-cmds.c
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "qapi/qapi-commands-migration.h"
|
||||
#include "qapi/qapi-visit-migration.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
-#include "qapi/qapi-visit-migration.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qemu/cutils.h"
|
||||
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
|
||||
index 94231ff295..bd1dbc3db1 100644
|
||||
--- a/migration/qemu-file.c
|
||||
+++ b/migration/qemu-file.c
|
||||
@@ -669,55 +669,6 @@ uint64_t qemu_get_be64(QEMUFile *f)
|
||||
return v;
|
||||
}
|
||||
|
||||
-/* return the size after compression, or negative value on error */
|
||||
-static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
|
||||
- const uint8_t *source, size_t source_len)
|
||||
-{
|
||||
- int err;
|
||||
-
|
||||
- err = deflateReset(stream);
|
||||
- if (err != Z_OK) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- stream->avail_in = source_len;
|
||||
- stream->next_in = (uint8_t *)source;
|
||||
- stream->avail_out = dest_len;
|
||||
- stream->next_out = dest;
|
||||
-
|
||||
- err = deflate(stream, Z_FINISH);
|
||||
- if (err != Z_STREAM_END) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- return stream->next_out - dest;
|
||||
-}
|
||||
-
|
||||
-/* Compress size bytes of data start at p and store the compressed
|
||||
- * data to the buffer of f.
|
||||
- *
|
||||
- * Since the file is dummy file with empty_ops, return -1 if f has no space to
|
||||
- * save the compressed data.
|
||||
- */
|
||||
-ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
|
||||
- const uint8_t *p, size_t size)
|
||||
-{
|
||||
- ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
|
||||
-
|
||||
- if (blen < compressBound(size)) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- blen = qemu_compress_data(stream, f->buf + f->buf_index + sizeof(int32_t),
|
||||
- blen, p, size);
|
||||
- if (blen < 0) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- qemu_put_be32(f, blen);
|
||||
- add_buf_to_iovec(f, blen);
|
||||
- return blen + sizeof(int32_t);
|
||||
-}
|
||||
|
||||
/* Put the data in the buffer of f_src to the buffer of f_des, and
|
||||
* then reset the buf_index of f_src to 0.
|
||||
@@ -834,3 +785,15 @@ int qemu_file_get_to_fd(QEMUFile *f, int fd, size_t size)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ssize_t qemu_put_compress_start(QEMUFile *f, uint8_t **dest_ptr)
|
||||
+{
|
||||
+ *dest_ptr = f->buf + f->buf_index + sizeof(int32_t);
|
||||
+ return IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
|
||||
+}
|
||||
+
|
||||
+void qemu_put_compress_end(QEMUFile *f, unsigned int v)
|
||||
+{
|
||||
+ qemu_put_be32(f, v);
|
||||
+ add_buf_to_iovec(f, v);
|
||||
+}
|
||||
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
|
||||
index 8aec9fabf7..8afa95732b 100644
|
||||
--- a/migration/qemu-file.h
|
||||
+++ b/migration/qemu-file.h
|
||||
@@ -54,8 +54,8 @@ void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size,
|
||||
|
||||
size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset);
|
||||
size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size);
|
||||
-ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
|
||||
- const uint8_t *p, size_t size);
|
||||
+ssize_t qemu_put_compress_start(QEMUFile *f, uint8_t **dest_ptr);
|
||||
+void qemu_put_compress_end(QEMUFile *f, unsigned int v);
|
||||
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
|
||||
bool qemu_file_buffer_empty(QEMUFile *file);
|
||||
|
||||
diff --git a/migration/ram-compress.c b/migration/ram-compress.c
|
||||
index fa4388f6a6..2be344acbc 100644
|
||||
--- a/migration/ram-compress.c
|
||||
+++ b/migration/ram-compress.c
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
-
|
||||
#include "ram-compress.h"
|
||||
|
||||
#include "qemu/error-report.h"
|
||||
@@ -40,6 +39,7 @@
|
||||
#include "exec/ramblock.h"
|
||||
#include "ram.h"
|
||||
#include "migration-stats.h"
|
||||
+#include "exec/ram_addr.h"
|
||||
|
||||
static struct {
|
||||
int64_t pages;
|
||||
@@ -83,28 +83,22 @@ static QemuThread *decompress_threads;
|
||||
static QemuMutex decomp_done_lock;
|
||||
static QemuCond decomp_done_cond;
|
||||
|
||||
-static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||||
- RAMBlock *block, ram_addr_t offset,
|
||||
- uint8_t *source_buf);
|
||||
+static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block);
|
||||
|
||||
static void *do_data_compress(void *opaque)
|
||||
{
|
||||
CompressParam *param = opaque;
|
||||
RAMBlock *block;
|
||||
- ram_addr_t offset;
|
||||
CompressResult result;
|
||||
|
||||
qemu_mutex_lock(¶m->mutex);
|
||||
while (!param->quit) {
|
||||
if (param->trigger) {
|
||||
block = param->block;
|
||||
- offset = param->offset;
|
||||
param->trigger = false;
|
||||
qemu_mutex_unlock(¶m->mutex);
|
||||
|
||||
- result = do_compress_ram_page(param->file, ¶m->stream,
|
||||
- block, offset, param->originbuf);
|
||||
-
|
||||
+ result = do_compress_ram_page(param, block);
|
||||
qemu_mutex_lock(&comp_done_lock);
|
||||
param->done = true;
|
||||
param->result = result;
|
||||
@@ -204,15 +198,57 @@ exit:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||||
- RAMBlock *block, ram_addr_t offset,
|
||||
- uint8_t *source_buf)
|
||||
+/*
|
||||
+ * Compress size bytes of data start at p and store the compressed
|
||||
+ * data to the buffer of f.
|
||||
+ *
|
||||
+ * Since the file is dummy file with empty_ops, return -1 if f has no space to
|
||||
+ * save the compressed data.
|
||||
+ */
|
||||
+static ssize_t qemu_put_compression_data(CompressParam *param, size_t size)
|
||||
+{
|
||||
+ int err;
|
||||
+ uint8_t *dest = NULL;
|
||||
+ z_stream *stream = ¶m->stream;
|
||||
+ uint8_t *p = param->originbuf;
|
||||
+ QEMUFile *f = f = param->file;
|
||||
+ ssize_t blen = qemu_put_compress_start(f, &dest);
|
||||
+
|
||||
+ if (blen < compressBound(size)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ err = deflateReset(stream);
|
||||
+ if (err != Z_OK) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ stream->avail_in = size;
|
||||
+ stream->next_in = p;
|
||||
+ stream->avail_out = blen;
|
||||
+ stream->next_out = dest;
|
||||
+
|
||||
+ err = deflate(stream, Z_FINISH);
|
||||
+ if (err != Z_STREAM_END) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ blen = stream->next_out - dest;
|
||||
+ if (blen < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ qemu_put_compress_end(f, blen);
|
||||
+ return blen + sizeof(int32_t);
|
||||
+}
|
||||
+
|
||||
+static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block)
|
||||
{
|
||||
- uint8_t *p = block->host + offset;
|
||||
+ uint8_t *p = block->host + (param->offset & TARGET_PAGE_MASK);
|
||||
size_t page_size = qemu_target_page_size();
|
||||
int ret;
|
||||
|
||||
- assert(qemu_file_buffer_empty(f));
|
||||
+ assert(qemu_file_buffer_empty(param->file));
|
||||
|
||||
if (buffer_is_zero(p, page_size)) {
|
||||
return RES_ZEROPAGE;
|
||||
@@ -223,12 +259,12 @@ static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||||
* so that we can catch up the error during compression and
|
||||
* decompression
|
||||
*/
|
||||
- memcpy(source_buf, p, page_size);
|
||||
- ret = qemu_put_compression_data(f, stream, source_buf, page_size);
|
||||
+ memcpy(param->originbuf, p, page_size);
|
||||
+ ret = qemu_put_compression_data(param, page_size);
|
||||
if (ret < 0) {
|
||||
qemu_file_set_error(migrate_get_current()->to_dst_file, ret);
|
||||
error_report("compressed data failed!");
|
||||
- qemu_fflush(f);
|
||||
+ qemu_fflush(param->file);
|
||||
return RES_NONE;
|
||||
}
|
||||
return RES_COMPRESS;
|
||||
@@ -322,19 +358,20 @@ bool compress_page_with_multi_thread(RAMBlock *block, ram_addr_t offset,
|
||||
|
||||
/* return the size after decompression, or negative value on error */
|
||||
static int
|
||||
-qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
|
||||
- const uint8_t *source, size_t source_len)
|
||||
+qemu_uncompress_data(DecompressParam *param, uint8_t *dest, size_t pagesize)
|
||||
{
|
||||
int err;
|
||||
|
||||
+ z_stream *stream = ¶m->stream;
|
||||
+
|
||||
err = inflateReset(stream);
|
||||
if (err != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
- stream->avail_in = source_len;
|
||||
- stream->next_in = (uint8_t *)source;
|
||||
- stream->avail_out = dest_len;
|
||||
+ stream->avail_in = param->len;
|
||||
+ stream->next_in = param->compbuf;
|
||||
+ stream->avail_out = pagesize;
|
||||
stream->next_out = dest;
|
||||
|
||||
err = inflate(stream, Z_NO_FLUSH);
|
||||
@@ -350,20 +387,18 @@ static void *do_data_decompress(void *opaque)
|
||||
DecompressParam *param = opaque;
|
||||
unsigned long pagesize;
|
||||
uint8_t *des;
|
||||
- int len, ret;
|
||||
+ int ret;
|
||||
|
||||
qemu_mutex_lock(¶m->mutex);
|
||||
while (!param->quit) {
|
||||
if (param->des) {
|
||||
des = param->des;
|
||||
- len = param->len;
|
||||
param->des = 0;
|
||||
qemu_mutex_unlock(¶m->mutex);
|
||||
|
||||
pagesize = qemu_target_page_size();
|
||||
|
||||
- ret = qemu_uncompress_data(¶m->stream, des, pagesize,
|
||||
- param->compbuf, len);
|
||||
+ ret = qemu_uncompress_data(param, des, pagesize);
|
||||
if (ret < 0 && migrate_get_current()->decompress_error_check) {
|
||||
error_report("decompress data failed");
|
||||
qemu_file_set_error(decomp_file, ret);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
86
migration-Skip-only-empty-block-devicesi.patch
Normal file
86
migration-Skip-only-empty-block-devicesi.patch
Normal file
@ -0,0 +1,86 @@
|
||||
From 4506b31c0fff0b7a69ec4c7e264715ed70df75a8 Mon Sep 17 00:00:00 2001
|
||||
From: gaojiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 25 Mar 2024 22:13:43 +0800
|
||||
Subject: [PATCH] migration: Skip only empty block devicesi
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from 2e128776dc56f502c2ee41750afe83938f389528
|
||||
|
||||
The block .save_setup() handler calls a helper routine
|
||||
init_blk_migration() which builds a list of block devices to take into
|
||||
account for migration. When one device is found to be empty (sectors
|
||||
== 0), the loop exits and all the remaining devices are ignored. This
|
||||
is a regression introduced when bdrv_iterate() was removed.
|
||||
|
||||
Change that by skipping only empty devices.
|
||||
|
||||
Cc: Markus Armbruster <armbru@redhat.com>
|
||||
Cc: qemu-stable <qemu-stable@nongnu.org>
|
||||
Suggested-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Fixes: fea68bb ("block: Eliminate bdrv_iterate(), use bdrv_next()")
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240312120431.550054-1-clg@redhat.com
|
||||
[peterx: fix "Suggested-by:"]
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
migration/block.c | 5 ++++-
|
||||
tests/qemu-iotests/198.out | 2 --
|
||||
tests/qemu-iotests/206.out | 1 -
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/migration/block.c b/migration/block.c
|
||||
index a15f9bddcb..710ef6f490 100644
|
||||
--- a/migration/block.c
|
||||
+++ b/migration/block.c
|
||||
@@ -409,7 +409,10 @@ static int init_blk_migration(QEMUFile *f)
|
||||
}
|
||||
|
||||
sectors = bdrv_nb_sectors(bs);
|
||||
- if (sectors <= 0) {
|
||||
+ if (sectors == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (sectors < 0) {
|
||||
ret = sectors;
|
||||
bdrv_next_cleanup(&it);
|
||||
goto out;
|
||||
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
|
||||
index 62fb73fa3e..805494916f 100644
|
||||
--- a/tests/qemu-iotests/198.out
|
||||
+++ b/tests/qemu-iotests/198.out
|
||||
@@ -39,7 +39,6 @@ Format specific information:
|
||||
compression type: COMPRESSION_TYPE
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
- detached header: false
|
||||
hash alg: sha256
|
||||
cipher alg: aes-256
|
||||
uuid: 00000000-0000-0000-0000-000000000000
|
||||
@@ -85,7 +84,6 @@ Format specific information:
|
||||
compression type: COMPRESSION_TYPE
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
- detached header: false
|
||||
hash alg: sha256
|
||||
cipher alg: aes-256
|
||||
uuid: 00000000-0000-0000-0000-000000000000
|
||||
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
|
||||
index 979f00f9bf..7e95694777 100644
|
||||
--- a/tests/qemu-iotests/206.out
|
||||
+++ b/tests/qemu-iotests/206.out
|
||||
@@ -114,7 +114,6 @@ Format specific information:
|
||||
refcount bits: 16
|
||||
encrypt:
|
||||
ivgen alg: plain64
|
||||
- detached header: false
|
||||
hash alg: sha1
|
||||
cipher alg: aes-128
|
||||
uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
--
|
||||
2.27.0
|
||||
|
||||
54
migration-report-migration-related-thread-pid-to-lib.patch
Normal file
54
migration-report-migration-related-thread-pid-to-lib.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 7caa5d818e0fa0e1cee2513f2fde4e81f8b5cc13 Mon Sep 17 00:00:00 2001
|
||||
From: zhengchuan <zhengchuan@huawei.com>
|
||||
Date: Mon, 5 Dec 2022 20:52:25 +0800
|
||||
Subject: [PATCH] migration: report migration related thread pid to libvirt
|
||||
|
||||
in order to control migration thread cgroup,
|
||||
we need to report migration related thread pid to libvirt
|
||||
|
||||
Signed-off-by:zhengchuan<zhengchuan@huawei.com>
|
||||
---
|
||||
migration/migration.c | 3 +++
|
||||
qapi/migration.json | 12 ++++++++++++
|
||||
2 files changed, 15 insertions(+)
|
||||
|
||||
diff --git a/migration/migration.c b/migration/migration.c
|
||||
index 3ce04b2aaf..7c2fdde26b 100644
|
||||
--- a/migration/migration.c
|
||||
+++ b/migration/migration.c
|
||||
@@ -3299,6 +3299,9 @@ static void *migration_thread(void *opaque)
|
||||
MigThrError thr_error;
|
||||
bool urgent = false;
|
||||
|
||||
+ /* report migration thread pid to libvirt */
|
||||
+ qapi_event_send_migration_pid(qemu_get_thread_id());
|
||||
+
|
||||
thread = migration_threads_add("live_migration", qemu_get_thread_id());
|
||||
|
||||
rcu_register_thread();
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index 29af841f4e..b442d0d878 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -1447,6 +1447,18 @@
|
||||
{ 'event': 'MIGRATION_PASS',
|
||||
'data': { 'pass': 'int' } }
|
||||
|
||||
+##
|
||||
+# @MIGRATION_PID:
|
||||
+#
|
||||
+# Emitted when migration thread appear
|
||||
+#
|
||||
+# @pid: pid of migration thread
|
||||
+#
|
||||
+# Since: EulerOS Virtual
|
||||
+##
|
||||
+{ 'event': 'MIGRATION_PID',
|
||||
+ 'data': { 'pid': 'int' } }
|
||||
+
|
||||
##
|
||||
# @COLOMessage:
|
||||
#
|
||||
--
|
||||
2.27.0
|
||||
|
||||
62
migration-report-multiFd-related-thread-pid-to-libvi.patch
Normal file
62
migration-report-multiFd-related-thread-pid-to-libvi.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From e387eaeef8845993a437ad19eaf988fb101d3fdd Mon Sep 17 00:00:00 2001
|
||||
From: zhengchuan <zhengchuan@huawei.com>
|
||||
Date: Mon, 5 Dec 2022 20:56:35 +0800
|
||||
Subject: [PATCH] migration: report multiFd related thread pid to libvirt
|
||||
|
||||
report multiFd related thread pid to libvirt in order to
|
||||
pin multiFd thread to different cpu.
|
||||
|
||||
Signed-off-by:zhengchuan<zhengchuan@huawei.com>
|
||||
---
|
||||
migration/multifd.c | 4 ++++
|
||||
qapi/migration.json | 12 ++++++++++++
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/migration/multifd.c b/migration/multifd.c
|
||||
index 409460684f..7d373a245e 100644
|
||||
--- a/migration/multifd.c
|
||||
+++ b/migration/multifd.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "exec/ramblock.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
+#include "qapi/qapi-events-migration.h"
|
||||
#include "ram.h"
|
||||
#include "migration.h"
|
||||
#include "migration-stats.h"
|
||||
@@ -657,6 +658,9 @@ static void *multifd_send_thread(void *opaque)
|
||||
|
||||
thread = migration_threads_add(p->name, qemu_get_thread_id());
|
||||
|
||||
+ /* report multifd thread pid to libvirt */
|
||||
+ qapi_event_send_migration_multifd_pid(qemu_get_thread_id());
|
||||
+
|
||||
trace_multifd_send_thread_start(p->id);
|
||||
rcu_register_thread();
|
||||
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index b442d0d878..5d0855a1d8 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -1447,6 +1447,18 @@
|
||||
{ 'event': 'MIGRATION_PASS',
|
||||
'data': { 'pass': 'int' } }
|
||||
|
||||
+##
|
||||
+# @MIGRATION_MULTIFD_PID:
|
||||
+#
|
||||
+# Emitted when multifd thread appear
|
||||
+#
|
||||
+# @pid: pid of multifd thread
|
||||
+#
|
||||
+# Since: EulerOS Virtual
|
||||
+##
|
||||
+{ 'event': 'MIGRATION_MULTIFD_PID',
|
||||
+ 'data': { 'pid': 'int' } }
|
||||
+
|
||||
##
|
||||
# @MIGRATION_PID:
|
||||
#
|
||||
--
|
||||
2.27.0
|
||||
|
||||
47
migration-skip-cache_drop-for-bios-bootloader-and-nv.patch
Normal file
47
migration-skip-cache_drop-for-bios-bootloader-and-nv.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From dfb9372702b2fb994392b8a6e8a39964c2656ae6 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 08:49:41 +0800
|
||||
Subject: [PATCH] migration: skip cache_drop for bios bootloader and nvram
|
||||
template
|
||||
|
||||
Qemu enabled page cache dropping for raw device on the destionation host
|
||||
during shared storage migration.
|
||||
However, fsync may take 300ms to multiple seconds to return in multiple-migration
|
||||
scene, because all domains in a host share bios bootloader file, skip cache_drop
|
||||
for bios bootloader and nvram template to avoid downtime increase.
|
||||
---
|
||||
block.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index b7cb963929..3bfd4be6b4 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -68,6 +68,9 @@
|
||||
|
||||
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
||||
|
||||
+#define DEFAULT_BIOS_BOOT_LOADER_DIR "/usr/share/edk2"
|
||||
+#define DEFAULT_NVRAM_TEMPLATE_DIR "/var/lib/libvirt/qemu/nvram"
|
||||
+
|
||||
/* Protected by BQL */
|
||||
static QTAILQ_HEAD(, BlockDriverState) graph_bdrv_states =
|
||||
QTAILQ_HEAD_INITIALIZER(graph_bdrv_states);
|
||||
@@ -7017,7 +7020,13 @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||
assert(!(bs->open_flags & BDRV_O_INACTIVE));
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
- if (bs->drv->bdrv_co_invalidate_cache) {
|
||||
+ /*
|
||||
+ * It's not necessary for bios bootloader and nvram template to drop cache
|
||||
+ * when migration, skip this step for them to avoid dowtime increase.
|
||||
+ */
|
||||
+ if (bs->drv->bdrv_co_invalidate_cache &&
|
||||
+ !strstr(bs->filename, DEFAULT_BIOS_BOOT_LOADER_DIR) &&
|
||||
+ !strstr(bs->filename, DEFAULT_NVRAM_TEMPLATE_DIR)) {
|
||||
bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
--
|
||||
2.27.0
|
||||
|
||||
96
monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch
Normal file
96
monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch
Normal file
@ -0,0 +1,96 @@
|
||||
From a344d8636168ba5f034a908d3394ef88d36133dd Mon Sep 17 00:00:00 2001
|
||||
From: Yan Wang <wangyan122@huawei.com>
|
||||
Date: Thu, 10 Feb 2022 11:18:13 +0800
|
||||
Subject: [PATCH] monitor: Discard BLOCK_IO_ERROR event when VM rebooted
|
||||
|
||||
Throttled event like QAPI_EVENT_BLOCK_IO_ERROR may be queued
|
||||
to limit event rate. Event may be delivered when VM is rebooted
|
||||
if the event was queued in the *monitor_qapi_event_state* hash table.
|
||||
Which may casue VM pause and other related problems.
|
||||
Such as seabios blocked during virtio-scsi initialization:
|
||||
vring_add_buf(vq, sg, out_num, in_num, 0, 0);
|
||||
vring_kick(vp, vq, 1);
|
||||
------------> VM paused here <-----------
|
||||
/* Wait for reply */
|
||||
while (!vring_more_used(vq)) usleep(5);
|
||||
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
include/monitor/monitor.h | 2 ++
|
||||
monitor/monitor.c | 29 +++++++++++++++++++++++++++++
|
||||
system/runstate.c | 1 +
|
||||
3 files changed, 32 insertions(+)
|
||||
|
||||
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
|
||||
index 965f5d5450..60079086a8 100644
|
||||
--- a/include/monitor/monitor.h
|
||||
+++ b/include/monitor/monitor.h
|
||||
@@ -63,4 +63,6 @@ void monitor_register_hmp_info_hrt(const char *name,
|
||||
int error_vprintf_unless_qmp(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
|
||||
int error_printf_unless_qmp(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
|
||||
|
||||
+void monitor_qapi_event_discard_io_error(void);
|
||||
+
|
||||
#endif /* MONITOR_H */
|
||||
diff --git a/monitor/monitor.c b/monitor/monitor.c
|
||||
index e540c1334a..8d59a76612 100644
|
||||
--- a/monitor/monitor.c
|
||||
+++ b/monitor/monitor.c
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "qemu/option.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "trace.h"
|
||||
+#include "qemu/log.h"
|
||||
+#include "qapi/qmp/qobject.h"
|
||||
|
||||
/*
|
||||
* To prevent flooding clients, events can be throttled. The
|
||||
@@ -787,6 +789,33 @@ int monitor_init_opts(QemuOpts *opts, Error **errp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+void monitor_qapi_event_discard_io_error(void)
|
||||
+{
|
||||
+ GHashTableIter event_iter;
|
||||
+ MonitorQAPIEventState *evstate;
|
||||
+ gpointer key, value;
|
||||
+ GString *json;
|
||||
+
|
||||
+ qemu_mutex_lock(&monitor_lock);
|
||||
+ g_hash_table_iter_init(&event_iter, monitor_qapi_event_state);
|
||||
+ while (g_hash_table_iter_next(&event_iter, &key, &value)) {
|
||||
+ evstate = key;
|
||||
+ /* Only QAPI_EVENT_BLOCK_IO_ERROR is discarded */
|
||||
+ if (evstate->event == QAPI_EVENT_BLOCK_IO_ERROR) {
|
||||
+ g_hash_table_iter_remove(&event_iter);
|
||||
+ json = qobject_to_json(QOBJECT(evstate->qdict));
|
||||
+ qemu_log(" %s event discarded\n", json->str);
|
||||
+ timer_del(evstate->timer);
|
||||
+ timer_free(evstate->timer);
|
||||
+ qobject_unref(evstate->data);
|
||||
+ qobject_unref(evstate->qdict);
|
||||
+ g_string_free(json, true);
|
||||
+ g_free(evstate);
|
||||
+ }
|
||||
+ }
|
||||
+ qemu_mutex_unlock(&monitor_lock);
|
||||
+}
|
||||
+
|
||||
QemuOptsList qemu_mon_opts = {
|
||||
.name = "mon",
|
||||
.implied_opt_name = "chardev",
|
||||
diff --git a/system/runstate.c b/system/runstate.c
|
||||
index 9d3f627fee..62e6db8d42 100644
|
||||
--- a/system/runstate.c
|
||||
+++ b/system/runstate.c
|
||||
@@ -503,6 +503,7 @@ void qemu_system_reset(ShutdownCause reason)
|
||||
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
|
||||
}
|
||||
cpu_synchronize_all_post_reset();
|
||||
+ monitor_qapi_event_discard_io_error();
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.27.0
|
||||
|
||||
111
monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch
Normal file
111
monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From c6b183a4c3c63454dea39be26b0fb773ec04887e Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 14:13:05 +0800
|
||||
Subject: [PATCH] monitor/qmp: drop inflight rsp if qmp client broken
|
||||
|
||||
If libvirt restart while qemu is handle qmp message, libvirt will
|
||||
reconnect qemu monitor socket, and query status of qemu by qmp.
|
||||
But qemu may return last qmp respond to new connect socket, and libvirt
|
||||
recv unexpected respond, So libvirt think qemu is abnormal, and will
|
||||
kill qemu.
|
||||
|
||||
This patch add qmp connect id, while reconnect id will change. While
|
||||
respond to libvirt, judge if id is same, if not, drop this respond.
|
||||
---
|
||||
monitor/monitor-internal.h | 1 +
|
||||
monitor/qmp.c | 19 +++++++++++--------
|
||||
2 files changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
|
||||
index 252de85681..d7842fa464 100644
|
||||
--- a/monitor/monitor-internal.h
|
||||
+++ b/monitor/monitor-internal.h
|
||||
@@ -144,6 +144,7 @@ typedef struct {
|
||||
const QmpCommandList *commands;
|
||||
bool capab_offered[QMP_CAPABILITY__MAX]; /* capabilities offered */
|
||||
bool capab[QMP_CAPABILITY__MAX]; /* offered and accepted */
|
||||
+ uint64_t qmp_client_id; /*qmp client id, update if peer disconnect */
|
||||
/*
|
||||
* Protects qmp request/response queue.
|
||||
* Take monitor_lock first when you need both.
|
||||
diff --git a/monitor/qmp.c b/monitor/qmp.c
|
||||
index 6eee450fe4..8f7671c5f1 100644
|
||||
--- a/monitor/qmp.c
|
||||
+++ b/monitor/qmp.c
|
||||
@@ -149,18 +149,19 @@ void qmp_send_response(MonitorQMP *mon, const QDict *rsp)
|
||||
* Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP.
|
||||
* Nothing is emitted then.
|
||||
*/
|
||||
-static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp)
|
||||
+static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp, uint64_t req_client_id)
|
||||
{
|
||||
- if (rsp) {
|
||||
- qmp_send_response(mon, rsp);
|
||||
+ if (!rsp || (mon->qmp_client_id != req_client_id)) {
|
||||
+ return;
|
||||
}
|
||||
+ qmp_send_response(mon, rsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs outside of coroutine context for OOB commands, but in
|
||||
* coroutine context for everything else.
|
||||
*/
|
||||
-static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req)
|
||||
+static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req, uint64_t req_client_id)
|
||||
{
|
||||
QDict *rsp;
|
||||
QDict *error;
|
||||
@@ -180,7 +181,7 @@ static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req)
|
||||
}
|
||||
}
|
||||
|
||||
- monitor_qmp_respond(mon, rsp);
|
||||
+ monitor_qmp_respond(mon, rsp, req_client_id);
|
||||
qobject_unref(rsp);
|
||||
}
|
||||
|
||||
@@ -340,13 +341,13 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||
trace_monitor_qmp_cmd_in_band(id_json->str);
|
||||
g_string_free(id_json, true);
|
||||
}
|
||||
- monitor_qmp_dispatch(mon, req_obj->req);
|
||||
+ monitor_qmp_dispatch(mon, req_obj->req, mon->qmp_client_id);
|
||||
} else {
|
||||
assert(req_obj->err);
|
||||
trace_monitor_qmp_err_in_band(error_get_pretty(req_obj->err));
|
||||
rsp = qmp_error_response(req_obj->err);
|
||||
req_obj->err = NULL;
|
||||
- monitor_qmp_respond(mon, rsp);
|
||||
+ monitor_qmp_respond(mon, rsp, mon->qmp_client_id);
|
||||
qobject_unref(rsp);
|
||||
}
|
||||
|
||||
@@ -402,7 +403,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
|
||||
trace_monitor_qmp_cmd_out_of_band(id_json->str);
|
||||
g_string_free(id_json, true);
|
||||
}
|
||||
- monitor_qmp_dispatch(mon, req);
|
||||
+ monitor_qmp_dispatch(mon, req, mon->qmp_client_id);
|
||||
qobject_unref(req);
|
||||
return;
|
||||
}
|
||||
@@ -486,6 +487,7 @@ static void monitor_qmp_event(void *opaque, QEMUChrEvent event)
|
||||
mon_refcount++;
|
||||
break;
|
||||
case CHR_EVENT_CLOSED:
|
||||
+ mon->qmp_client_id++;
|
||||
/*
|
||||
* Note: this is only useful when the output of the chardev
|
||||
* backend is still open. For example, when the backend is
|
||||
@@ -539,6 +541,7 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
|
||||
}
|
||||
qemu_chr_fe_set_echo(&mon->common.chr, true);
|
||||
|
||||
+ mon->qmp_client_id = 1;
|
||||
/* Note: we run QMP monitor in I/O thread when @chr supports that */
|
||||
monitor_data_init(&mon->common, true, false,
|
||||
qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT));
|
||||
--
|
||||
2.27.0
|
||||
|
||||
45
nbd-server.c-fix-invalid-read-after-client-was-alrea.patch
Normal file
45
nbd-server.c-fix-invalid-read-after-client-was-alrea.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 81b4091eee81fe3871d836b1a684e27828cdc2be Mon Sep 17 00:00:00 2001
|
||||
From: WangJian <wangjian161@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 10:42:33 +0800
|
||||
Subject: [PATCH] nbd/server.c: fix invalid read after client was already free
|
||||
|
||||
In the process of NBD equipment pressurization, executing QEMU NBD will
|
||||
lead to the failure of IO distribution and go to NBD_ Out process of trip().
|
||||
If two or more IO go to the out process, client NBD will release in nbd_request_put().
|
||||
The user after free problem that is read again in close().
|
||||
Through the NBD_ Save the value of client > closing before the out process in trip
|
||||
to solve the use after free problem.
|
||||
|
||||
Signed-off-by: wangjian161 <wangjian161@huawei.com>
|
||||
---
|
||||
nbd/server.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/nbd/server.c b/nbd/server.c
|
||||
index 895cf0a752..e8baed9705 100644
|
||||
--- a/nbd/server.c
|
||||
+++ b/nbd/server.c
|
||||
@@ -2939,6 +2939,7 @@ static coroutine_fn void nbd_trip(void *opaque)
|
||||
NBDRequestData *req;
|
||||
NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */
|
||||
int ret;
|
||||
+ bool client_closing;
|
||||
Error *local_err = NULL;
|
||||
|
||||
trace_nbd_trip();
|
||||
@@ -3023,8 +3024,11 @@ disconnect:
|
||||
if (local_err) {
|
||||
error_reportf_err(local_err, "Disconnect client, due to: ");
|
||||
}
|
||||
+ client_closing = client->closing;
|
||||
nbd_request_put(req);
|
||||
- client_close(client, true);
|
||||
+ if (!client_closing) {
|
||||
+ client_close(client, true);
|
||||
+ }
|
||||
nbd_client_put(client);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
51
net-dump.c-Suppress-spurious-compiler-warning.patch
Normal file
51
net-dump.c-Suppress-spurious-compiler-warning.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 6999f07558308ee6b7d63e46ca554a0b702948d6 Mon Sep 17 00:00:00 2001
|
||||
From: liuxiangdong <liuxiangdong5@huawei.com>
|
||||
Date: Tue, 8 Feb 2022 15:10:25 +0800
|
||||
Subject: [PATCH] net/dump.c: Suppress spurious compiler warning
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Compiling with gcc version 11.2.0 (Ubuntu 11.2.0-13ubuntu1) results in
|
||||
a (spurious) warning:
|
||||
|
||||
In function ‘dump_receive_iov’,
|
||||
inlined from ‘filter_dump_receive_iov’ at ../net/dump.c:157:5:
|
||||
../net/dump.c:89:9: error: ‘writev’ specified size 18446744073709551600
|
||||
exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
|
||||
89 | if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
In file included from /home/ptomsich/qemu/include/qemu/osdep.h:108,
|
||||
from ../net/dump.c:25:
|
||||
../net/dump.c: In function ‘filter_dump_receive_iov’:
|
||||
/usr/include/x86_64-linux-gnu/sys/uio.h:52:16: note: in a call to function
|
||||
‘writev’ declared with attribute ‘read_only (2, 3)’
|
||||
52 | extern ssize_t writev (int __fd, const struct iovec *__iovec, int
|
||||
__count)
|
||||
| ^~~~~~
|
||||
cc1: all warnings being treated as errors
|
||||
|
||||
This change helps that version of GCC to understand what is going on
|
||||
and suppresses this warning.
|
||||
|
||||
Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu>
|
||||
---
|
||||
net/dump.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/dump.c b/net/dump.c
|
||||
index 16073f2458..d880a7e299 100644
|
||||
--- a/net/dump.c
|
||||
+++ b/net/dump.c
|
||||
@@ -87,7 +87,7 @@ static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt,
|
||||
dumpiov[0].iov_len = sizeof(hdr);
|
||||
cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, offset, caplen);
|
||||
|
||||
- if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
|
||||
+ if (writev(s->fd, &dumpiov[0], cnt + 1) != sizeof(hdr) + caplen) {
|
||||
error_report("network dump write error - stopping dump");
|
||||
close(s->fd);
|
||||
s->fd = -1;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
58
net-eepro100-validate-various-address-valuesi-CVE-20.patch
Normal file
58
net-eepro100-validate-various-address-valuesi-CVE-20.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 6e6215b3ad0c8eac918bca9e2b5bb661e27f2fed Mon Sep 17 00:00:00 2001
|
||||
From: zhouli57 <zhouli57@huawei.com>
|
||||
Date: Sat, 18 Dec 2021 09:39:57 +0800
|
||||
Subject: [PATCH] net: eepro100: validate various address
|
||||
valuesi(CVE-2021-20255)
|
||||
|
||||
fix CVE-2021-20255
|
||||
|
||||
patch link: https://lists.gnu.org/archive/html/qemu-devel/2021-02/msg06098.html
|
||||
|
||||
fix CVE-2021-20255, sync patch from ostms platform.
|
||||
|
||||
Signed-off-by: zhouli57 <zhouli57@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
hw/net/eepro100.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
|
||||
index 69e1c4bb89..f6204ec059 100644
|
||||
--- a/hw/net/eepro100.c
|
||||
+++ b/hw/net/eepro100.c
|
||||
@@ -279,6 +279,9 @@ typedef struct {
|
||||
/* Quasi static device properties (no need to save them). */
|
||||
uint16_t stats_size;
|
||||
bool has_extended_tcb_support;
|
||||
+
|
||||
+ /* Flag to avoid recursions. */
|
||||
+ bool busy;
|
||||
} EEPRO100State;
|
||||
|
||||
/* Word indices in EEPROM. */
|
||||
@@ -844,6 +847,14 @@ static void action_command(EEPRO100State *s)
|
||||
Therefore we limit the number of iterations. */
|
||||
unsigned max_loop_count = 16;
|
||||
|
||||
+ if (s->busy) {
|
||||
+ /* Prevent recursions. */
|
||||
+ logout("recursion in %s:%u\n", __FILE__, __LINE__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ s->busy = true;
|
||||
+
|
||||
for (;;) {
|
||||
bool bit_el;
|
||||
bool bit_s;
|
||||
@@ -940,6 +951,7 @@ static void action_command(EEPRO100State *s)
|
||||
}
|
||||
TRACE(OTHER, logout("CU list empty\n"));
|
||||
/* List is empty. Now CU is idle or suspended. */
|
||||
+ s->busy = false;
|
||||
}
|
||||
|
||||
static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
57
oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch
Normal file
57
oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From b6c45f5ea5d1a379ac0a507cf59345c573b27cc8 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 14:21:39 +0800
|
||||
Subject: [PATCH] oslib-posix: optimise vm startup time for 1G hugepage
|
||||
|
||||
It takes quit a long time to clear 1G-hugepage, which makes glibc
|
||||
pthread_create quit slow.
|
||||
Create touch_pages threads in advance, and then handle the touch_pages
|
||||
callback. Only read lock is held here.
|
||||
---
|
||||
util/oslib-posix.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
|
||||
index e86fd64e09..9ca3fee2b8 100644
|
||||
--- a/util/oslib-posix.c
|
||||
+++ b/util/oslib-posix.c
|
||||
@@ -88,6 +88,8 @@ static QemuMutex sigbus_mutex;
|
||||
static QemuMutex page_mutex;
|
||||
static QemuCond page_cond;
|
||||
|
||||
+static int started_num_threads;
|
||||
+
|
||||
int qemu_get_thread_id(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
@@ -344,6 +346,10 @@ static void *do_touch_pages(void *arg)
|
||||
}
|
||||
qemu_mutex_unlock(&page_mutex);
|
||||
|
||||
+ while (started_num_threads != memset_args->context.num_threads) {
|
||||
+ smp_mb();
|
||||
+ }
|
||||
+
|
||||
/* unblock SIGBUS */
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGBUS);
|
||||
@@ -448,7 +454,7 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
||||
context.threads = g_new0(MemsetThread, context.num_threads);
|
||||
numpages_per_thread = numpages / context.num_threads;
|
||||
leftover = numpages % context.num_threads;
|
||||
- for (i = 0; i < context.num_threads; i++) {
|
||||
+ for (i = 0, started_num_threads = 0; i < context.num_threads; i++) {
|
||||
context.threads[i].addr = addr;
|
||||
context.threads[i].numpages = numpages_per_thread + (i < leftover);
|
||||
context.threads[i].hpagesize = hpagesize;
|
||||
@@ -464,6 +470,7 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
||||
QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
addr += context.threads[i].numpages * hpagesize;
|
||||
+ started_num_threads++;
|
||||
}
|
||||
|
||||
if (!use_madv_populate_write) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
99
pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch
Normal file
99
pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch
Normal file
@ -0,0 +1,99 @@
|
||||
From 3c4b4c4fc3c71b375490233bb9209763d7094ee9 Mon Sep 17 00:00:00 2001
|
||||
From: Yan Wang <wangyan122@huawei.com>
|
||||
Date: Tue, 8 Feb 2022 16:10:31 +0800
|
||||
Subject: [PATCH] pcie: Add pcie-root-port fast plug/unplug feature
|
||||
|
||||
If a device is plugged in the pcie-root-port when VM kernel is
|
||||
booting, the kernel may wrongly disable the device.
|
||||
This bug was brought in by two patches of the linux kernel:
|
||||
|
||||
https://patchwork.kernel.org/patch/10575355/
|
||||
https://patchwork.kernel.org/patch/10766219/
|
||||
|
||||
VM runtime like kata uses this feature to boot microVM,
|
||||
so we must fix it up. We hack into the pcie native hotplug
|
||||
patch so that hotplug/unplug will work under this circumstance.
|
||||
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
hw/core/machine.c | 2 ++
|
||||
hw/pci-bridge/gen_pcie_root_port.c | 2 ++
|
||||
hw/pci/pcie.c | 13 ++++++++++++-
|
||||
include/hw/pci/pcie_port.h | 3 +++
|
||||
4 files changed, 19 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index 0c17398141..965682619b 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -160,6 +160,8 @@ const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
||||
GlobalProperty hw_compat_3_1[] = {
|
||||
{ "pcie-root-port", "x-speed", "2_5" },
|
||||
{ "pcie-root-port", "x-width", "1" },
|
||||
+ { "pcie-root-port", "fast-plug", "0" },
|
||||
+ { "pcie-root-port", "fast-unplug", "0" },
|
||||
{ "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
|
||||
{ "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
|
||||
{ "tpm-crb", "ppi", "false" },
|
||||
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
|
||||
index 1ce4e7beba..1e1ab5bb19 100644
|
||||
--- a/hw/pci-bridge/gen_pcie_root_port.c
|
||||
+++ b/hw/pci-bridge/gen_pcie_root_port.c
|
||||
@@ -145,6 +145,8 @@ static Property gen_rp_props[] = {
|
||||
speed, PCIE_LINK_SPEED_16),
|
||||
DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
|
||||
width, PCIE_LINK_WIDTH_32),
|
||||
+ DEFINE_PROP_UINT8("fast-plug", PCIESlot, fast_plug, 0),
|
||||
+ DEFINE_PROP_UINT8("fast-unplug", PCIESlot, fast_unplug, 0),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
|
||||
index dccf204451..04fbd794a8 100644
|
||||
--- a/hw/pci/pcie.c
|
||||
+++ b/hw/pci/pcie.c
|
||||
@@ -555,6 +555,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
|
||||
uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP);
|
||||
uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
|
||||
+ PCIESlot *s = PCIE_SLOT(hotplug_pdev);
|
||||
|
||||
/* Check if hot-unplug is disabled on the slot */
|
||||
if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) {
|
||||
@@ -600,7 +601,17 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
- pcie_cap_slot_push_attention_button(hotplug_pdev);
|
||||
+ if ((pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) && s->fast_plug) {
|
||||
+ pci_word_test_and_clear_mask(pci_dev->config + pci_dev->exp.exp_cap + PCI_EXP_LNKSTA,
|
||||
+ PCI_EXP_LNKSTA_DLLLA);
|
||||
+ }
|
||||
+
|
||||
+ if (s->fast_unplug) {
|
||||
+ pcie_cap_slot_event(hotplug_pdev,
|
||||
+ PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
|
||||
+ } else {
|
||||
+ pcie_cap_slot_push_attention_button(hotplug_pdev);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* pci express slot for pci express root/downstream port
|
||||
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
|
||||
index 90e6cf45b8..7148a0959b 100644
|
||||
--- a/include/hw/pci/pcie_port.h
|
||||
+++ b/include/hw/pci/pcie_port.h
|
||||
@@ -56,6 +56,9 @@ struct PCIESlot {
|
||||
uint8_t chassis;
|
||||
uint16_t slot;
|
||||
|
||||
+ uint8_t fast_plug;
|
||||
+ uint8_t fast_unplug;
|
||||
+
|
||||
PCIExpLinkSpeed speed;
|
||||
PCIExpLinkWidth width;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
50
pcie-Compat-with-devices-which-do-not-support-Link-W.patch
Normal file
50
pcie-Compat-with-devices-which-do-not-support-Link-W.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 6c72e65d57dc2a7d811f76a126a9a006abd0ab75 Mon Sep 17 00:00:00 2001
|
||||
From: fangying <fangying1@huawei.com>
|
||||
Date: Wed, 18 Mar 2020 12:51:33 +0800
|
||||
Subject: [PATCH] pcie: Compat with devices which do not support Link Width,
|
||||
such as ioh3420
|
||||
|
||||
We hack into PCI_EXP_LNKCAP to support device fast plug/unplug
|
||||
for pcie-root-port. However some devices like ioh3420 does not
|
||||
suport it, so PCI_EXP_LNKCAP is not set for such devices.
|
||||
|
||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
hw/pci/pcie.c | 13 ++++++-------
|
||||
1 file changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
|
||||
index 6db0cf69cd..dccf204451 100644
|
||||
--- a/hw/pci/pcie.c
|
||||
+++ b/hw/pci/pcie.c
|
||||
@@ -97,13 +97,6 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
- /* Clear and fill LNKCAP from what was configured above */
|
||||
- pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
- PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
|
||||
- pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
- QEMU_PCI_EXP_LNKCAP_MLW(s->width) |
|
||||
- QEMU_PCI_EXP_LNKCAP_MLS(s->speed));
|
||||
-
|
||||
/*
|
||||
* Link bandwidth notification is required for all root ports and
|
||||
* downstream ports supporting links wider than x1 or multiple link
|
||||
@@ -111,6 +104,12 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
|
||||
*/
|
||||
if (s->width > QEMU_PCI_EXP_LNK_X1 ||
|
||||
s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
|
||||
+ /* Clear and fill LNKCAP from what was configured above */
|
||||
+ pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
+ PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
|
||||
+ pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
+ QEMU_PCI_EXP_LNKCAP_MLW(s->width) |
|
||||
+ QEMU_PCI_EXP_LNKCAP_MLS(s->speed));
|
||||
pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
|
||||
PCI_EXP_LNKCAP_LBNC);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
127
physmem-gdbstub-Common-helping-funcs-changes-to-unre.patch
Normal file
127
physmem-gdbstub-Common-helping-funcs-changes-to-unre.patch
Normal file
@ -0,0 +1,127 @@
|
||||
From 8fa5af7de07d9bc2535ea8fab087d509795e3579 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Sun, 6 Aug 2023 22:12:52 +0000
|
||||
Subject: [PATCH] physmem,gdbstub: Common helping funcs/changes to *unrealize*
|
||||
vCPU
|
||||
|
||||
Supporting vCPU Hotplug for ARM arch also means introducing new functionality of
|
||||
unrealizing the ARMCPU. This requires some new common functions.
|
||||
|
||||
Defining them as part of architecture independent change so that this code could
|
||||
be reused by other interested parties.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
---
|
||||
gdbstub/gdbstub.c | 6 ++++++
|
||||
include/exec/cpu-common.h | 8 ++++++++
|
||||
include/exec/gdbstub.h | 1 +
|
||||
include/hw/core/cpu.h | 1 +
|
||||
system/physmem.c | 25 +++++++++++++++++++++++++
|
||||
5 files changed, 41 insertions(+)
|
||||
|
||||
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
|
||||
index 46d752bbc2..f16006d2a8 100644
|
||||
--- a/gdbstub/gdbstub.c
|
||||
+++ b/gdbstub/gdbstub.c
|
||||
@@ -582,6 +582,12 @@ void gdb_register_coprocessor(CPUState *cpu,
|
||||
}
|
||||
}
|
||||
|
||||
+void gdb_unregister_coprocessor_all(CPUState *cpu)
|
||||
+{
|
||||
+ g_array_free(cpu->gdb_regs, true);
|
||||
+ cpu->gdb_regs = NULL;
|
||||
+}
|
||||
+
|
||||
static void gdb_process_breakpoint_remove_all(GDBProcess *p)
|
||||
{
|
||||
CPUState *cpu = gdb_get_first_cpu_in_process(p);
|
||||
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
|
||||
index 41115d8919..2a3d4aa1c8 100644
|
||||
--- a/include/exec/cpu-common.h
|
||||
+++ b/include/exec/cpu-common.h
|
||||
@@ -139,6 +139,14 @@ size_t qemu_ram_pagesize_largest(void);
|
||||
*/
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr);
|
||||
+/**
|
||||
+ * cpu_address_space_destroy:
|
||||
+ * @cpu: CPU for which address space needs to be destroyed
|
||||
+ * @asidx: integer index of this address space
|
||||
+ *
|
||||
+ * Note that with KVM only one address space is supported.
|
||||
+ */
|
||||
+void cpu_address_space_destroy(CPUState *cpu, int asidx);
|
||||
|
||||
void cpu_physical_memory_rw(hwaddr addr, void *buf,
|
||||
hwaddr len, bool is_write);
|
||||
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
|
||||
index d8a3c56fa2..d123b838c2 100644
|
||||
--- a/include/exec/gdbstub.h
|
||||
+++ b/include/exec/gdbstub.h
|
||||
@@ -39,6 +39,7 @@ typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
|
||||
void gdb_register_coprocessor(CPUState *cpu,
|
||||
gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
|
||||
int num_regs, const char *xml, int g_pos);
|
||||
+void gdb_unregister_coprocessor_all(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* gdbserver_start: start the gdb server
|
||||
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
||||
index 0ca778eb75..6dbe163548 100644
|
||||
--- a/include/hw/core/cpu.h
|
||||
+++ b/include/hw/core/cpu.h
|
||||
@@ -496,6 +496,7 @@ struct CPUState {
|
||||
QSIMPLEQ_HEAD(, qemu_work_item) work_list;
|
||||
|
||||
CPUAddressSpace *cpu_ases;
|
||||
+ int cpu_ases_ref_count;
|
||||
int num_ases;
|
||||
AddressSpace *as;
|
||||
MemoryRegion *memory;
|
||||
diff --git a/system/physmem.c b/system/physmem.c
|
||||
index 247c252e53..299174ad91 100644
|
||||
--- a/system/physmem.c
|
||||
+++ b/system/physmem.c
|
||||
@@ -761,6 +761,7 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
|
||||
if (!cpu->cpu_ases) {
|
||||
cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
|
||||
+ cpu->cpu_ases_ref_count = cpu->num_ases;
|
||||
}
|
||||
|
||||
newas = &cpu->cpu_ases[asidx];
|
||||
@@ -774,6 +775,30 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
}
|
||||
}
|
||||
|
||||
+void cpu_address_space_destroy(CPUState *cpu, int asidx)
|
||||
+{
|
||||
+ CPUAddressSpace *cpuas;
|
||||
+
|
||||
+ assert(asidx < cpu->num_ases);
|
||||
+ assert(asidx == 0 || !kvm_enabled());
|
||||
+ assert(cpu->cpu_ases);
|
||||
+
|
||||
+ cpuas = &cpu->cpu_ases[asidx];
|
||||
+ if (tcg_enabled()) {
|
||||
+ memory_listener_unregister(&cpuas->tcg_as_listener);
|
||||
+ }
|
||||
+
|
||||
+ address_space_destroy(cpuas->as);
|
||||
+ g_free_rcu(cpuas->as, rcu);
|
||||
+
|
||||
+ if (cpu->cpu_ases_ref_count == 1) {
|
||||
+ g_free(cpu->cpu_ases);
|
||||
+ cpu->cpu_ases = NULL;
|
||||
+ }
|
||||
+
|
||||
+ cpu->cpu_ases_ref_count--;
|
||||
+}
|
||||
+
|
||||
AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
|
||||
{
|
||||
/* Return the AddressSpace corresponding to the specified index */
|
||||
--
|
||||
2.27.0
|
||||
|
||||
42
pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch
Normal file
42
pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From e730214f4485ad444d8a1db9a284da53f407e8da Mon Sep 17 00:00:00 2001
|
||||
From: Ying Fang <fangying1@huawei.com>
|
||||
Date: Mon, 29 Jul 2019 16:16:35 +0800
|
||||
Subject: [PATCH] pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff
|
||||
|
||||
We can enable ACPI when AArch64 Linux is booted with QEMU and UEFI (AAVMF).
|
||||
When VM is booting and the SBSA driver has not initialized, writting data
|
||||
that exceds 32 bytes will cause the read FIFO full and proceeding data will
|
||||
be lost. The searil port appears to be stuck in this abnormal situation.
|
||||
|
||||
A hack to reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff appears to
|
||||
resolve the issue.
|
||||
|
||||
The question is fully discussed at
|
||||
https://www.spinics.net/lists/linux-serial/msg23163.html
|
||||
|
||||
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
|
||||
Reviewed-by: Shannon Zhao <shannon.zhaosl@gmail.com>
|
||||
Reviewed-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
hw/char/pl011.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
|
||||
index 58edeb9ddb..bc65d778d2 100644
|
||||
--- a/hw/char/pl011.c
|
||||
+++ b/hw/char/pl011.c
|
||||
@@ -314,6 +314,10 @@ static void pl011_write(void *opaque, hwaddr offset,
|
||||
case 17: /* UARTICR */
|
||||
s->int_level &= ~value;
|
||||
pl011_update(s);
|
||||
+ if (!s->int_enabled && !s->int_level) {
|
||||
+ s->read_count = 0;
|
||||
+ s->read_pos = 0;
|
||||
+ }
|
||||
break;
|
||||
case 18: /* UARTDMACR */
|
||||
s->dmacr = value;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
71
pl031-support-rtc-timer-property-for-pl031.patch
Normal file
71
pl031-support-rtc-timer-property-for-pl031.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From 8e30e81c4268103d502587de565842b9632a7965 Mon Sep 17 00:00:00 2001
|
||||
From: Jinhao Gao <gaojinhao@huawei.com>
|
||||
Date: Tue, 15 Feb 2022 17:02:08 +0800
|
||||
Subject: [PATCH] pl031: support rtc-timer property for pl031
|
||||
|
||||
This patch adds the rtc-timer property for pl031, we can get the
|
||||
rtc time (UTC) through qmp command "qom-get date" with this property.
|
||||
|
||||
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
|
||||
Reviewed-by: Shannon Zhao <shanon.Zhaosl@gmail.com>
|
||||
Reviewed-by: Ying Fang <fangying1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Jinhao Gao <gaojinhao@huawei.com>
|
||||
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||||
---
|
||||
hw/rtc/pl031.c | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c
|
||||
index f2e6baebba..57e9a35616 100644
|
||||
--- a/hw/rtc/pl031.c
|
||||
+++ b/hw/rtc/pl031.c
|
||||
@@ -63,6 +63,15 @@ static uint32_t pl031_get_count(PL031State *s)
|
||||
return s->tick_offset + now / NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
|
||||
+static void pl031_get_date(Object *obj, struct tm *current_tm, Error **errp)
|
||||
+{
|
||||
+ PL031State *s = PL031(obj);
|
||||
+ time_t ti = pl031_get_count(s);
|
||||
+
|
||||
+ /* Changed to UTC time */
|
||||
+ gmtime_r(&ti, current_tm);
|
||||
+}
|
||||
+
|
||||
static void pl031_set_alarm(PL031State *s)
|
||||
{
|
||||
uint32_t ticks;
|
||||
@@ -202,6 +211,20 @@ static void pl031_init(Object *obj)
|
||||
qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
|
||||
|
||||
s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
|
||||
+ object_property_add_tm(OBJECT(s), "date", pl031_get_date);
|
||||
+}
|
||||
+
|
||||
+static void pl031_realize(DeviceState *d, Error **errp)
|
||||
+{
|
||||
+ object_property_add_alias(qdev_get_machine(), "rtc-time",
|
||||
+ OBJECT(d), "date");
|
||||
+}
|
||||
+
|
||||
+static void pl031_unrealize(DeviceState *d)
|
||||
+{
|
||||
+ if (object_property_find(qdev_get_machine(), "rtc-time")) {
|
||||
+ object_property_del(qdev_get_machine(), "rtc-time");
|
||||
+ }
|
||||
}
|
||||
|
||||
static void pl031_finalize(Object *obj)
|
||||
@@ -338,6 +361,8 @@ static void pl031_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->vmsd = &vmstate_pl031;
|
||||
+ dc->realize = pl031_realize;
|
||||
+ dc->unrealize = pl031_unrealize;
|
||||
device_class_set_props(dc, pl031_properties);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
||||
35
ps2-fix-oob-in-ps2-kbd.patch
Normal file
35
ps2-fix-oob-in-ps2-kbd.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 0a54d68547df3f276dc242b52d54e8549d0a84a0 Mon Sep 17 00:00:00 2001
|
||||
From: Chuan Zheng <zhengchuan@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 11:21:28 +0800
|
||||
Subject: [PATCH] ps2: fix oob in ps2 kbd
|
||||
|
||||
fix oob in ps2 kbd
|
||||
---
|
||||
hw/input/ps2.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
|
||||
index c8fd23cf36..b647561069 100644
|
||||
--- a/hw/input/ps2.c
|
||||
+++ b/hw/input/ps2.c
|
||||
@@ -167,7 +167,7 @@ void ps2_queue_noirq(PS2State *s, int b)
|
||||
}
|
||||
|
||||
q->data[q->wptr] = b;
|
||||
- if (++q->wptr == PS2_BUFFER_SIZE) {
|
||||
+ if (++q->wptr >= PS2_BUFFER_SIZE) {
|
||||
q->wptr = 0;
|
||||
}
|
||||
q->count++;
|
||||
@@ -557,7 +557,7 @@ uint32_t ps2_read_data(PS2State *s)
|
||||
val = q->data[index];
|
||||
} else {
|
||||
val = q->data[q->rptr];
|
||||
- if (++q->rptr == PS2_BUFFER_SIZE) {
|
||||
+ if (++q->rptr >= PS2_BUFFER_SIZE) {
|
||||
q->rptr = 0;
|
||||
}
|
||||
q->count--;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
31
qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch
Normal file
31
qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 172d79d8ebb343fa144987d2c50d90655d5aa5f9 Mon Sep 17 00:00:00 2001
|
||||
From: Kunkun Jiang <jiangkunkun@huawei.com>
|
||||
Date: Thu, 29 Jul 2021 15:24:48 +0800
|
||||
Subject: [PATCH] qdev/monitors: Fix reundant error_setg of qdev_add_device
|
||||
|
||||
There is an extra log "error_setg" in qdev_add_device(). When
|
||||
hot-plug a device, if the corresponding bus doesn't exist, it
|
||||
will trigger an asseration "assert(*errp == NULL)".
|
||||
|
||||
Fixes: 515a7970490 (log: Add some logs on VM runtime path)
|
||||
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
|
||||
Signed-off-by: Yan Wang <wangyan122@huawei.com>
|
||||
---
|
||||
system/qdev-monitor.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
|
||||
index c885175b66..b10e483a9a 100644
|
||||
--- a/system/qdev-monitor.c
|
||||
+++ b/system/qdev-monitor.c
|
||||
@@ -644,7 +644,6 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts,
|
||||
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)) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
35
qemu-nbd-make-native-as-the-default-aio-mode.patch
Normal file
35
qemu-nbd-make-native-as-the-default-aio-mode.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 0e610831d584d9485eb0655168d08d8234bbb555 Mon Sep 17 00:00:00 2001
|
||||
From: WangJian <wangjian161@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 10:48:58 +0800
|
||||
Subject: [PATCH] qemu-nbd: make native as the default aio mode
|
||||
|
||||
When the file system is dealing with multithreading concurrent writing to a file,
|
||||
the performance will be degraded because of the lock.
|
||||
At present, the default AIO mode of QEMU NBD is threads. In the case of large blocks,
|
||||
because IO is divided into small pieces and multiple queues, it will become multithreading
|
||||
concurrent writing the same file. Due to the file system, the performance will be greatly reduced.
|
||||
If you change to native mode, this problem will not exist.
|
||||
|
||||
Signed-off-by: wangjian161 <wangjian161@huawei.com>
|
||||
---
|
||||
qemu-nbd.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/qemu-nbd.c b/qemu-nbd.c
|
||||
index 186e6468b1..acccf2977f 100644
|
||||
--- a/qemu-nbd.c
|
||||
+++ b/qemu-nbd.c
|
||||
@@ -843,6 +843,10 @@ int main(int argc, char **argv)
|
||||
trace_init_file();
|
||||
qemu_set_log(LOG_TRACE, &error_fatal);
|
||||
|
||||
+ if (!seen_aio && (flags & BDRV_O_NOCACHE)) {
|
||||
+ flags |= BDRV_O_NATIVE_AIO;
|
||||
+ }
|
||||
+
|
||||
socket_activation = check_socket_activation();
|
||||
if (socket_activation == 0) {
|
||||
if (!sockpath) {
|
||||
--
|
||||
2.27.0
|
||||
|
||||
42
qemu-nbd-set-timeout-to-qemu-nbd-socket.patch
Normal file
42
qemu-nbd-set-timeout-to-qemu-nbd-socket.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From d6aa08ac3693be3e08f2c8d3ad5a356ea6e9dead Mon Sep 17 00:00:00 2001
|
||||
From: WangJian <wangjian161@huawei.com>
|
||||
Date: Wed, 9 Feb 2022 10:55:08 +0800
|
||||
Subject: [PATCH] qemu-nbd: set timeout to qemu-nbd socket
|
||||
|
||||
In case of insufficient memory and kill-9,
|
||||
the NBD socket cannot be processed and stuck all the time.
|
||||
|
||||
Signed-off-by: wangjian161 <wangjian161@huawei.com>
|
||||
---
|
||||
nbd/client.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/nbd/client.c b/nbd/client.c
|
||||
index 29ffc609a4..987dde43c7 100644
|
||||
--- a/nbd/client.c
|
||||
+++ b/nbd/client.c
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "nbd-internal.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
+#define NBD_TIMEOUT_SECONDS 30
|
||||
+
|
||||
/* Definitions for opaque data types */
|
||||
|
||||
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
|
||||
@@ -1310,6 +1312,12 @@ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (ioctl(fd, NBD_SET_TIMEOUT, NBD_TIMEOUT_SECONDS) < 0) {
|
||||
+ int serrno = errno;
|
||||
+ error_setg(errp, "Failed setting timeout");
|
||||
+ return -serrno;
|
||||
+ }
|
||||
+
|
||||
trace_nbd_init_finish();
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
304
qemu.spec
304
qemu.spec
@ -3,7 +3,7 @@
|
||||
|
||||
Name: qemu
|
||||
Version: 8.2.0
|
||||
Release: 3
|
||||
Release: 6
|
||||
Epoch: 11
|
||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
||||
@ -89,6 +89,153 @@ Patch0072: target-loongarch-kvm-Enable-LSX-LASX-extension.patch
|
||||
Patch0073: target-loongarch-Fix-qtest-test-hmp-error-when-KVM-o.patch
|
||||
Patch0074: loongarch-Change-the-UEFI-loading-mode-to-loongarch.patch
|
||||
Patch0075: disable-keyring-option.patch
|
||||
Patch0076: virtio-net-correctly-copy-vnet-header-when-flushing-.patch
|
||||
Patch0077: ui-clipboard-mark-type-as-not-available-when-there-i.patch
|
||||
Patch0078: memory-backup-Modify-the-VM-s-physical-bits-value-se.patch
|
||||
Patch0079: backup-memory-bakcup-hugepages-hugepages-files-maybe.patch
|
||||
Patch0080: block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch
|
||||
Patch0081: travis-ci-Rename-SOFTMMU-SYSTEM.patch
|
||||
Patch0082: iotests-adapt-to-output-change-for-recently-introduc.patch
|
||||
Patch0083: migration-Skip-only-empty-block-devicesi.patch
|
||||
Patch0084: vhost-cancel-migration-when-vhost-user-restarted-dur.patch
|
||||
Patch0085: Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch
|
||||
Patch0086: ps2-fix-oob-in-ps2-kbd.patch
|
||||
Patch0087: monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch
|
||||
Patch0088: oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch
|
||||
Patch0089: migration-skip-cache_drop-for-bios-bootloader-and-nv.patch
|
||||
Patch0090: migration-Add-multi-thread-compress-method.patch
|
||||
Patch0091: migration-Refactoring-multi-thread-compress-migratio.patch
|
||||
Patch0092: migration-Add-multi-thread-compress-ops.patch
|
||||
Patch0093: migration-Add-zstd-support-in-multi-thread-compressi.patch
|
||||
Patch0094: migration-Add-compress_level-sanity-check.patch
|
||||
Patch0095: doc-Update-multi-thread-compression-doc.patch
|
||||
Patch0096: cpu-features-fix-bug-for-memory-leakage.patch
|
||||
Patch0097: migration-report-migration-related-thread-pid-to-lib.patch
|
||||
Patch0098: migration-report-multiFd-related-thread-pid-to-libvi.patch
|
||||
Patch0099: virtio-check-descriptor-numbers.patch
|
||||
Patch0100: virtio-bugfix-add-rcu_read_lock-when-vring_avail_idx.patch
|
||||
Patch0101: virtio-print-the-guest-virtio_net-features-that-host.patch
|
||||
Patch0102: virtio-bugfix-check-the-value-of-caches-before-acces.patch
|
||||
Patch0103: virtio-scsi-bugfix-fix-qemu-crash-for-hotplug-scsi-d.patch
|
||||
Patch0104: nbd-server.c-fix-invalid-read-after-client-was-alrea.patch
|
||||
Patch0105: qemu-nbd-make-native-as-the-default-aio-mode.patch
|
||||
Patch0106: qemu-nbd-set-timeout-to-qemu-nbd-socket.patch
|
||||
Patch0107: qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch
|
||||
Patch0108: pcie-Compat-with-devices-which-do-not-support-Link-W.patch
|
||||
Patch0109: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch
|
||||
Patch0110: net-dump.c-Suppress-spurious-compiler-warning.patch
|
||||
Patch0111: hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch
|
||||
Patch0112: i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch
|
||||
Patch0113: vhost-user-Set-the-acked_features-to-vm-s-featrue.patch
|
||||
Patch0114: vhost-user-Add-support-reconnect-vhost-user-socket.patch
|
||||
Patch0115: fix-qemu-core-when-vhost-user-net-config-with-server.patch
|
||||
Patch0116: vhost-user-quit-infinite-loop-while-used-memslots-is.patch
|
||||
Patch0117: vhost-user-add-vhost_set_mem_table-when-vm-load_setu.patch
|
||||
Patch0118: vhost-user-add-unregister_savevm-when-vhost-user-cle.patch
|
||||
Patch0119: monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch
|
||||
Patch0120: virtio-net-bugfix-do-not-delete-netdev-before-virtio.patch
|
||||
Patch0121: virtio-net-fix-max-vring-buf-size-when-set-ring-num.patch
|
||||
Patch0122: virtio-net-set-the-max-of-queue-size-to-4096.patch
|
||||
Patch0123: virtio-net-update-the-default-and-max-of-rx-tx_queue.patch
|
||||
Patch0124: hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch
|
||||
Patch0125: vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch
|
||||
Patch0126: vhost-vdpa-add-migration-log-ops-for-VhostOps.patch
|
||||
Patch0127: vhost-introduce-bytemap-for-vhost-backend-logging.patch
|
||||
Patch0128: vhost-add-vhost_dev_suspend-resume_op.patch
|
||||
Patch0129: vhost-implement-vhost-vdpa-suspend-resume.patch
|
||||
Patch0130: vhost-implement-vhost_vdpa_device_suspend-resume.patch
|
||||
Patch0131: vhost-implement-savevm_handler-for-vdpa-device.patch
|
||||
Patch0132: vhost-implement-post-resume-bh.patch
|
||||
Patch0133: vhost-implement-migration-state-notifier-for-vdpa-de.patch
|
||||
Patch0134: vdpa-implement-vdpa-device-migration.patch
|
||||
Patch0135: vdpa-move-memory-listener-to-the-realize-stage.patch
|
||||
Patch0136: vdpa-support-vdpa-device-suspend-resume.patch
|
||||
Patch0137: vdpa-suspend-function-return-0-when-the-vdpa-device-.patch
|
||||
Patch0138: vdpa-correct-param-passed-in-when-unregister-save.patch
|
||||
Patch0139: vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch
|
||||
Patch0140: docs-Add-generic-vhost-vdpa-device-documentation.patch
|
||||
Patch0141: vdpa-set-vring-enable-only-if-the-vring-address-has-.patch
|
||||
Patch0142: ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch
|
||||
Patch0143: net-eepro100-validate-various-address-valuesi-CVE-20.patch
|
||||
Patch0144: cpu-add-Kunpeng-920-cpu-support.patch
|
||||
Patch0145: cpu-add-Cortex-A72-processor-kvm-target-support.patch
|
||||
Patch0146: tests-virt-Allow-changes-to-PPTT-test-table.patch
|
||||
Patch0147: hw-arm64-add-vcpu-cache-info-support.patch
|
||||
Patch0148: arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch
|
||||
Patch0149: tests-virt-Update-expected-ACPI-tables-for-virt-test.patch
|
||||
Patch0150: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch
|
||||
Patch0151: shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch
|
||||
Patch0152: tests-Disable-filemonitor-testcase.patch
|
||||
Patch0153: freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch
|
||||
Patch0154: freeclock-set-rtc_date_diff-for-arm.patch
|
||||
Patch0155: freeclock-set-rtc_date_diff-for-X86.patch
|
||||
Patch0156: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch
|
||||
Patch0157: bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch
|
||||
Patch0158: log-Add-log-at-boot-cpu-init-for-aarch64.patch
|
||||
Patch0159: feature-Add-log-for-each-modules.patch
|
||||
Patch0160: feature-Add-logs-for-vm-start-and-destroy.patch
|
||||
Patch0161: pl031-support-rtc-timer-property-for-pl031.patch
|
||||
Patch0162: arm-acpi-Fix-when-make-qemu-system-aarch64-at-x86_64.patch
|
||||
Patch0163: linux-headers-update-against-5.10-and-manual-clear-v.patch
|
||||
Patch0164: vfio-Maintain-DMA-mapping-range-for-the-container.patch
|
||||
Patch0165: vfio-migration-Add-support-for-manual-clear-vfio-dir.patch
|
||||
Patch0166: arm-virt-target-arm-Add-new-ARMCPU-socket-cluster-co.patch
|
||||
Patch0167: cpus-common-Add-common-CPU-utility-for-possible-vCPU.patch
|
||||
Patch0168: hw-arm-virt-Move-setting-of-common-CPU-properties-in.patch
|
||||
Patch0169: arm-virt-target-arm-Machine-init-time-change-common-.patch
|
||||
Patch0170: accel-kvm-Extract-common-KVM-vCPU-creation-parking-c.patch
|
||||
Patch0171: arm-virt-kvm-Pre-create-disabled-possible-vCPUs-mach.patch
|
||||
Patch0172: arm-virt-gicv3-Changes-to-pre-size-GIC-with-possible.patch
|
||||
Patch0173: arm-virt-Init-PMU-at-host-for-all-possible-vcpus.patch
|
||||
Patch0174: hw-acpi-Move-CPU-ctrl-dev-MMIO-region-len-macro-to-c.patch
|
||||
Patch0175: arm-acpi-Enable-ACPI-support-for-vcpu-hotplug.patch
|
||||
Patch0176: hw-acpi-Add-ACPI-CPU-hotplug-init-stub.patch
|
||||
Patch0177: hw-acpi-Use-qemu_present_cpu-API-in-ACPI-CPU-hotplug.patch
|
||||
Patch0178: hw-acpi-Init-GED-framework-with-cpu-hotplug-events.patch
|
||||
Patch0179: arm-virt-Add-cpu-hotplug-events-to-GED-during-creati.patch
|
||||
Patch0180: arm-virt-Create-GED-dev-before-disabled-CPU-Objs-are.patch
|
||||
Patch0181: hw-acpi-Update-CPUs-AML-with-cpu-ctrl-dev-change.patch
|
||||
Patch0182: arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch
|
||||
Patch0183: acpi-cpu-Add-cpu_cppc-building-support.patch
|
||||
Patch0184: tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch
|
||||
Patch0185: arm-virt-acpi-Build-CPUs-AML-with-CPU-Hotplug-suppor.patch
|
||||
Patch0186: arm-virt-Make-ARM-vCPU-present-status-ACPI-persisten.patch
|
||||
Patch0187: hw-acpi-ACPI-AML-Changes-to-reflect-the-correct-_STA.patch
|
||||
Patch0188: hw-acpi-Update-GED-_EVT-method-AML-with-cpu-scan.patch
|
||||
Patch0189: hw-arm-MADT-Tbl-change-to-size-the-guest-with-possib.patch
|
||||
Patch0190: hw-acpi-Make-_MAT-method-optional.patch
|
||||
Patch0191: arm-virt-Release-objects-for-disabled-possible-vCPUs.patch
|
||||
Patch0192: hw-acpi-Update-ACPI-GED-framework-to-support-vCPU-Ho.patch
|
||||
Patch0193: arm-virt-Add-update-basic-hot-un-plug-framework.patch
|
||||
Patch0194: arm-virt-Changes-to-un-wire-GICC-vCPU-IRQs-during-ho.patch
|
||||
Patch0195: hw-arm-gicv3-Changes-to-update-GIC-with-vCPU-hot-plu.patch
|
||||
Patch0196: hw-intc-arm-gicv3-Changes-required-to-re-init-the-vC.patch
|
||||
Patch0197: arm-virt-Update-the-guest-via-GED-about-CPU-hot-un-p.patch
|
||||
Patch0198: hw-arm-Changes-required-for-reset-and-to-support-nex.patch
|
||||
Patch0199: physmem-gdbstub-Common-helping-funcs-changes-to-unre.patch
|
||||
Patch0200: target-arm-Add-support-of-unrealize-ARMCPU-during-vC.patch
|
||||
Patch0201: target-arm-kvm-Write-CPU-state-back-to-KVM-on-reset.patch
|
||||
Patch0202: target-arm-kvm-tcg-Register-Handle-SMCCC-hypercall-e.patch
|
||||
Patch0203: hw-arm-Support-hotplug-capability-check-using-_OSC-m.patch
|
||||
Patch0204: tcg-mttcg-enable-threads-to-unregister-in-tcg_ctxs.patch
|
||||
Patch0205: hw-arm-virt-Expose-cold-booted-CPUs-as-MADT-GICC-Ena.patch
|
||||
Patch0206: system-physmem-Fix-possible-double-free-when-destroy.patch
|
||||
Patch0207: arm-cpu-Some-fixes-for-arm_cpu_unrealizefn.patch
|
||||
Patch0208: acpi-cpu-Fix-cpu_hotplug_hw_init.patch
|
||||
Patch0209: system-cpus-Fix-pause_all_vcpus-under-concurrent-env.patch
|
||||
Patch0210: system-cpus-Fix-resume_all_vcpus-under-vCPU-hotplug-.patch
|
||||
Patch0211: arm-virt.c-Convey-local_err-when-set-psci-conduit.patch
|
||||
Patch0212: arm-virt-Fix-adjudgement-of-core_id-for-vcpu-hotplug.patch
|
||||
Patch0213: accel-kvm-Use-correct-id-for-parked-vcpu.patch
|
||||
Patch0214: arm-kvm-Set-psci-smccc-filter-only-with-vcpu-hotplug.patch
|
||||
Patch0215: intc-gicv3-Fixes-for-vcpu-hotplug.patch
|
||||
Patch0216: acpi-ged-Init-cpu-hotplug-only-when-machine-support-.patch
|
||||
Patch0217: acpi-ged-Remove-cpuhp-field-of-ged.patch
|
||||
Patch0218: arm-virt-acpi-Require-possible_cpu_arch_ids-for-buil.patch
|
||||
Patch0219: arm-virt-Consider-has_ged-when-set-mc-has_hotpluggab.patch
|
||||
Patch0220: arm-virt-Require-mc-has_hotpluggable_cpus-for-cold-p.patch
|
||||
Patch0221: tests-acpi-Update-expected-ACPI-tables-for-vcpu-hotp.patch
|
||||
Patch0222: coro-support-live-patch-for-libcare.patch
|
||||
|
||||
BuildRequires: flex
|
||||
BuildRequires: gcc
|
||||
@ -303,7 +450,7 @@ qemubuilddir="build"
|
||||
|
||||
tar xf %{SOURCE4}
|
||||
cd BinDir/
|
||||
\cp -r -a . ../
|
||||
\cp -r -a * ../
|
||||
cd ../
|
||||
|
||||
./configure \
|
||||
@ -686,6 +833,159 @@ getent passwd qemu >/dev/null || \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Apr 10 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-6
|
||||
- coro: support live patch for libcare
|
||||
- tests/acpi: Update expected ACPI tables for vcpu hotplug(Update BinDir)
|
||||
- arm/virt: Require mc->has_hotpluggable_cpus for cold-plugged vcpu
|
||||
- arm/virt: Consider has_ged when set mc->has_hotpluggable_cpus
|
||||
- arm/virt-acpi: Require possible_cpu_arch_ids for build_cpus_aml()
|
||||
- acpi/ged: Remove cpuhp field of ged
|
||||
- acpi/ged: Init cpu hotplug only when machine support it
|
||||
- intc/gicv3: Fixes for vcpu hotplug
|
||||
- arm/kvm: Set psci smccc filter only with vcpu hotplug
|
||||
- accel/kvm: Use correct id for parked vcpu
|
||||
- arm/virt: Fix adjudgement of core_id for vcpu hotplugged
|
||||
- arm/virt.c: Convey local_err when set psci-conduit
|
||||
- system/cpus: Fix resume_all_vcpus() under vCPU hotplug condition
|
||||
- system/cpus: Fix pause_all_vcpus() under concurrent environment
|
||||
- acpi/cpu: Fix cpu_hotplug_hw_init()
|
||||
- arm/cpu: Some fixes for arm_cpu_unrealizefn()
|
||||
- system/physmem: Fix possible double free when destroy cpu as
|
||||
- hw/arm/virt: Expose cold-booted CPUs as MADT GICC Enabled
|
||||
- tcg/mttcg: enable threads to unregister in tcg_ctxs[]
|
||||
- hw/arm: Support hotplug capability check using _OSC method
|
||||
- target/arm/kvm,tcg: Register/Handle SMCCC hypercall exits to VMM/Qemu
|
||||
- target/arm/kvm: Write CPU state back to KVM on reset
|
||||
- target/arm: Add support of *unrealize* ARMCPU during vCPU Hot-unplug
|
||||
- physmem,gdbstub: Common helping funcs/changes to *unrealize* vCPU
|
||||
- hw/arm: Changes required for reset and to support next boot
|
||||
- arm/virt: Update the guest(via GED) about CPU hot-(un)plug events
|
||||
- hw/intc/arm-gicv3*: Changes required to (re)init the vCPU register info
|
||||
- hw/arm,gicv3: Changes to update GIC with vCPU hot-plug notification
|
||||
- arm/virt: Changes to (un)wire GICC<->vCPU IRQs during hot-(un)plug
|
||||
- arm/virt: Add/update basic hot-(un)plug framework
|
||||
- hw/acpi: Update ACPI GED framework to support vCPU Hotplug
|
||||
- arm/virt: Release objects for *disabled* possible vCPUs after init
|
||||
- hw/acpi: Make _MAT method optional
|
||||
- hw/arm: MADT Tbl change to size the guest with possible vCPUs
|
||||
- hw/acpi: Update GED _EVT method AML with cpu scan
|
||||
- hw/acpi: ACPI/AML Changes to reflect the correct _STA.{PRES,ENA} Bits to Guest
|
||||
- arm/virt: Make ARM vCPU *present* status ACPI *persistent*
|
||||
- arm/virt/acpi: Build CPUs AML with CPU Hotplug support
|
||||
- tests/acpi/bios-tables-test: Allow changes to virt/DSDT file
|
||||
- acpi/cpu: Add cpu_cppc building support
|
||||
- arm/virt/acpi: Factor out CPPC building from DSDT CPU aml
|
||||
- hw/acpi: Update CPUs AML with cpu-(ctrl)dev change
|
||||
- arm/virt: Create GED dev before *disabled* CPU Objs are destroyed
|
||||
- arm/virt: Add cpu hotplug events to GED during creation
|
||||
- hw/acpi: Init GED framework with cpu hotplug events
|
||||
- hw/acpi: Use qemu_present_cpu() API in ACPI CPU hotplug init
|
||||
- hw/acpi: Add ACPI CPU hotplug init stub
|
||||
- arm/acpi: Enable ACPI support for vcpu hotplug
|
||||
- hw/acpi: Move CPU ctrl-dev MMIO region len macro to common header file
|
||||
- arm/virt: Init PMU at host for all possible vcpus
|
||||
- arm/virt,gicv3: Changes to pre-size GIC with possible vcpus @machine init
|
||||
- arm/virt,kvm: Pre-create disabled possible vCPUs @machine init
|
||||
- accel/kvm: Extract common KVM vCPU {creation,parking} code
|
||||
- arm/virt,target/arm: Machine init time change common to vCPU {cold|hot}-plug
|
||||
- hw/arm/virt: Move setting of common CPU properties in a function
|
||||
- cpus-common: Add common CPU utility for possible vCPUs
|
||||
- arm/virt,target/arm: Add new ARMCPU {socket,cluster,core,thread}-id property
|
||||
|
||||
* Sun Apr 7 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-5
|
||||
- vfio/migration: Add support for manual clear vfio dirty log
|
||||
- vfio: Maintain DMA mapping range for the container
|
||||
- linux-headers: update against 5.10 and manual clear vfio dirty log series
|
||||
- arm/acpi: Fix when make qemu-system-aarch64 at x86_64 host bios_tables_test fail reason: __aarch64__ macro let build_pptt at x86_64 and aarch64 host build different function that let bios_tables_test fail.
|
||||
- pl031: support rtc-timer property for pl031
|
||||
- feature: Add logs for vm start and destroy
|
||||
- feature: Add log for each modules
|
||||
- log: Add log at boot & cpu init for aarch64
|
||||
- bugfix: irq: Avoid covering object refcount of qemu_irq
|
||||
- i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo
|
||||
- freeclock: set rtc_date_diff for X86
|
||||
- freeclock: set rtc_date_diff for arm
|
||||
- freeclock: add qmp command to get time offset of vm in seconds
|
||||
- tests: Disable filemonitor testcase
|
||||
- shadow_dev: introduce shadow dev for virtio-net device
|
||||
- pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff
|
||||
- tests: virt: Update expected ACPI tables for virt test(Update BinDir)
|
||||
- arm64: Add the cpufreq device to show cpufreq info to guest
|
||||
- hw/arm64: add vcpu cache info support
|
||||
- tests: virt: Allow changes to PPTT test table
|
||||
- cpu: add Cortex-A72 processor kvm target support
|
||||
- cpu: add Kunpeng-920 cpu support
|
||||
- net: eepro100: validate various address valuesi(CVE-2021-20255)
|
||||
- ide: ahci: add check to avoid null dereference (CVE-2019-12067)
|
||||
- vdpa: set vring enable only if the vring address has already been set
|
||||
- docs: Add generic vhost-vdpa device documentation
|
||||
- vdpa: don't suspend/resume device when vdpa device not started
|
||||
- vdpa: correct param passed in when unregister save
|
||||
- vdpa: suspend function return 0 when the vdpa device is stopped
|
||||
- vdpa: support vdpa device suspend/resume
|
||||
- vdpa: move memory listener to the realize stage
|
||||
- vdpa: implement vdpa device migration
|
||||
- vhost: implement migration state notifier for vdpa device
|
||||
- vhost: implement post resume bh
|
||||
- vhost: implement savevm_handler for vdpa device
|
||||
- vhost: implement vhost_vdpa_device_suspend/resume
|
||||
- vhost: implement vhost-vdpa suspend/resume
|
||||
- vhost: add vhost_dev_suspend/resume_op
|
||||
- vhost: introduce bytemap for vhost backend logging
|
||||
- vhost-vdpa: add migration log ops for VhostOps
|
||||
- vhost-vdpa: add VHOST_BACKEND_F_BYTEMAPLOG
|
||||
- hw/usb: reduce the vpcu cost of UHCI when VNC disconnect
|
||||
- virtio-net: update the default and max of rx/tx_queue_size
|
||||
- virtio-net: set the max of queue size to 4096
|
||||
- virtio-net: fix max vring buf size when set ring num
|
||||
- virtio-net: bugfix: do not delete netdev before virtio net
|
||||
- monitor: Discard BLOCK_IO_ERROR event when VM rebooted
|
||||
- vhost-user: add unregister_savevm when vhost-user cleanup
|
||||
- vhost-user: add vhost_set_mem_table when vm load_setup at destination
|
||||
- vhost-user: quit infinite loop while used memslots is more than the backend limit
|
||||
- fix qemu-core when vhost-user-net config with server mode
|
||||
- vhost-user: Add support reconnect vhost-user socket
|
||||
- vhost-user: Set the acked_features to vm's featrue
|
||||
- i6300esb watchdog: bugfix: Add a runstate transition
|
||||
- hw/net/rocker_of_dpa: fix double free bug of rocker device
|
||||
- net/dump.c: Suppress spurious compiler warning
|
||||
- pcie: Add pcie-root-port fast plug/unplug feature
|
||||
- pcie: Compat with devices which do not support Link Width, such as ioh3420
|
||||
- qdev/monitors: Fix reundant error_setg of qdev_add_device
|
||||
- qemu-nbd: set timeout to qemu-nbd socket
|
||||
- qemu-nbd: make native as the default aio mode
|
||||
- nbd/server.c: fix invalid read after client was already free
|
||||
- virtio-scsi: bugfix: fix qemu crash for hotplug scsi disk with dataplane
|
||||
- virtio: bugfix: check the value of caches before accessing it
|
||||
- virtio: print the guest virtio_net features that host does not support
|
||||
- virtio: bugfix: add rcu_read_lock when vring_avail_idx is called
|
||||
- virtio: check descriptor numbers
|
||||
- migration: report multiFd related thread pid to libvirt
|
||||
- migration: report migration related thread pid to libvirt
|
||||
- cpu/features: fix bug for memory leakage
|
||||
- doc: Update multi-thread compression doc
|
||||
- migration: Add compress_level sanity check
|
||||
- migration: Add zstd support in multi-thread compression
|
||||
- migration: Add multi-thread compress ops
|
||||
- migration: Refactoring multi-thread compress migration
|
||||
- migration: Add multi-thread compress method
|
||||
- migration: skip cache_drop for bios bootloader and nvram template
|
||||
- oslib-posix: optimise vm startup time for 1G hugepage
|
||||
- monitor/qmp: drop inflight rsp if qmp client broken
|
||||
- ps2: fix oob in ps2 kbd
|
||||
- Currently, while kvm and qemu can not handle some kvm exit, qemu will do vm_stop, which will make vm in pause state. This action make vm unrecoverable, so send guest panic to libvirt instead.
|
||||
- vhost: cancel migration when vhost-user restarted during migraiton
|
||||
|
||||
* Mon Apr 1 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-4
|
||||
- migration: Skip only empty block devicesi
|
||||
- iotests: adapt to output change for recently introduced 'detached hea…
|
||||
- travis-ci: Rename SOFTMMU -> SYSTEM
|
||||
- block: disallow block jobs when there is a BDRV_O_INACTIVE flag
|
||||
- [backup] memory: bakcup hugepages: hugepages files maybe leftover
|
||||
- memory: [backup] Modify the VM's physical bits value set policy.
|
||||
- ui/clipboard: mark type as not available when there is no data (CVE-2023-6683)
|
||||
- virtio-net: correctly copy vnet header when flushing TX (CVE-2023-6693)
|
||||
|
||||
* Wed Mar 27 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-3
|
||||
- disable keyring option
|
||||
- loongarch: Change the UEFI loading mode to loongarch
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user