@@ -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 */ }
},
@@ -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];
@@ -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);
@@ -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;
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(-)