From d0a6acf456a2497ce9f70f8366a5b405745ba279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 18:21:52 +0200 Subject: [PATCH 01/15] target-i386: Fix x86_cpuid_set_model_id() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't assume zeroed cpuid_model[] fields. This didn't break anything yet but QOM properties should be able to set the value to something else without setting an intermediate zero string. Reviewed-by: Eduardo Habhost Reviewed-by: Igor Mammedov [AF: Use memset() instead of for loop, suggested by Igor] Signed-off-by: Andreas Färber --- target-i386/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 3df53ca74b..e1517e65c6 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -627,6 +627,7 @@ static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id) model_id = ""; } len = strlen(model_id); + memset(env->cpuid_model, 0, 48); for (i = 0; i < 48; i++) { if (i >= len) { c = '\0'; From 61dcd775785b07a5e0c3858b67aa356b87543710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 12:00:51 +0200 Subject: [PATCH 02/15] target-i386: Pass X86CPU to cpu_x86_register() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids an x86_env_get_cpu() call there, to work with QOM properties. Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 3 ++- target-i386/cpu.h | 2 +- target-i386/helper.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e1517e65c6..3dc0f80c9a 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -905,8 +905,9 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) } } -int cpu_x86_register (CPUX86State *env, const char *cpu_model) +int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { + CPUX86State *env = &cpu->env; x86_def_t def1, *def = &def1; memset(def, 0, sizeof(*def)); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 4bb4592db5..b5b9a50695 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -901,7 +901,7 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo, void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); -int cpu_x86_register (CPUX86State *env, const char *cpu_model); +int cpu_x86_register(X86CPU *cpu, const char *cpu_model); void cpu_clear_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); diff --git a/target-i386/helper.c b/target-i386/helper.c index 87954f0919..0b22582ed6 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1176,7 +1176,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model) cpu_set_debug_excp_handler(breakpoint_handler); #endif } - if (cpu_x86_register(env, cpu_model) < 0) { + if (cpu_x86_register(cpu, cpu_model) < 0) { object_delete(OBJECT(cpu)); return NULL; } From a88a677f54e855c0453f06e0347904e4144e1c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 16:15:15 +0200 Subject: [PATCH 03/15] target-i386: Add range check for -cpu ,family=x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A family field value of 0xf and extended family field value of 0xff is the maximum representable unsigned family number. All other CPUID property values are bounds-checked, so add a check here for symmetry before we adopt it in a property setter. Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 3dc0f80c9a..5cebb3dd9b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -691,7 +691,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) if (!strcmp(featurestr, "family")) { char *err; numvalue = strtoul(val, &err, 0); - if (!*val || *err) { + if (!*val || *err || numvalue > 0xff + 0xf) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } From 71ad61d37e612119cca6967484f5feb165a169a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 12:10:29 +0200 Subject: [PATCH 04/15] target-i386: Add "family" property to X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the property early in the initfn so that it can be used in helpers such as mce_init(). Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost [AF: Add an error_free(), spotted by Michael Roth] Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 5cebb3dd9b..9eb5738e35 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -27,6 +27,8 @@ #include "qemu-option.h" #include "qemu-config.h" +#include "qapi/qapi-visit-core.h" + #include "hyperv.h" /* feature flags taken from "Intel Processor Identification and the CPUID @@ -597,13 +599,30 @@ static int check_features_against_host(x86_def_t *guest_def) return rv; } -static void x86_cpuid_version_set_family(CPUX86State *env, int family) +static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + const int64_t min = 0; + const int64_t max = 0xff + 0xf; + int64_t value; + + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + env->cpuid_version &= ~0xff00f00; - if (family > 0x0f) { - env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20); + if (value > 0x0f) { + env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20); } else { - env->cpuid_version |= family << 8; + env->cpuid_version |= value << 8; } } @@ -909,6 +928,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { CPUX86State *env = &cpu->env; x86_def_t def1, *def = &def1; + Error *error = NULL; memset(def, 0, sizeof(*def)); @@ -925,7 +945,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } env->cpuid_vendor_override = def->vendor_override; env->cpuid_level = def->level; - x86_cpuid_version_set_family(env, def->family); + object_property_set_int(OBJECT(cpu), def->family, "family", &error); x86_cpuid_version_set_model(env, def->model); x86_cpuid_version_set_stepping(env, def->stepping); env->cpuid_features = def->features; @@ -950,6 +970,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_svm_features &= TCG_SVM_FEATURES; } x86_cpuid_set_model_id(env, def->model_id); + if (error_is_set(&error)) { + error_free(error); + return -1; + } return 0; } @@ -1474,6 +1498,11 @@ static void x86_cpu_initfn(Object *obj) CPUX86State *env = &cpu->env; cpu_exec_init(env); + + object_property_add(obj, "family", "int", + NULL, + x86_cpuid_version_set_family, NULL, NULL, NULL); + env->cpuid_apic_id = env->cpu_index; mce_init(cpu); } From c5291a4f2d87310c5650064ab870251600b68c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 12:16:39 +0200 Subject: [PATCH 05/15] target-i386: Add "model" property to X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 9eb5738e35..ebee9914cc 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -626,10 +626,27 @@ static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, } } -static void x86_cpuid_version_set_model(CPUX86State *env, int model) +static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + const int64_t min = 0; + const int64_t max = 0xff; + int64_t value; + + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + env->cpuid_version &= ~0xf00f0; - env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16); + env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16); } static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping) @@ -946,7 +963,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_vendor_override = def->vendor_override; env->cpuid_level = def->level; object_property_set_int(OBJECT(cpu), def->family, "family", &error); - x86_cpuid_version_set_model(env, def->model); + object_property_set_int(OBJECT(cpu), def->model, "model", &error); x86_cpuid_version_set_stepping(env, def->stepping); env->cpuid_features = def->features; env->cpuid_ext_features = def->ext_features; @@ -1502,6 +1519,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "family", "int", NULL, x86_cpuid_version_set_family, NULL, NULL, NULL); + object_property_add(obj, "model", "int", + NULL, + x86_cpuid_version_set_model, NULL, NULL, NULL); env->cpuid_apic_id = env->cpu_index; mce_init(cpu); From 036e2222ca70f80515c6b780a30068cd0be8b7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 14:14:18 +0200 Subject: [PATCH 06/15] target-i386: Add "stepping" property to X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ebee9914cc..82194dd78a 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -649,10 +649,28 @@ static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16); } -static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping) +static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) { + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + const int64_t min = 0; + const int64_t max = 0xf; + int64_t value; + + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + env->cpuid_version &= ~0xf; - env->cpuid_version |= stepping & 0xf; + env->cpuid_version |= value & 0xf; } static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id) @@ -964,7 +982,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_level = def->level; object_property_set_int(OBJECT(cpu), def->family, "family", &error); object_property_set_int(OBJECT(cpu), def->model, "model", &error); - x86_cpuid_version_set_stepping(env, def->stepping); + object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error); env->cpuid_features = def->features; env->cpuid_ext_features = def->ext_features; env->cpuid_ext2_features = def->ext2_features; @@ -1522,6 +1540,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "model", "int", NULL, x86_cpuid_version_set_model, NULL, NULL, NULL); + object_property_add(obj, "stepping", "int", + NULL, + x86_cpuid_version_set_stepping, NULL, NULL, NULL); env->cpuid_apic_id = env->cpu_index; mce_init(cpu); From 938d4c2521149a13fc4dc77e68e31953d2ec5e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 15:17:27 +0200 Subject: [PATCH 07/15] target-i386: Add "model-id" property to X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 82194dd78a..bb57345125 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -673,8 +673,11 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, env->cpuid_version |= value & 0xf; } -static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id) +static void x86_cpuid_set_model_id(Object *obj, const char *model_id, + Error **errp) { + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; int c, len, i; if (model_id == NULL) { @@ -1004,7 +1007,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_ext3_features &= TCG_EXT3_FEATURES; env->cpuid_svm_features &= TCG_SVM_FEATURES; } - x86_cpuid_set_model_id(env, def->model_id); + object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error_is_set(&error)) { error_free(error); return -1; @@ -1543,6 +1546,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "stepping", "int", NULL, x86_cpuid_version_set_stepping, NULL, NULL, NULL); + object_property_add_str(obj, "model-id", + NULL, + x86_cpuid_set_model_id, NULL); env->cpuid_apic_id = env->cpu_index; mce_init(cpu); From 95b8519d163e4154f468288103d62937bce7598d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 14:42:22 +0200 Subject: [PATCH 08/15] target-i386: Add property getter for CPU family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bb57345125..90c1373576 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -599,6 +599,20 @@ static int check_features_against_host(x86_def_t *guest_def) return rv; } +static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + int64_t value; + + value = (env->cpuid_version >> 8) & 0xf; + if (value == 0xf) { + value += (env->cpuid_version >> 20) & 0xff; + } + visit_type_int(v, &value, name, errp); +} + static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -1538,7 +1552,7 @@ static void x86_cpu_initfn(Object *obj) cpu_exec_init(env); object_property_add(obj, "family", "int", - NULL, + x86_cpuid_version_get_family, x86_cpuid_version_set_family, NULL, NULL, NULL); object_property_add(obj, "model", "int", NULL, From 67e30c83497df23bb821d40648aec774910c3ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 14:48:14 +0200 Subject: [PATCH 09/15] target-i386: Add property getter for CPU model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Igor Mammedov Reviewed-by: Michael Roth --- target-i386/cpu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 90c1373576..7f63afd8f5 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -640,6 +640,18 @@ static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, } } +static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + int64_t value; + + value = (env->cpuid_version >> 4) & 0xf; + value |= ((env->cpuid_version >> 16) & 0xf) << 4; + visit_type_int(v, &value, name, errp); +} + static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -1555,7 +1567,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpuid_version_get_family, x86_cpuid_version_set_family, NULL, NULL, NULL); object_property_add(obj, "model", "int", - NULL, + x86_cpuid_version_get_model, x86_cpuid_version_set_model, NULL, NULL, NULL); object_property_add(obj, "stepping", "int", NULL, From 35112e415a771507fd94cca3b1a4ba4f99dd18d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 14:50:53 +0200 Subject: [PATCH 10/15] target-i386: Add property getter for CPU stepping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7f63afd8f5..2ff5142950 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -675,6 +675,18 @@ static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16); } +static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + int64_t value; + + value = env->cpuid_version & 0xf; + visit_type_int(v, &value, name, errp); +} + static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) @@ -1570,7 +1582,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpuid_version_get_model, x86_cpuid_version_set_model, NULL, NULL, NULL); object_property_add(obj, "stepping", "int", - NULL, + x86_cpuid_version_get_stepping, x86_cpuid_version_set_stepping, NULL, NULL, NULL); object_property_add_str(obj, "model-id", NULL, From 63e886ebef04c3c8b40735a1467a11caf3efda4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 23:02:26 +0200 Subject: [PATCH 11/15] target-i386: Add property getter for CPU model-id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 2ff5142950..8b5c47d7a0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -711,6 +711,21 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, env->cpuid_version |= value & 0xf; } +static char *x86_cpuid_get_model_id(Object *obj, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + char *value; + int i; + + value = g_malloc(48 + 1); + for (i = 0; i < 48; i++) { + value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3)); + } + value[48] = '\0'; + return value; +} + static void x86_cpuid_set_model_id(Object *obj, const char *model_id, Error **errp) { @@ -1585,7 +1600,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpuid_version_get_stepping, x86_cpuid_version_set_stepping, NULL, NULL, NULL); object_property_add_str(obj, "model-id", - NULL, + x86_cpuid_get_model_id, x86_cpuid_set_model_id, NULL); env->cpuid_apic_id = env->cpu_index; From 8e1898bf948ed03a22fb0dcb5a74ce3323692822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 18:41:40 +0200 Subject: [PATCH 12/15] target-i386: Introduce "level" property for X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 8b5c47d7a0..5b03c47610 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -711,6 +711,39 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, env->cpuid_version |= value & 0xf; } +static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + int64_t value; + + value = cpu->env.cpuid_level; + /* TODO Use visit_type_uint32() once available */ + visit_type_int(v, &value, name, errp); +} + +static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + const int64_t min = 0; + const int64_t max = UINT32_MAX; + int64_t value; + + /* TODO Use visit_type_uint32() once available */ + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + + cpu->env.cpuid_level = value; +} + static char *x86_cpuid_get_model_id(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); @@ -1035,7 +1068,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; } env->cpuid_vendor_override = def->vendor_override; - env->cpuid_level = def->level; + object_property_set_int(OBJECT(cpu), def->level, "level", &error); object_property_set_int(OBJECT(cpu), def->family, "family", &error); object_property_set_int(OBJECT(cpu), def->model, "model", &error); object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error); @@ -1599,6 +1632,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "stepping", "int", x86_cpuid_version_get_stepping, x86_cpuid_version_set_stepping, NULL, NULL, NULL); + object_property_add(obj, "level", "int", + x86_cpuid_get_level, + x86_cpuid_set_level, NULL, NULL, NULL); object_property_add_str(obj, "model-id", x86_cpuid_get_model_id, x86_cpuid_set_model_id, NULL); From 16b93aa89df07524a695855545a88522ef47fa36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 18:44:07 +0200 Subject: [PATCH 13/15] target-i386: Introduce "xlevel" property for X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 5b03c47610..deac4a7b95 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -744,6 +744,39 @@ static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque, cpu->env.cpuid_level = value; } +static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + int64_t value; + + value = cpu->env.cpuid_xlevel; + /* TODO Use visit_type_uint32() once available */ + visit_type_int(v, &value, name, errp); +} + +static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + const int64_t min = 0; + const int64_t max = UINT32_MAX; + int64_t value; + + /* TODO Use visit_type_uint32() once available */ + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + + cpu->env.cpuid_xlevel = value; +} + static char *x86_cpuid_get_model_id(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); @@ -1076,7 +1109,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_ext_features = def->ext_features; env->cpuid_ext2_features = def->ext2_features; env->cpuid_ext3_features = def->ext3_features; - env->cpuid_xlevel = def->xlevel; + object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error); env->cpuid_kvm_features = def->kvm_features; env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; @@ -1635,6 +1668,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "level", "int", x86_cpuid_get_level, x86_cpuid_set_level, NULL, NULL, NULL); + object_property_add(obj, "xlevel", "int", + x86_cpuid_get_xlevel, + x86_cpuid_set_xlevel, NULL, NULL, NULL); object_property_add_str(obj, "model-id", x86_cpuid_get_model_id, x86_cpuid_set_model_id, NULL); From d480e1aff2f3df3d02900905bcc8e0c4e4c108c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Apr 2012 19:22:58 +0200 Subject: [PATCH 14/15] target-i386: Prepare "vendor" property for X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using it now would incur converting the three x86_def_t vendor words into a string for object_property_set_str(), then back to three words in the "vendor" setter. The built-in CPU definitions use numeric preprocessor defines to initialize the three words in a charset-safe way, so do not change the fields to char[12] just to use the setter. Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index deac4a7b95..0ff79a5f41 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -777,6 +777,47 @@ static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque, cpu->env.cpuid_xlevel = value; } +static char *x86_cpuid_get_vendor(Object *obj, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + char *value; + int i; + + value = (char *)g_malloc(12 + 1); + for (i = 0; i < 4; i++) { + value[i ] = env->cpuid_vendor1 >> (8 * i); + value[i + 4] = env->cpuid_vendor2 >> (8 * i); + value[i + 8] = env->cpuid_vendor3 >> (8 * i); + } + value[12] = '\0'; + return value; +} + +static void x86_cpuid_set_vendor(Object *obj, const char *value, + Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + int i; + + if (strlen(value) != 12) { + error_set(errp, QERR_PROPERTY_VALUE_BAD, "", + "vendor", value); + return; + } + + env->cpuid_vendor1 = 0; + env->cpuid_vendor2 = 0; + env->cpuid_vendor3 = 0; + for (i = 0; i < 4; i++) { + env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i); + env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i); + env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i); + } + env->cpuid_vendor_override = 1; +} + static char *x86_cpuid_get_model_id(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); @@ -1671,6 +1712,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "xlevel", "int", x86_cpuid_get_xlevel, x86_cpuid_set_xlevel, NULL, NULL, NULL); + object_property_add_str(obj, "vendor", + x86_cpuid_get_vendor, + x86_cpuid_set_vendor, NULL); object_property_add_str(obj, "model-id", x86_cpuid_get_model_id, x86_cpuid_set_model_id, NULL); From 89e48965609f96900189aeb373e7e23693eb6eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 18 Apr 2012 00:12:23 +0200 Subject: [PATCH 15/15] target-i386: Introduce "tsc-frequency" property for X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use Hz as unit. Signed-off-by: Andreas Färber Reviewed-by: Eduardo Habkost Reviewed-by: Igor Mammedov --- target-i386/cpu.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 0ff79a5f41..65d9af6ac7 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -855,6 +855,37 @@ static void x86_cpuid_set_model_id(Object *obj, const char *model_id, } } +static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + int64_t value; + + value = cpu->env.tsc_khz * 1000; + visit_type_int(v, &value, name, errp); +} + +static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + const int64_t min = 0; + const int64_t max = INT_MAX; + int64_t value; + + visit_type_int(v, &value, name, errp); + if (error_is_set(errp)) { + return; + } + if (value < min || value > max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", + name ? name : "null", value, min, max); + return; + } + + cpu->env.tsc_khz = value / 1000; +} + static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) { unsigned int i; @@ -1155,7 +1186,8 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; env->cpuid_xlevel2 = def->xlevel2; - env->tsc_khz = def->tsc_khz; + object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, + "tsc-frequency", &error); if (!kvm_enabled()) { env->cpuid_features &= TCG_FEATURES; env->cpuid_ext_features &= TCG_EXT_FEATURES; @@ -1718,6 +1750,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add_str(obj, "model-id", x86_cpuid_get_model_id, x86_cpuid_set_model_id, NULL); + object_property_add(obj, "tsc-frequency", "int", + x86_cpuid_get_tsc_freq, + x86_cpuid_set_tsc_freq, NULL, NULL, NULL); env->cpuid_apic_id = env->cpu_index; mce_init(cpu);