* [Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs
2012-01-15 15:39 [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Josh Triplett
@ 2012-01-15 15:39 ` Josh Triplett
2012-01-15 15:39 ` [Qemu-devel] [PATCH 2/3] Support arbitrary additional MSRs in cpu definitions Josh Triplett
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Josh Triplett @ 2012-01-15 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Liguori, Paul Brook
qemu normally returns 0 for rdmsr of an unknown MSR, and silently
ignores wrmsr of an unknown MSR. Add a new msr_gpf option to cpudef,
which when enabled causes qemu to generate a GPF on any access to an
unknown MSR.
This option allows qemu to better support software which detects the
availability of MSRs and their associated features by handling GPFs.
Signed-off-by: Josh Triplet <josh@joshtriplett.org>
---
qemu-config.c | 3 +++
target-i386/cpu.h | 1 +
target-i386/cpuid.c | 9 +++++++++
target-i386/op_helper.c | 16 ++++++++++++----
4 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index ecc88e8..8f9f16e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -416,6 +416,9 @@ static QemuOptsList qemu_cpudef_opts = {
},{
.name = "vendor_override",
.type = QEMU_OPT_NUMBER,
+ },{
+ .name = "msr_gpf",
+ .type = QEMU_OPT_BOOL,
},
{ /* end of list */ }
},
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 37dde79..c37cb30 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -734,6 +734,7 @@ typedef struct CPUX86State {
/* Store the results of Centaur's CPUID instructions */
uint32_t cpuid_xlevel2;
uint32_t cpuid_ext4_features;
+ bool msr_gpf;
/* MTRRs */
uint64_t mtrr_fixed[11];
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 91a104b..8cbbe9b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -234,6 +234,7 @@ typedef struct x86_def_t {
/* Store the results of Centaur's CPUID instructions */
uint32_t ext4_features;
uint32_t xlevel2;
+ bool msr_gpf;
} x86_def_t;
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -547,6 +548,8 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
*/
x86_cpu_def->svm_features = -1;
+ x86_cpu_def->msr_gpf = false;
+
return 0;
}
@@ -842,6 +845,8 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
0);
(*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n",
def->ext3_features, buf);
+ if (def->msr_gpf)
+ (*cpu_fprintf)(f, " GPF on unknown MSRs\n");
(*cpu_fprintf)(f, "\n");
}
}
@@ -884,6 +889,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_svm_features = def->svm_features;
env->cpuid_ext4_features = def->ext4_features;
env->cpuid_xlevel2 = def->xlevel2;
+ env->msr_gpf = def->msr_gpf;
env->tsc_khz = def->tsc_khz;
if (!kvm_enabled()) {
env->cpuid_features &= TCG_FEATURES;
@@ -995,6 +1001,8 @@ static int cpudef_setfield(const char *name, const char *str, void *opaque)
setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
} else if (!strcmp(name, "xlevel")) {
setscalar(&def->xlevel, str, &err)
+ } else if (!strcmp(name, "msr_gpf")) {
+ /* Handled in cpudef_register */
} else {
fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
return (1);
@@ -1013,6 +1021,7 @@ static int cpudef_register(QemuOpts *opts, void *opaque)
x86_def_t *def = g_malloc0(sizeof (x86_def_t));
qemu_opt_foreach(opts, cpudef_setfield, def, 1);
+ def->msr_gpf = qemu_opt_get_bool(opts, "msr_gpf", false);
def->next = x86_defs;
x86_defs = def;
return (0);
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 2aea71b..f782f03 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3292,7 +3292,10 @@ void helper_wrmsr(void)
env->mce_banks[offset] = val;
break;
}
- /* XXX: exception ? */
+ if (env->msr_gpf) {
+ raise_exception(EXCP0D_GPF);
+ return;
+ }
break;
}
}
@@ -3400,8 +3403,10 @@ void helper_rdmsr(void)
case MSR_MTRRcap:
if (env->cpuid_features & CPUID_MTRR)
val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;
- else
- /* XXX: exception ? */
+ else if (env->msr_gpf) {
+ raise_exception(EXCP0D_GPF);
+ return;
+ } else
val = 0;
break;
case MSR_MCG_CAP:
@@ -3426,7 +3431,10 @@ void helper_rdmsr(void)
val = env->mce_banks[offset];
break;
}
- /* XXX: exception ? */
+ if (env->msr_gpf) {
+ raise_exception(EXCP0D_GPF);
+ return;
+ }
val = 0;
break;
}
--
1.7.8.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/3] Support arbitrary additional MSRs in cpu definitions
2012-01-15 15:39 [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Josh Triplett
2012-01-15 15:39 ` [Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs Josh Triplett
@ 2012-01-15 15:39 ` Josh Triplett
2012-01-15 15:41 ` [Qemu-devel] [PATCH 3/3] Handle parse failures in CPU definitions, and avoid adding a partial cpudef Josh Triplett
2012-01-15 18:08 ` [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Andreas Färber
3 siblings, 0 replies; 5+ messages in thread
From: Josh Triplett @ 2012-01-15 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Liguori, Paul Brook
CPU definitions can now define arbitrary additional MSRs, and rdmsr will
support those MSRs and return the corresponding values.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---
qemu-config.c | 3 +++
target-i386/cpu.h | 5 +++++
target-i386/cpuid.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
target-i386/op_helper.c | 20 ++++++++++++++++++++
4 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index 8f9f16e..a675ba7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -419,6 +419,9 @@ static QemuOptsList qemu_cpudef_opts = {
},{
.name = "msr_gpf",
.type = QEMU_OPT_BOOL,
+ },{
+ .name = "msr",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index c37cb30..3c0f8f1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -613,6 +613,8 @@ typedef struct {
#define NB_MMU_MODES 2
+struct QDict;
+
typedef struct CPUX86State {
/* standard registers */
target_ulong regs[CPU_NB_REGS];
@@ -735,6 +737,9 @@ typedef struct CPUX86State {
uint32_t cpuid_xlevel2;
uint32_t cpuid_ext4_features;
bool msr_gpf;
+#ifdef CONFIG_SOFTMMU
+ struct QDict *msr_dict;
+#endif
/* MTRRs */
uint64_t mtrr_fixed[11];
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 8cbbe9b..ea55f69 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -26,6 +26,10 @@
#include "qemu-option.h"
#include "qemu-config.h"
+#ifdef CONFIG_SOFTMMU
+#include "qdict.h"
+#include "qint.h"
+#endif
/* feature flags taken from "Intel Processor Identification and the CPUID
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
@@ -235,6 +239,9 @@ typedef struct x86_def_t {
uint32_t ext4_features;
uint32_t xlevel2;
bool msr_gpf;
+#ifdef CONFIG_SOFTMMU
+ QDict *msr_dict;
+#endif
} x86_def_t;
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -624,6 +631,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
goto error;
} else {
memcpy(x86_cpu_def, def, sizeof(*def));
+#ifdef CONFIG_SOFTMMU
+ QINCREF(def->msr_dict);
+#endif
}
plus_kvm_features = ~0; /* not supported bits will be filtered out later */
@@ -847,6 +857,17 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
def->ext3_features, buf);
if (def->msr_gpf)
(*cpu_fprintf)(f, " GPF on unknown MSRs\n");
+#ifdef CONFIG_SOFTMMU
+ if (def->msr_dict) {
+ const QDictEntry *entry;
+ (*cpu_fprintf)(f, " Additional MSRs:\n");
+ for (entry = qdict_first(def->msr_dict); entry;
+ entry = qdict_next(def->msr_dict, entry))
+ (*cpu_fprintf)(f, " MSR 0x%s = 0x%" PRIx64 "\n",
+ qdict_entry_key(entry),
+ (uint64_t)qint_get_int(qobject_to_qint(qdict_entry_value(entry))));
+ }
+#endif
(*cpu_fprintf)(f, "\n");
}
}
@@ -890,6 +911,10 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_ext4_features = def->ext4_features;
env->cpuid_xlevel2 = def->xlevel2;
env->msr_gpf = def->msr_gpf;
+#ifdef CONFIG_SOFTMMU
+ env->msr_dict = def->msr_dict;
+ QINCREF(def->msr_dict);
+#endif
env->tsc_khz = def->tsc_khz;
if (!kvm_enabled()) {
env->cpuid_features &= TCG_FEATURES;
@@ -1003,6 +1028,26 @@ static int cpudef_setfield(const char *name, const char *str, void *opaque)
setscalar(&def->xlevel, str, &err)
} else if (!strcmp(name, "msr_gpf")) {
/* Handled in cpudef_register */
+ } else if (!strcmp(name, "msr")) {
+#ifdef CONFIG_SOFTMMU
+ int chars;
+ def->msr_dict = qdict_new();
+ /* Skip initial whitespace */
+ sscanf(str, " %n", &chars);
+ str += chars;
+ while (*str) {
+ int32_t num;
+ int64_t value;
+ char key[9];
+ if (sscanf(str, " %" SCNi32 " = %" SCNi64 " %n", &num, &value, &chars) < 2) {
+ fprintf(stderr, "error: bad value for msr option; failed to parse \"%s\"\n", str);
+ return 1;
+ }
+ str += chars;
+ snprintf(key, sizeof(key), "%x", (uint32_t)num);
+ qdict_put(def->msr_dict, key, qint_from_int(value));
+ }
+#endif
} else {
fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
return (1);
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index f782f03..c7d5dab 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -27,6 +27,11 @@
#include "cpu-defs.h"
#include "helper.h"
+#ifdef CONFIG_SOFTMMU
+#include "qdict.h"
+#include "qint.h"
+#endif
+
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
@@ -3306,6 +3311,21 @@ void helper_rdmsr(void)
helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
+#ifdef CONFIG_SOFTMMU
+ if (env->msr_dict) {
+ char key[9];
+ QObject *obj;
+ snprintf(key, sizeof(key), "%x", (uint32_t)ECX);
+ obj = qdict_get(env->msr_dict, key);
+ if (obj) {
+ val = (uint64_t)qint_get_int(qobject_to_qint(obj));
+ EAX = (uint32_t)(val);
+ EDX = (uint32_t)(val >> 32);
+ return;
+ }
+ }
+#endif
+
switch((uint32_t)ECX) {
case MSR_IA32_SYSENTER_CS:
val = env->sysenter_cs;
--
1.7.8.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 3/3] Handle parse failures in CPU definitions, and avoid adding a partial cpudef
2012-01-15 15:39 [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Josh Triplett
2012-01-15 15:39 ` [Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs Josh Triplett
2012-01-15 15:39 ` [Qemu-devel] [PATCH 2/3] Support arbitrary additional MSRs in cpu definitions Josh Triplett
@ 2012-01-15 15:41 ` Josh Triplett
2012-01-15 18:08 ` [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Andreas Färber
3 siblings, 0 replies; 5+ messages in thread
From: Josh Triplett @ 2012-01-15 15:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Liguori, Paul Brook
Without this change, a parse failure would stop the processing of the
cpudef entry, but the partially-parsed CPU definition would still get
added to the list of CPUs.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---
target-i386/cpuid.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index ea55f69..c2a95c4 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1065,7 +1065,10 @@ static int cpudef_register(QemuOpts *opts, void *opaque)
{
x86_def_t *def = g_malloc0(sizeof (x86_def_t));
- qemu_opt_foreach(opts, cpudef_setfield, def, 1);
+ if (qemu_opt_foreach(opts, cpudef_setfield, def, 1) != 0) {
+ g_free(def);
+ return 1;
+ }
def->msr_gpf = qemu_opt_get_bool(opts, "msr_gpf", false);
def->next = x86_defs;
x86_defs = def;
--
1.7.8.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs
2012-01-15 15:39 [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs Josh Triplett
` (2 preceding siblings ...)
2012-01-15 15:41 ` [Qemu-devel] [PATCH 3/3] Handle parse failures in CPU definitions, and avoid adding a partial cpudef Josh Triplett
@ 2012-01-15 18:08 ` Andreas Färber
3 siblings, 0 replies; 5+ messages in thread
From: Andreas Färber @ 2012-01-15 18:08 UTC (permalink / raw)
To: Josh Triplett; +Cc: Anthony Liguori, qemu-devel, Paul Brook
Am 15.01.2012 16:39, schrieb Josh Triplett:
> Josh Triplett (3):
> Add cpudef option to GPF on unknown MSRs
> Support arbitrary additional MSRs in cpu definitions
> Handle parse failures in CPU definitions, and avoid adding a partial
> cpudef
Please prefix the subjects with "target-i386: ". PowerPC has MSRs, too.
Thanks,
Andreas
> qemu-config.c | 6 ++++
> target-i386/cpu.h | 6 ++++
> target-i386/cpuid.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-
> target-i386/op_helper.c | 36 +++++++++++++++++++++++++---
> 4 files changed, 102 insertions(+), 5 deletions(-)
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 5+ messages in thread