aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/virt.c7
-rw-r--r--include/qom/cpu.h2
-rw-r--r--qom/cpu.c41
-rw-r--r--target-i386/cpu.c26
4 files changed, 54 insertions, 22 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6e098afd1f..ae90ca5771 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1261,6 +1261,7 @@ static void machvirt_init(MachineState *machine)
for (n = 0; n < smp_cpus; n++) {
ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
+ const char *typename = object_class_get_name(oc);
CPUClass *cc = CPU_CLASS(oc);
Object *cpuobj;
Error *err = NULL;
@@ -1270,10 +1271,10 @@ static void machvirt_init(MachineState *machine)
error_report("Unable to find CPU definition");
exit(1);
}
- cpuobj = object_new(object_class_get_name(oc));
+ /* convert -smp CPU options specified by the user into global props */
+ cc->parse_features(typename, cpuopts, &err);
+ cpuobj = object_new(typename);
- /* Handle any CPU options specified by the user */
- cc->parse_features(CPU(cpuobj), cpuopts, &err);
g_free(cpuopts);
if (err) {
error_report_err(err);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 32f3af3e1c..cacb100f7b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -134,7 +134,7 @@ typedef struct CPUClass {
/*< public >*/
ObjectClass *(*class_by_name)(const char *cpu_model);
- void (*parse_features)(CPUState *cpu, char *str, Error **errp);
+ void (*parse_features)(const char *typename, char *str, Error **errp);
void (*reset)(CPUState *cpu);
int reset_dump_flags;
diff --git a/qom/cpu.c b/qom/cpu.c
index 751e992de8..2a0d9fe10f 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -28,6 +28,7 @@
#include "exec/log.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
bool cpu_exists(int64_t id)
{
@@ -46,7 +47,7 @@ bool cpu_exists(int64_t id)
CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
{
char *str, *name, *featurestr;
- CPUState *cpu;
+ CPUState *cpu = NULL;
ObjectClass *oc;
CPUClass *cc;
Error *err = NULL;
@@ -60,16 +61,18 @@ CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
return NULL;
}
- cpu = CPU(object_new(object_class_get_name(oc)));
- cc = CPU_GET_CLASS(cpu);
-
+ cc = CPU_CLASS(oc);
featurestr = strtok(NULL, ",");
- cc->parse_features(cpu, featurestr, &err);
+ /* TODO: all callers of cpu_generic_init() need to be converted to
+ * call parse_features() only once, before calling cpu_generic_init().
+ */
+ cc->parse_features(object_class_get_name(oc), featurestr, &err);
g_free(str);
if (err != NULL) {
goto out;
}
+ cpu = CPU(object_new(object_class_get_name(oc)));
object_property_set_bool(OBJECT(cpu), true, "realized", &err);
out:
@@ -282,25 +285,39 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model)
return NULL;
}
-static void cpu_common_parse_features(CPUState *cpu, char *features,
+static void cpu_common_parse_features(const char *typename, char *features,
Error **errp)
{
char *featurestr; /* Single "key=value" string being parsed */
char *val;
- Error *err = NULL;
+ static bool cpu_globals_initialized;
+
+ /* TODO: all callers of ->parse_features() need to be changed to
+ * call it only once, so we can remove this check (or change it
+ * to assert(!cpu_globals_initialized).
+ * Current callers of ->parse_features() are:
+ * - machvirt_init()
+ * - cpu_generic_init()
+ * - cpu_x86_create()
+ */
+ if (cpu_globals_initialized) {
+ return;
+ }
+ cpu_globals_initialized = true;
featurestr = features ? strtok(features, ",") : NULL;
while (featurestr) {
val = strchr(featurestr, '=');
if (val) {
+ GlobalProperty *prop = g_new0(typeof(*prop), 1);
*val = 0;
val++;
- object_property_parse(OBJECT(cpu), val, featurestr, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
+ prop->driver = typename;
+ prop->property = g_strdup(featurestr);
+ prop->value = g_strdup(val);
+ prop->errp = &error_fatal;
+ qdev_prop_register_global(prop);
} else {
error_setg(errp, "Expected key=value format, found %s.",
featurestr);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 0b286e161c..16977d5404 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1958,12 +1958,17 @@ static FeatureWordArray minus_features = { 0 };
/* Parse "+feature,-feature,feature=foo" CPU feature string
*/
-static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
+static void x86_cpu_parse_featurestr(const char *typename, char *features,
Error **errp)
{
- X86CPU *cpu = X86_CPU(cs);
char *featurestr; /* Single 'key=value" string being parsed */
Error *local_err = NULL;
+ static bool cpu_globals_initialized;
+
+ if (cpu_globals_initialized) {
+ return;
+ }
+ cpu_globals_initialized = true;
if (!features) {
return;
@@ -1976,6 +1981,7 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
const char *val = NULL;
char *eq = NULL;
char num[32];
+ GlobalProperty *prop;
/* Compatibility syntax: */
if (featurestr[0] == '+') {
@@ -2013,7 +2019,12 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
name = "tsc-frequency";
}
- object_property_parse(OBJECT(cpu), val, name, &local_err);
+ prop = g_new0(typeof(*prop), 1);
+ prop->driver = typename;
+ prop->property = g_strdup(name);
+ prop->value = g_strdup(val);
+ prop->errp = &error_fatal;
+ qdev_prop_register_global(prop);
}
if (local_err) {
@@ -2202,9 +2213,11 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
{
X86CPU *cpu = NULL;
ObjectClass *oc;
+ CPUClass *cc;
gchar **model_pieces;
char *name, *features;
Error *error = NULL;
+ const char *typename;
model_pieces = g_strsplit(cpu_model, ",", 2);
if (!model_pieces[0]) {
@@ -2219,10 +2232,11 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
error_setg(&error, "Unable to find CPU definition: %s", name);
goto out;
}
+ cc = CPU_CLASS(oc);
+ typename = object_class_get_name(oc);
- cpu = X86_CPU(object_new(object_class_get_name(oc)));
-
- x86_cpu_parse_featurestr(CPU(cpu), features, &error);
+ cc->parse_features(typename, features, &error);
+ cpu = X86_CPU(object_new(typename));
if (error) {
goto out;
}