On 02/15/2012 05:16 PM, Igor Mammedov wrote:
Convert pc cpu to qdev device that is attached to icc bus, later
hot-plug ability of icc bus will allow to implement cpu hot-plug.
Signed-off-by: Igor Mammedov<imamm...@redhat.com>
Obviously, this needs to go to QOM, but also, this is a shallow conversion.
Beginning with a shallow conversion is okay but only if there's a clear path to
a proper conversion. I don't think this approach fits that requirement. The
approach is a bit too pc centric. It's not clear how it would generalize.
Regards,
Anthony Liguori
---
hw/pc.c | 62 +++++++++++++++++++++++++++++++++++++++++++------
target-i386/cpu.h | 1 +
target-i386/helper.c | 26 ++++++++++++++------
3 files changed, 73 insertions(+), 16 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index 33d8090..b8db5dc 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -922,6 +922,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int
level)
}
}
+typedef struct CPUPC {
+ ICCBusDevice busdev;
+ char *model;
+ CPUState state;
+} CPUPC;
+
static void pc_cpu_reset(void *opaque)
{
CPUState *env = opaque;
@@ -930,23 +936,63 @@ static void pc_cpu_reset(void *opaque)
env->halted = !cpu_is_bsp(env);
}
-static CPUState *pc_new_cpu(const char *cpu_model)
+static DeviceState *pc_new_cpu(const char *cpu_model)
{
- CPUState *env;
+ DeviceState *dev;
+ BusState *b;
- env = cpu_init(cpu_model);
- if (!env) {
- fprintf(stderr, "Unable to find x86 CPU definition\n");
- exit(1);
+ b = get_icc_bus();
+ dev = qdev_create(b, "cpu-pc");
+ if (!dev) {
+ return NULL;
+ }
+ qdev_prop_set_string(dev, "model", g_strdup(cpu_model));
+ if (qdev_init(dev)< 0) {
+ return NULL;
+ }
+ return dev;
+}
+
+static int cpu_device_init(ICCBusDevice *dev)
+{
+ CPUPC* cpu = DO_UPCAST(CPUPC, busdev, dev);
+ CPUState *env =&cpu->state;
+
+ if (cpu_x86_init_inplace(env, cpu->model)< 0) {
+ return -1;
}
+
if ((env->cpuid_features& CPUID_APIC) || smp_cpus> 1) {
env->apic_state = apic_init(env, env->cpuid_apic_id);
}
- qemu_register_reset(pc_cpu_reset, env);
+
+ return 0;
+}
+
+static void cpu_device_reset(DeviceState *dev) {
+ CPUPC *cpu = DO_UPCAST(CPUPC, busdev.qdev, dev);
+ CPUState *env =&cpu->state;
pc_cpu_reset(env);
- return env;
}
+static ICCBusDeviceInfo cpu_device_info = {
+ .qdev.name = "cpu-pc",
+ .qdev.size = sizeof(CPUPC),
+ .qdev.reset = cpu_device_reset,
+ .init = cpu_device_init,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_STRING("model", CPUPC, model),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
+static void pc_register_devices(void)
+{
+ iccbus_register_devinfo(&cpu_device_info);
+}
+
+device_init(pc_register_devices);
+
void pc_cpus_init(const char *cpu_model)
{
int i;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 7e66bcf..830b65e 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -775,6 +775,7 @@ typedef struct CPUX86State {
} CPUX86State;
CPUX86State *cpu_x86_init(const char *cpu_model);
+int cpu_x86_init_inplace(CPUX86State *env, const char *cpu_model);
int cpu_x86_exec(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2586aff..df2f5ba 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1235,12 +1235,14 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned
int selector,
return 1;
}
-CPUX86State *cpu_x86_init(const char *cpu_model)
+int cpu_x86_init_inplace(CPUX86State *env, const char *cpu_model)
{
- CPUX86State *env;
static int inited;
- env = g_malloc0(sizeof(CPUX86State));
+ if (cpu_x86_register(env, cpu_model)< 0) {
+ fprintf(stderr, "Unable to find x86 CPU definition\n");
+ return -1;
+ }
cpu_exec_init(env);
env->cpu_model_str = cpu_model;
@@ -1253,18 +1255,26 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
cpu_set_debug_excp_handler(breakpoint_handler);
#endif
}
- if (cpu_x86_register(env, cpu_model)< 0) {
- cpu_x86_close(env);
- return NULL;
- }
env->cpuid_apic_id = env->cpu_index;
mce_init(env);
qemu_init_vcpu(env);
- return env;
+ return 0;
}
+CPUX86State *cpu_x86_init(const char *cpu_model)
+{
+ CPUX86State *env;
+
+ env = g_malloc0(sizeof(CPUX86State));
+ if (cpu_x86_init_inplace(env, cpu_model)< 0) {
+ g_free(env);
+ return NULL;
+ }
+
+ return env;
+}
#if !defined(CONFIG_USER_ONLY)
void do_cpu_init(CPUState *env)
{