qemu/arm-virt-target-arm-Machine-init-time-change-common-.patch

329 lines
12 KiB
Diff
Raw Permalink Normal View History

QEMU update to version 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 Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
2024-04-10 20:59:57 +08:00
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