mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
cpu: Use CPUClass->parse_features() as convertor to global properties
Currently CPUClass->parse_features() is used to parse -cpu features string and set properties on created CPU instances. But considering that features specified by -cpu apply to every created CPU instance, it doesn't make sense to parse the same features string for every CPU created. It also makes every target that cares about parsing features string explicitly call CPUClass->parse_features() parser, which gets in a way if we consider using generic device_add for CPU hotplug as device_add has not a clue about CPU specific hooks. Turns out we can use global properties mechanism to set properties on every created CPU instance for a given type. That way it's possible to convert CPU features into a set of global properties for CPU type specified by -cpu cpu_model and common Device.device_post_init() will apply them to CPU of given type automatically regardless whether it's manually created CPU or CPU created with help of device_add. Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
cf2887c973
commit
62a48a2a57
4 changed files with 54 additions and 22 deletions
41
qom/cpu.c
41
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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue