diff options
author | Eduardo Habkost <ehabkost@redhat.com> | 2015-03-23 17:29:32 -0300 |
---|---|---|
committer | Eduardo Habkost <ehabkost@redhat.com> | 2015-06-02 15:15:52 -0300 |
commit | 38e5c119c2925812bd441450ab9e5e00fc79e662 (patch) | |
tree | 28a3db7a35211da597857d5b75b4439f51c58c4a /target-i386 | |
parent | be9f8a08727e46c790adb8caa8a4525a1e8e9e73 (diff) |
target-i386: Register QOM properties for feature flags
This uses the feature name arrays to register QOM properties for feature
flags. This simply adds properties that can be configured using -global,
but doesn't change x86_cpu_parse_featurestr() to use them yet.
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 3305e09413..99ad551bee 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2841,12 +2841,126 @@ out: } } +typedef struct BitProperty { + uint32_t *ptr; + uint32_t mask; +} BitProperty; + +static void x86_cpu_get_bit_prop(Object *obj, + struct Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + BitProperty *fp = opaque; + bool value = (*fp->ptr & fp->mask) == fp->mask; + visit_type_bool(v, &value, name, errp); +} + +static void x86_cpu_set_bit_prop(Object *obj, + struct Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + BitProperty *fp = opaque; + Error *local_err = NULL; + bool value; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_bool(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (value) { + *fp->ptr |= fp->mask; + } else { + *fp->ptr &= ~fp->mask; + } +} + +static void x86_cpu_release_bit_prop(Object *obj, const char *name, + void *opaque) +{ + BitProperty *prop = opaque; + g_free(prop); +} + +/* Register a boolean property to get/set a single bit in a uint32_t field. + * + * The same property name can be registered multiple times to make it affect + * multiple bits in the same FeatureWord. In that case, the getter will return + * true only if all bits are set. + */ +static void x86_cpu_register_bit_prop(X86CPU *cpu, + const char *prop_name, + uint32_t *field, + int bitnr) +{ + BitProperty *fp; + ObjectProperty *op; + uint32_t mask = (1UL << bitnr); + + op = object_property_find(OBJECT(cpu), prop_name, NULL); + if (op) { + fp = op->opaque; + assert(fp->ptr == field); + fp->mask |= mask; + } else { + fp = g_new0(BitProperty, 1); + fp->ptr = field; + fp->mask = mask; + object_property_add(OBJECT(cpu), prop_name, "bool", + x86_cpu_get_bit_prop, + x86_cpu_set_bit_prop, + x86_cpu_release_bit_prop, fp, &error_abort); + } +} + +static void x86_cpu_register_feature_bit_props(X86CPU *cpu, + FeatureWord w, + int bitnr) +{ + Object *obj = OBJECT(cpu); + int i; + char **names; + FeatureWordInfo *fi = &feature_word_info[w]; + + if (!fi->feat_names) { + return; + } + if (!fi->feat_names[bitnr]) { + return; + } + + names = g_strsplit(fi->feat_names[bitnr], "|", 0); + + feat2prop(names[0]); + x86_cpu_register_bit_prop(cpu, names[0], &cpu->env.features[w], bitnr); + + for (i = 1; names[i]; i++) { + feat2prop(names[i]); + object_property_add_alias(obj, names[i], obj, g_strdup(names[0]), + &error_abort); + } + + g_strfreev(names); +} + static void x86_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); X86CPU *cpu = X86_CPU(obj); X86CPUClass *xcc = X86_CPU_GET_CLASS(obj); CPUX86State *env = &cpu->env; + FeatureWord w; static int inited; cs->env_ptr = env; @@ -2887,6 +3001,14 @@ static void x86_cpu_initfn(Object *obj) cpu->apic_id = -1; #endif + for (w = 0; w < FEATURE_WORDS; w++) { + int bitnr; + + for (bitnr = 0; bitnr < 32; bitnr++) { + x86_cpu_register_feature_bit_props(cpu, w, bitnr); + } + } + x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); /* init various static tables used in TCG mode */ |