[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs
From: |
Josh Triplett |
Subject: |
[Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs |
Date: |
Mon, 16 Jan 2012 02:39:38 +1100 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
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 <address@hidden>
---
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