[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 6/6] cpu: add device_add foo-x86_64-cpu support
From: |
Gu Zheng |
Subject: |
[Qemu-devel] [PATCH 6/6] cpu: add device_add foo-x86_64-cpu support |
Date: |
Thu, 13 Nov 2014 09:10:32 +0800 |
From: Chen Fan <address@hidden>
Add support to device_add foo-x86_64-cpu, and additional checks of
apic id are added into x86_cpuid_set_apic_id() to avoid duplicate.
Besides, in order to support "device/device_add foo-x86_64-cpu"
which without specified apic id, we assign cpuid_apic_id with a
default broadcast value (0xFFFFFFFF) in initfn, and a new function
get_free_apic_id() to provide a free apid id to cpuid_apic_id if
it still has the default at realize time (e.g. hot add foo-cpu without
a specified apic id) to avoid apic id duplicates.
Thanks very much for Igor's suggestion.
Signed-off-by: Chen Fan <address@hidden>
Signed-off-by: Gu Zheng <address@hidden>
Signed-off-by: Zhu Guihua <address@hidden>
---
hw/acpi/cpu_hotplug.c | 5 ++++-
hw/i386/pc.c | 6 ------
target-i386/cpu.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
target-i386/topology.h | 18 ++++++++++++++++++
4 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index b8ebfad..3dbfd71 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -60,7 +60,10 @@ void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
}
ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS;
- acpi_update_sci(ar, irq);
+
+ /* Only trigger sci if cpu is hotplugged */
+ if (dev->hotplugged)
+ acpi_update_sci(ar, irq);
}
void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1205db8..08e169d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1615,13 +1615,7 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
- if (!dev->hotplugged) {
- goto out;
- }
-
if (!pcms->acpi_dev) {
- error_setg(&local_err,
- "cpu hotplug is not enabled: missing acpi device");
goto out;
}
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 0f23ba3..d0eb3c9 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -49,7 +49,6 @@
#include "hw/i386/apic_internal.h"
#endif
-
/* Cache topology CPUID constants: */
/* CPUID Leaf 2 Descriptors */
@@ -1633,6 +1632,7 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor
*v, void *opaque,
const int64_t max = UINT32_MAX;
Error *error = NULL;
int64_t value;
+ X86CPUTopoInfo topo;
if (dev->realized) {
error_setg(errp, "Attempt to set property '%s' on '%s' after "
@@ -1652,6 +1652,19 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor
*v, void *opaque,
return;
}
+ if (value > x86_cpu_apic_id_from_index(max_cpus - 1)) {
+ error_setg(errp, "CPU with APIC ID %" PRIi64
+ " is more than MAX APIC ID limits", value);
+ return;
+ }
+
+ x86_topo_ids_from_apic_id(smp_cores, smp_threads, value, &topo);
+ if (topo.smt_id >= smp_threads || topo.core_id >= smp_cores) {
+ error_setg(errp, "CPU with APIC ID %" PRIi64 " does not match "
+ "topology configuration.", value);
+ return;
+ }
+
if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
return;
@@ -2106,8 +2119,10 @@ static void x86_cpu_cpudef_class_init(ObjectClass *oc,
void *data)
{
X86CPUDefinition *cpudef = data;
X86CPUClass *xcc = X86_CPU_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
xcc->cpu_def = cpudef;
+ dc->cannot_instantiate_with_device_add_yet = false;
}
static void x86_register_cpudef_type(X86CPUDefinition *def)
@@ -2116,6 +2131,7 @@ static void x86_register_cpudef_type(X86CPUDefinition
*def)
TypeInfo ti = {
.name = typename,
.parent = TYPE_X86_CPU,
+ .instance_size = sizeof(X86CPU),
.class_init = x86_cpu_cpudef_class_init,
.class_data = def,
};
@@ -2649,12 +2665,27 @@ static void mce_init(X86CPU *cpu)
}
#ifndef CONFIG_USER_ONLY
+static uint32_t get_free_apic_id(void)
+{
+ int i;
+
+ for (i = 0; i < max_cpus; i++) {
+ uint32_t id = x86_cpu_apic_id_from_index(i);
+
+ if (!cpu_exists(id)) {
+ return id;
+ }
+ }
+
+ return x86_cpu_apic_id_from_index(max_cpus);
+}
+
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
- CPUX86State *env = &cpu->env;
DeviceState *dev = DEVICE(cpu);
APICCommonState *apic;
const char *apic_type = "apic";
+ uint32_t apic_id;
if (kvm_irqchip_in_kernel()) {
apic_type = "kvm-apic";
@@ -2670,7 +2701,14 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error
**errp)
object_property_add_child(OBJECT(cpu), "apic",
OBJECT(cpu->apic_state), NULL);
- qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
+
+ apic_id = object_property_get_int(OBJECT(cpu), "apic-id", NULL);
+ if (apic_id == 0xffffffff) {
+ apic_id = get_free_apic_id();
+ object_property_set_int(OBJECT(cpu), apic_id, "apic-id", errp);
+ }
+
+ qdev_prop_set_uint8(cpu->apic_state, "id", apic_id);
/* TODO: convert to link<> */
apic = APIC_COMMON(cpu->apic_state);
apic->cpu = cpu;
@@ -2859,7 +2897,7 @@ static void x86_cpu_initfn(Object *obj)
NULL, NULL, (void *)cpu->filtered_features, NULL);
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
- env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
+ env->cpuid_apic_id = 0xffffffff;
x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
diff --git a/target-i386/topology.h b/target-i386/topology.h
index e9ff89c..dcb4988 100644
--- a/target-i386/topology.h
+++ b/target-i386/topology.h
@@ -132,4 +132,22 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned
nr_cores,
return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
}
+/* Calculate CPU topology based on CPU APIC ID.
+ */
+static inline void x86_topo_ids_from_apic_id(unsigned nr_cores,
+ unsigned nr_threads,
+ apic_id_t apic_id,
+ X86CPUTopoInfo *topo)
+{
+ unsigned offset_mask;
+ topo->pkg_id = apic_id >> apicid_pkg_offset(nr_cores, nr_threads);
+
+ offset_mask = (1L << apicid_pkg_offset(nr_cores, nr_threads)) - 1;
+ topo->core_id = (apic_id & offset_mask)
+ >> apicid_core_offset(nr_cores, nr_threads);
+
+ offset_mask = (1L << apicid_core_offset(nr_cores, nr_threads)) - 1;
+ topo->smt_id = apic_id & offset_mask;
+}
+
#endif /* TARGET_I386_TOPOLOGY_H */
--
1.7.7
- [Qemu-devel] [PATCH 0/6] cpu: add device_add foo-x86_64-cpu support, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 1/6] cpu: introduce CpuTopoInfo structure for argument simplification, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 2/6] qom/cpu: move register_vmstate to common CPUClass.realizefn, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 3/6] qom/cpu: move apic vmstate register into x86_cpu_apic_realize, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 4/6] monitor: use cc->get_arch_id as the cpu index, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 5/6] acpi:cpu hotplug: set pcmachine as icc bus' hotplug handler, Gu Zheng, 2014/11/12
- [Qemu-devel] [PATCH 6/6] cpu: add device_add foo-x86_64-cpu support,
Gu Zheng <=
- Re: [Qemu-devel] [PATCH 0/6] cpu: add device_add foo-x86_64-cpu support, Gu Zheng, 2014/11/18