[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC] target-i386: Display i386 CPUID properties
From: |
Valentin Rakush |
Subject: |
[Qemu-devel] [RFC] target-i386: Display i386 CPUID properties |
Date: |
Tue, 12 Jan 2016 17:36:27 +0300 |
This is RFC because implementation depends on the upcoming class
properties
http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg03115.html
and also because this patch does not handle all x86_64 properties.
This RFC is in response to concerns pointed in this review but with changed
subject line as recommended.
http://lists.nongnu.org/archive/html/qemu-devel/2016-01/msg00053.html
This RFC demonstrates the way for displaying cpu properties using -cpu
help option.
Advantages:
- It is flexible and could be extended to all targets.
- With object class properties it would be possible to display cpu properties
from the single place with better granularity.
- displaying actual/default values for properties
There are things left TODO:
1. The patch from Daniel P. Berrange should be submitted.
- object properties now stored in hash table an dperhaps object class
properties should be stored in hash table as well
- add more functions for object class properties like getters,
iterators etc.
2. The code duplication in cpu_* functions should be refactored in final patch.
3. All target-i386 cpu properties should be reviewed and set during class
initialization.
4. Output formatting:
- list cpu properties per CPUID
- list cpu properties along with values
5. and more ...
Signed-off-by: Valentin Rakush <address@hidden>
---
include/qom/cpu.h | 2 +
include/qom/object.h | 46 +++++++++++
qom/cpu.c | 50 ++++++++++++
qom/object.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++
target-i386/cpu.c | 29 +++++++
vl.c | 2 +
6 files changed, 349 insertions(+)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 51a1323..4ec07ce 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -761,6 +761,8 @@ void QEMU_NORETURN cpu_abort(CPUState *cpu, const char
*fmt, ...)
GCC_FMT_ATTR(2, 3);
void cpu_exec_exit(CPUState *cpu);
+void cpu_properties_list(FILE *f, fprintf_function cpu_fprintf);
+
#ifdef CONFIG_SOFTMMU
extern const struct VMStateDescription vmstate_cpu_common;
#else
diff --git a/include/qom/object.h b/include/qom/object.h
index 4509166..9777565 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -344,6 +344,8 @@ typedef struct ObjectProperty
ObjectPropertyResolve *resolve;
ObjectPropertyRelease *release;
void *opaque;
+
+ QTAILQ_ENTRY(ObjectProperty) node;
} ObjectProperty;
/**
@@ -381,6 +383,8 @@ struct ObjectClass
const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];
ObjectUnparent *unparent;
+
+ QTAILQ_HEAD(, ObjectProperty) properties;
};
/**
@@ -944,6 +948,13 @@ ObjectProperty *object_property_add(Object *obj, const
char *name,
void object_property_del(Object *obj, const char *name, Error **errp);
+ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name,
+ const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque, Error **errp);
+
/**
* object_property_find:
* @obj: the object
@@ -954,6 +965,8 @@ void object_property_del(Object *obj, const char *name,
Error **errp);
*/
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp);
+ObjectProperty *object_class_property_find(ObjectClass *klass, const char
*name,
+ Error **errp);
typedef struct ObjectPropertyIterator ObjectPropertyIterator;
@@ -1371,6 +1384,12 @@ void object_property_add_str(Object *obj, const char
*name,
void (*set)(Object *, const char *, Error **),
Error **errp);
+void object_class_property_add_str(ObjectClass *klass, const char *name,
+ char *(*get)(Object *, Error **),
+ void (*set)(Object *, const char *,
+ Error **),
+ Error **errp);
+
/**
* object_property_add_bool:
* @obj: the object to add a property to
@@ -1387,6 +1406,11 @@ void object_property_add_bool(Object *obj, const char
*name,
void (*set)(Object *, bool, Error **),
Error **errp);
+void object_class_property_add_bool(ObjectClass *klass, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **),
+ Error **errp);
+
/**
* object_property_add_enum:
* @obj: the object to add a property to
@@ -1406,6 +1430,13 @@ void object_property_add_enum(Object *obj, const char
*name,
void (*set)(Object *, int, Error **),
Error **errp);
+void object_class_property_add_enum(ObjectClass *klass, const char *name,
+ const char *typename,
+ const char * const *strings,
+ int (*get)(Object *, Error **),
+ void (*set)(Object *, int, Error **),
+ Error **errp);
+
/**
* object_property_add_tm:
* @obj: the object to add a property to
@@ -1420,6 +1451,10 @@ void object_property_add_tm(Object *obj, const char
*name,
void (*get)(Object *, struct tm *, Error **),
Error **errp);
+void object_class_property_add_tm(ObjectClass *klass, const char *name,
+ void (*get)(Object *, struct tm *, Error **),
+ Error **errp);
+
/**
* object_property_add_uint8_ptr:
* @obj: the object to add a property to
@@ -1432,6 +1467,8 @@ void object_property_add_tm(Object *obj, const char *name,
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
+void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
+ const uint8_t *v, Error **errp);
/**
* object_property_add_uint16_ptr:
@@ -1445,6 +1482,8 @@ void object_property_add_uint8_ptr(Object *obj, const
char *name,
*/
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
+void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
+ const uint16_t *v, Error **errp);
/**
* object_property_add_uint32_ptr:
@@ -1458,6 +1497,8 @@ void object_property_add_uint16_ptr(Object *obj, const
char *name,
*/
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
+void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
+ const uint32_t *v, Error **errp);
/**
* object_property_add_uint64_ptr:
@@ -1471,6 +1512,8 @@ void object_property_add_uint32_ptr(Object *obj, const
char *name,
*/
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
+void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
+ const uint64_t *v, Error **Errp);
/**
* object_property_add_alias:
@@ -1522,6 +1565,9 @@ void object_property_add_const_link(Object *obj, const
char *name,
*/
void object_property_set_description(Object *obj, const char *name,
const char *description, Error **errp);
+void object_class_property_set_description(ObjectClass *klass, const char
*name,
+ const char *description,
+ Error **errp);
/**
* object_child_foreach:
diff --git a/qom/cpu.c b/qom/cpu.c
index fb80d13..8951f61 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -25,6 +25,7 @@
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
+#include "exec/cpu-common.h"
bool cpu_exists(int64_t id)
{
@@ -379,4 +380,53 @@ static void cpu_register_types(void)
type_register_static(&cpu_type_info);
}
+static void cpu_class_list_properties(ObjectClass* klass, FILE *f,
fprintf_function cpu_fprintf)
+{
+ ObjectProperty *prop;
+ ObjectClass *parent_klass;
+
+ parent_klass = object_class_get_parent(klass);
+ if (parent_klass) {
+ cpu_class_list_properties(parent_klass, f, cpu_fprintf);
+ }
+
+ QTAILQ_FOREACH(prop, &klass->properties, node) {
+ (*cpu_fprintf)(f, "%s ", prop->name);
+ }
+}
+
+static void cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *oc = data;
+ CPUListState *s = user_data;
+ const char *typename;
+ char *name;
+
+ typename = object_class_get_name(oc);
+ name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_CPU));
+ (*s->cpu_fprintf)(s->file, " %s : " , name);
+
+ cpu_class_list_properties(oc, s->file, s->cpu_fprintf);
+
+ (*s->cpu_fprintf)(s->file, "\n");
+
+ g_free(name);
+}
+
+void cpu_properties_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ CPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_CPU, false);
+ g_slist_foreach(list, cpu_list_entry, &s);
+ g_slist_free(list);
+
+ (*cpu_fprintf)(f, "\n");
+}
+
+
type_init(cpu_register_types)
diff --git a/qom/object.c b/qom/object.c
index d751569..8a5f8bc 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -268,6 +268,7 @@ static void type_initialize(TypeImpl *ti)
g_assert_cmpint(parent->class_size, <=, ti->class_size);
memcpy(ti->class, parent->class, parent->class_size);
ti->class->interfaces = NULL;
+ QTAILQ_INIT(&ti->class->properties);
for (e = parent->class->interfaces; e; e = e->next) {
InterfaceClass *iface = e->data;
@@ -292,6 +293,8 @@ static void type_initialize(TypeImpl *ti)
type_initialize_interface(ti, t, t);
}
+ } else {
+ QTAILQ_INIT(&ti->class->properties);
}
ti->class->type = ti;
@@ -939,10 +942,70 @@ object_property_add(Object *obj, const char *name, const
char *type,
return prop;
}
+ObjectProperty *
+object_class_property_add(ObjectClass *klass,
+ const char *name,
+ const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque,
+ Error **errp)
+{
+ ObjectProperty *prop;
+ size_t name_len = strlen(name);
+
+ if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
+ int i;
+ ObjectProperty *ret;
+ char *name_no_array = g_strdup(name);
+
+ name_no_array[name_len - 3] = '\0';
+ for (i = 0; ; ++i) {
+ char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
+
+ ret = object_class_property_add(klass, full_name, type, get, set,
+ release, opaque, NULL);
+ g_free(full_name);
+ if (ret) {
+ break;
+ }
+ }
+ g_free(name_no_array);
+ return ret;
+ }
+
+ if (object_class_property_find(klass, name, NULL) != NULL) {
+ error_setg(errp, "attempt to add duplicate property '%s'"
+ " to object (type '%s')", name,
+ object_class_get_name(klass));
+ return NULL;
+ }
+
+ prop = g_malloc0(sizeof(*prop));
+
+ prop->name = g_strdup(name);
+ prop->type = g_strdup(type);
+
+ prop->get = get;
+ prop->set = set;
+ prop->release = release;
+ prop->opaque = opaque;
+
+ QTAILQ_INSERT_TAIL(&klass->properties, prop, node);
+ return prop;
+}
+
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp)
{
ObjectProperty *prop;
+ ObjectClass *klass = object_get_class(obj);
+
+ prop = object_class_property_find(klass, name, NULL);
+ if (prop) {
+ return prop;
+ }
prop = g_hash_table_lookup(obj->properties, name);
if (prop) {
@@ -977,6 +1040,30 @@ ObjectProperty
*object_property_iter_next(ObjectPropertyIterator *iter)
return val;
}
+ObjectProperty *object_class_property_find(ObjectClass *klass, const char
*name,
+ Error **errp)
+{
+ ObjectProperty *prop;
+ ObjectClass *parent_klass;
+
+ parent_klass = object_class_get_parent(klass);
+ if (parent_klass) {
+ prop = object_class_property_find(parent_klass, name, NULL);
+ if (prop) {
+ return prop;
+ }
+ }
+
+ QTAILQ_FOREACH(prop, &klass->properties, node) {
+ if (strcmp(prop->name, name) == 0) {
+ return prop;
+ }
+ }
+
+ error_setg(errp, "Property '.%s' not found", name);
+ return NULL;
+}
+
void object_property_del(Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
@@ -1730,6 +1817,29 @@ void object_property_add_str(Object *obj, const char
*name,
}
}
+void object_class_property_add_str(ObjectClass *klass, const char *name,
+ char *(*get)(Object *, Error **),
+ void (*set)(Object *, const char *,
+ Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ StringProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, "string",
+ get ? property_get_str : NULL,
+ set ? property_set_str : NULL,
+ property_release_str,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
typedef struct BoolProperty
{
bool (*get)(Object *, Error **);
@@ -1797,6 +1907,28 @@ void object_property_add_bool(Object *obj, const char
*name,
}
}
+void object_class_property_add_bool(ObjectClass *klass, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ BoolProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, "bool",
+ get ? property_get_bool : NULL,
+ set ? property_set_bool : NULL,
+ property_release_bool,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
static void property_get_enum(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -1860,6 +1992,31 @@ void object_property_add_enum(Object *obj, const char
*name,
}
}
+void object_class_property_add_enum(ObjectClass *klass, const char *name,
+ const char *typename,
+ const char * const *strings,
+ int (*get)(Object *, Error **),
+ void (*set)(Object *, int, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ EnumProperty *prop = g_malloc(sizeof(*prop));
+
+ prop->strings = strings;
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, typename,
+ get ? property_get_enum : NULL,
+ set ? property_set_enum : NULL,
+ property_release_enum,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
typedef struct TMProperty {
void (*get)(Object *, struct tm *, Error **);
} TMProperty;
@@ -1939,6 +2096,25 @@ void object_property_add_tm(Object *obj, const char
*name,
}
}
+void object_class_property_add_tm(ObjectClass *klass, const char *name,
+ void (*get)(Object *, struct tm *, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ TMProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+
+ object_class_property_add(klass, name, "struct tm",
+ get ? property_get_tm : NULL, NULL,
+ property_release_tm,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
static char *qdev_get_type(Object *obj, Error **errp)
{
return g_strdup(object_get_typename(obj));
@@ -1983,6 +2159,13 @@ void object_property_add_uint8_ptr(Object *obj, const
char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
+ const uint8_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp)
{
@@ -1990,6 +2173,13 @@ void object_property_add_uint16_ptr(Object *obj, const
char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
+ const uint16_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp)
{
@@ -1997,6 +2187,13 @@ void object_property_add_uint32_ptr(Object *obj, const
char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
+ const uint32_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **errp)
{
@@ -2004,6 +2201,13 @@ void object_property_add_uint64_ptr(Object *obj, const
char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
+ const uint64_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
typedef struct {
Object *target_obj;
char *target_name;
@@ -2101,6 +2305,22 @@ void object_property_set_description(Object *obj, const
char *name,
op->description = g_strdup(description);
}
+void object_class_property_set_description(ObjectClass *klass,
+ const char *name,
+ const char *description,
+ Error **errp)
+{
+ ObjectProperty *op;
+
+ op = object_class_property_find(klass, name, errp);
+ if (!op) {
+ return;
+ }
+
+ g_free(op->description);
+ op->description = g_strdup(description);
+}
+
static void object_instance_init(Object *obj)
{
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 0d447b5..13c36a9 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -3202,6 +3202,35 @@ static void x86_cpu_common_class_init(ObjectClass *oc,
void *data)
cc->cpu_exec_enter = x86_cpu_exec_enter;
cc->cpu_exec_exit = x86_cpu_exec_exit;
+
+ object_class_property_add(oc, "family", "int",
+ x86_cpuid_version_get_family,
+ x86_cpuid_version_set_family, NULL, NULL, NULL);
+ object_class_property_add(oc, "model", "int",
+ x86_cpuid_version_get_model,
+ x86_cpuid_version_set_model, NULL, NULL, NULL);
+ object_class_property_add(oc, "stepping", "int",
+ x86_cpuid_version_get_stepping,
+ x86_cpuid_version_set_stepping, NULL, NULL,
NULL);
+ object_class_property_add_str(oc, "vendor",
+ x86_cpuid_get_vendor,
+ x86_cpuid_set_vendor, NULL);
+ object_class_property_add_str(oc, "model-id",
+ x86_cpuid_get_model_id,
+ x86_cpuid_set_model_id, NULL);
+ object_class_property_add(oc, "tsc-frequency", "int",
+ x86_cpuid_get_tsc_freq,
+ x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+ object_class_property_add(oc, "apic-id", "int",
+ x86_cpuid_get_apic_id,
+ x86_cpuid_set_apic_id, NULL, NULL, NULL);
+ object_class_property_add(oc, "feature-words", "X86CPUFeatureWordInfo",
+ x86_cpu_get_feature_words,
+ NULL, NULL, NULL, NULL);
+ object_class_property_add(oc, "filtered-features", "X86CPUFeatureWordInfo",
+ x86_cpu_get_feature_words,
+ NULL, NULL, NULL, NULL);
+
/*
* Reason: x86_cpu_initfn() calls cpu_exec_init(), which saves the
* object in cpus -> dangling pointer after final object_unref().
diff --git a/vl.c b/vl.c
index 5aaea77..ebe4552 100644
--- a/vl.c
+++ b/vl.c
@@ -4092,6 +4092,8 @@ int main(int argc, char **argv, char **envp)
if (cpu_model && is_help_option(cpu_model)) {
list_cpus(stdout, &fprintf, cpu_model);
+ printf("\nRecognized CPUID properties:\n");
+ cpu_properties_list(stdout, &fprintf);
exit(0);
}
--
1.8.3.1
- [Qemu-devel] [RFC] target-i386: Display i386 CPUID properties,
Valentin Rakush <=