* [Qemu-devel] [PATCH 0/3] Support configurable CPU Model-Specific Registers (MSRs) in cpudefs
@ 2012-01-15 15:39 Josh Triplett
2012-01-15 15:39 ` [Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs Josh Triplett
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Josh Triplett @ 2012-01-15 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Liguori, Paul Brook
This patch series adds configuration options allowing CPU definitions to
support rdmsr on arbitrary MSRs with corresponding values, and to GPF on
unknown MSRs. This allows better emulation of CPU-specific behavior. I plan
to use this to allow testing many of the CPU-specific tests in BITS
(http://biosbits.org/) via qemu/kvm rather than always via real systems with
the CPUs in question.
I've attached a sample configuration file for these new options, created
by copying the "Nehalem" CPU definition from the standard configuration
file and adding "NehalemGPF" and "NehalemMSR" definitions which take
advantage of the first and the first two patches, respectively. This
sample configuration makes it easy to validate the behavior added by the
first two patches.
I used a QDict to store the map from MSR numbers to values. Unfortunately,
QDict only supports strings as keys, so I had to format the MSR as a hex string
before looking it up.
The third patch in the series provides a bugfix for CPU definition parsing,
which will otherwise add a partial CPU definition (up to the parse failure) to
the list of CPU definitions.
Written on the plane to linux.conf.au.
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
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(-)
--
1.7.8.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [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
end of thread, other threads:[~2012-01-15 18:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).