aboutsummaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/cpu-qom.h15
-rw-r--r--target-i386/cpu.c307
-rw-r--r--target-i386/cpu.h26
-rw-r--r--target-i386/excp_helper.c6
-rw-r--r--target-i386/helper.c77
-rw-r--r--target-i386/kvm.c8
-rw-r--r--target-i386/machine.c7
-rw-r--r--target-i386/mem_helper.c16
-rw-r--r--target-i386/misc_helper.c20
-rw-r--r--target-i386/seg_helper.c20
-rw-r--r--target-i386/smm_helper.c2
-rw-r--r--target-i386/svm_helper.c41
-rw-r--r--target-i386/translate.c4
13 files changed, 339 insertions, 210 deletions
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 722f11a..e9b3d57 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -38,7 +38,17 @@
OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
/**
+ * X86CPUDefinition:
+ *
+ * CPU model definition data that was not converted to QOM per-subclass
+ * property defaults yet.
+ */
+typedef struct X86CPUDefinition X86CPUDefinition;
+
+/**
* X86CPUClass:
+ * @cpu_def: CPU model definition
+ * @kvm_required: Whether CPU model requires KVM to be enabled.
* @parent_realize: The parent class' realize handler.
* @parent_reset: The parent class' reset handler.
*
@@ -49,6 +59,11 @@ typedef struct X86CPUClass {
CPUClass parent_class;
/*< public >*/
+ /* Should be eventually replaced by subclass-specific property defaults. */
+ X86CPUDefinition *cpu_def;
+
+ bool kvm_required;
+
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
} X86CPUClass;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 5cfe450..e7e62c5 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -358,17 +358,23 @@ typedef struct model_features_t {
FeatureWord feat_word;
} model_features_t;
-static uint32_t kvm_default_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
+/* KVM-specific features that are automatically added to all CPU models
+ * when KVM is enabled.
+ */
+static uint32_t kvm_default_features[FEATURE_WORDS] = {
+ [FEAT_KVM] = (1 << KVM_FEATURE_CLOCKSOURCE) |
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
(1 << KVM_FEATURE_STEAL_TIME) |
(1 << KVM_FEATURE_PV_EOI) |
- (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+ (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT),
+ [FEAT_1_ECX] = CPUID_EXT_X2APIC,
+};
-void disable_kvm_pv_eoi(void)
+void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features)
{
- kvm_default_features &= ~(1UL << KVM_FEATURE_PV_EOI);
+ kvm_default_features[w] &= ~features;
}
void host_cpuid(uint32_t function, uint32_t count,
@@ -484,7 +490,35 @@ static void add_flagname_to_bitmaps(const char *flagname,
}
}
-typedef struct x86_def_t {
+/* CPU class name definitions: */
+
+#define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU
+#define X86_CPU_TYPE_NAME(name) (name X86_CPU_TYPE_SUFFIX)
+
+/* Return type name for a given CPU model name
+ * Caller is responsible for freeing the returned string.
+ */
+static char *x86_cpu_type_name(const char *model_name)
+{
+ return g_strdup_printf(X86_CPU_TYPE_NAME("%s"), model_name);
+}
+
+static ObjectClass *x86_cpu_class_by_name(const char *cpu_model)
+{
+ ObjectClass *oc;
+ char *typename;
+
+ if (cpu_model == NULL) {
+ return NULL;
+ }
+
+ typename = x86_cpu_type_name(cpu_model);
+ oc = object_class_by_name(typename);
+ g_free(typename);
+ return oc;
+}
+
+struct X86CPUDefinition {
const char *name;
uint32_t level;
uint32_t xlevel;
@@ -497,7 +531,7 @@ typedef struct x86_def_t {
FeatureWordArray features;
char model_id[48];
bool cache_info_passthrough;
-} x86_def_t;
+};
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
@@ -547,9 +581,7 @@ typedef struct x86_def_t {
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
CPUID_7_0_EBX_RDSEED */
-/* built-in CPU model definitions
- */
-static x86_def_t builtin_x86_defs[] = {
+static X86CPUDefinition builtin_x86_defs[] = {
{
.name = "qemu64",
.level = 4,
@@ -1108,7 +1140,7 @@ static x86_def_t builtin_x86_defs[] = {
void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
uint32_t feat_add, uint32_t feat_remove)
{
- x86_def_t *def;
+ X86CPUDefinition *def;
int i;
for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
def = &builtin_x86_defs[i];
@@ -1119,6 +1151,8 @@ void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
}
}
+#ifdef CONFIG_KVM
+
static int cpu_x86_fill_model_id(char *str)
{
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
@@ -1134,44 +1168,68 @@ static int cpu_x86_fill_model_id(char *str)
return 0;
}
-/* Fill a x86_def_t struct with information about the host CPU, and
- * the CPU features supported by the host hardware + host kernel
+static X86CPUDefinition host_cpudef;
+
+/* class_init for the "host" CPU model
*
- * This function may be called only if KVM is enabled.
+ * This function may be called before KVM is initialized.
*/
-static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
+static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
{
- KVMState *s = kvm_state;
+ X86CPUClass *xcc = X86_CPU_CLASS(oc);
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
- assert(kvm_enabled());
+ xcc->kvm_required = true;
- x86_cpu_def->name = "host";
- x86_cpu_def->cache_info_passthrough = true;
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
- x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx);
+ x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
- x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
- x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
- x86_cpu_def->stepping = eax & 0x0F;
+ host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+ host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+ host_cpudef.stepping = eax & 0x0F;
- x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
- x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
- x86_cpu_def->xlevel2 =
- kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
+ cpu_x86_fill_model_id(host_cpudef.model_id);
- cpu_x86_fill_model_id(x86_cpu_def->model_id);
+ xcc->cpu_def = &host_cpudef;
+ host_cpudef.cache_info_passthrough = true;
+ /* level, xlevel, xlevel2, and the feature words are initialized on
+ * instance_init, because they require KVM to be initialized.
+ */
+}
+
+static void host_x86_cpu_initfn(Object *obj)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ KVMState *s = kvm_state;
FeatureWord w;
+
+ assert(kvm_enabled());
+
+ env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
+ env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
+ env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
+
for (w = 0; w < FEATURE_WORDS; w++) {
FeatureWordInfo *wi = &feature_word_info[w];
- x86_cpu_def->features[w] =
+ env->features[w] =
kvm_arch_get_supported_cpuid(s, wi->cpuid_eax, wi->cpuid_ecx,
wi->cpuid_reg);
}
+ object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
}
+static const TypeInfo host_x86_cpu_type_info = {
+ .name = X86_CPU_TYPE_NAME("host"),
+ .parent = TYPE_X86_CPU,
+ .instance_init = host_x86_cpu_initfn,
+ .class_init = host_x86_cpu_class_init,
+};
+
+#endif
+
static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask)
{
int i;
@@ -1582,32 +1640,6 @@ static PropertyInfo qdev_prop_spinlocks = {
.set = x86_set_hv_spinlocks,
};
-static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
- const char *name)
-{
- x86_def_t *def;
- int i;
-
- if (name == NULL) {
- return -1;
- }
- if (kvm_enabled() && strcmp(name, "host") == 0) {
- kvm_cpu_fill_host(x86_cpu_def);
- object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
- def = &builtin_x86_defs[i];
- if (strcmp(name, def->name) == 0) {
- memcpy(x86_cpu_def, def, sizeof(*def));
- return 0;
- }
- }
-
- return -1;
-}
-
/* Convert all '_' in a feature string option name to '-', to make feature
* name conform to QOM property naming rule, which uses '-' instead of '_'.
*/
@@ -1620,8 +1652,10 @@ static inline void feat2prop(char *s)
/* Parse "+feature,-feature,feature=foo" CPU feature string
*/
-static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
+static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
+ Error **errp)
{
+ X86CPU *cpu = X86_CPU(cs);
char *featurestr; /* Single 'key=value" string being parsed */
/* Features to be added */
FeatureWordArray plus_features = { 0 };
@@ -1629,6 +1663,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
FeatureWordArray minus_features = { 0 };
uint32_t numvalue;
CPUX86State *env = &cpu->env;
+ Error *local_err = NULL;
featurestr = features ? strtok(features, ",") : NULL;
@@ -1647,16 +1682,16 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
numvalue = strtoul(val, &err, 0);
if (!*val || *err) {
- error_setg(errp, "bad numerical value %s", val);
+ error_setg(&local_err, "bad numerical value %s", val);
goto out;
}
if (numvalue < 0x80000000) {
- fprintf(stderr, "xlevel value shall always be >= 0x80000000"
- ", fixup will be removed in future versions\n");
+ error_report("xlevel value shall always be >= 0x80000000"
+ ", fixup will be removed in future versions");
numvalue += 0x80000000;
}
snprintf(num, sizeof(num), "%" PRIu32, numvalue);
- object_property_parse(OBJECT(cpu), num, featurestr, errp);
+ object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
} else if (!strcmp(featurestr, "tsc-freq")) {
int64_t tsc_freq;
char *err;
@@ -1665,36 +1700,38 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
tsc_freq = strtosz_suffix_unit(val, &err,
STRTOSZ_DEFSUFFIX_B, 1000);
if (tsc_freq < 0 || *err) {
- error_setg(errp, "bad numerical value %s", val);
+ error_setg(&local_err, "bad numerical value %s", val);
goto out;
}
snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
- object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp);
+ object_property_parse(OBJECT(cpu), num, "tsc-frequency",
+ &local_err);
} else if (!strcmp(featurestr, "hv-spinlocks")) {
char *err;
const int min = 0xFFF;
char num[32];
numvalue = strtoul(val, &err, 0);
if (!*val || *err) {
- error_setg(errp, "bad numerical value %s", val);
+ error_setg(&local_err, "bad numerical value %s", val);
goto out;
}
if (numvalue < min) {
- fprintf(stderr, "hv-spinlocks value shall always be >= 0x%x"
- ", fixup will be removed in future versions\n",
+ error_report("hv-spinlocks value shall always be >= 0x%x"
+ ", fixup will be removed in future versions",
min);
numvalue = min;
}
snprintf(num, sizeof(num), "%" PRId32, numvalue);
- object_property_parse(OBJECT(cpu), num, featurestr, errp);
+ object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
} else {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
+ object_property_parse(OBJECT(cpu), val, featurestr, &local_err);
}
} else {
feat2prop(featurestr);
- object_property_parse(OBJECT(cpu), "on", featurestr, errp);
+ object_property_parse(OBJECT(cpu), "on", featurestr, &local_err);
}
- if (error_is_set(errp)) {
+ if (local_err) {
+ error_propagate(errp, local_err);
goto out;
}
featurestr = strtok(NULL, ",");
@@ -1753,7 +1790,7 @@ static void listflags(char *buf, int bufsize, uint32_t fbits,
/* generate CPU information. */
void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
- x86_def_t *def;
+ X86CPUDefinition *def;
char buf[256];
int i;
@@ -1780,7 +1817,7 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
{
CpuDefinitionInfoList *cpu_list = NULL;
- x86_def_t *def;
+ X86CPUDefinition *def;
int i;
for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
@@ -1817,17 +1854,13 @@ static void filter_features_for_kvm(X86CPU *cpu)
}
}
-static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
+/* Load data from X86CPUDefinition
+ */
+static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
{
CPUX86State *env = &cpu->env;
- x86_def_t def1, *def = &def1;
-
- memset(def, 0, sizeof(*def));
-
- if (cpu_x86_find_by_name(cpu, def, name) < 0) {
- error_setg(errp, "Unable to find CPU definition: %s", name);
- return;
- }
+ const char *vendor;
+ char host_vendor[CPUID_VENDOR_SZ + 1];
object_property_set_int(OBJECT(cpu), def->level, "level", errp);
object_property_set_int(OBJECT(cpu), def->family, "family", errp);
@@ -1847,10 +1880,14 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
- /* Special cases not set in the x86_def_t structs: */
+ /* Special cases not set in the X86CPUDefinition structs: */
if (kvm_enabled()) {
- env->features[FEAT_KVM] |= kvm_default_features;
+ FeatureWord w;
+ for (w = 0; w < FEATURE_WORDS; w++) {
+ env->features[w] |= kvm_default_features[w];
+ }
}
+
env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
/* sysenter isn't supported in compatibility mode on AMD,
@@ -1860,8 +1897,7 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
* KVM's sysenter/syscall emulation in compatibility mode and
* when doing cross vendor migration
*/
- const char *vendor = def->vendor;
- char host_vendor[CPUID_VENDOR_SZ + 1];
+ vendor = def->vendor;
if (kvm_enabled()) {
uint32_t ebx = 0, ecx = 0, edx = 0;
host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
@@ -1877,9 +1913,10 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
Error **errp)
{
X86CPU *cpu = NULL;
+ X86CPUClass *xcc;
+ ObjectClass *oc;
gchar **model_pieces;
char *name, *features;
- char *typename;
Error *error = NULL;
model_pieces = g_strsplit(cpu_model, ",", 2);
@@ -1890,30 +1927,30 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
name = model_pieces[0];
features = model_pieces[1];
- cpu = X86_CPU(object_new(TYPE_X86_CPU));
-#ifndef CONFIG_USER_ONLY
- if (icc_bridge == NULL) {
- error_setg(&error, "Invalid icc-bridge value");
+ oc = x86_cpu_class_by_name(name);
+ if (oc == NULL) {
+ error_setg(&error, "Unable to find CPU definition: %s", name);
goto out;
}
- qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
- object_unref(OBJECT(cpu));
-#endif
+ xcc = X86_CPU_CLASS(oc);
- cpu_x86_register(cpu, name, &error);
- if (error) {
+ if (xcc->kvm_required && !kvm_enabled()) {
+ error_setg(&error, "CPU model '%s' requires KVM", name);
goto out;
}
- /* Emulate per-model subclasses for global properties */
- typename = g_strdup_printf("%s-" TYPE_X86_CPU, name);
- qdev_prop_set_globals_for_type(DEVICE(cpu), typename, &error);
- g_free(typename);
- if (error) {
+ cpu = X86_CPU(object_new(object_class_get_name(oc)));
+
+#ifndef CONFIG_USER_ONLY
+ if (icc_bridge == NULL) {
+ error_setg(&error, "Invalid icc-bridge value");
goto out;
}
+ qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
+ object_unref(OBJECT(cpu));
+#endif
- cpu_x86_parse_featurestr(cpu, features, &error);
+ x86_cpu_parse_featurestr(CPU(cpu), features, &error);
if (error) {
goto out;
}
@@ -1921,8 +1958,10 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
out:
if (error != NULL) {
error_propagate(errp, error);
- object_unref(OBJECT(cpu));
- cpu = NULL;
+ if (cpu) {
+ object_unref(OBJECT(cpu));
+ cpu = NULL;
+ }
}
g_strfreev(model_pieces);
return cpu;
@@ -1952,6 +1991,28 @@ out:
return cpu;
}
+static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
+{
+ X86CPUDefinition *cpudef = data;
+ X86CPUClass *xcc = X86_CPU_CLASS(oc);
+
+ xcc->cpu_def = cpudef;
+}
+
+static void x86_register_cpudef_type(X86CPUDefinition *def)
+{
+ char *typename = x86_cpu_type_name(def->name);
+ TypeInfo ti = {
+ .name = typename,
+ .parent = TYPE_X86_CPU,
+ .class_init = x86_cpu_cpudef_class_init,
+ .class_data = def,
+ };
+
+ type_register(&ti);
+ g_free(typename);
+}
+
#if !defined(CONFIG_USER_ONLY)
void cpu_clear_apic_feature(CPUX86State *env)
@@ -1969,7 +2030,7 @@ void x86_cpudef_setup(void)
static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" };
for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
- x86_def_t *def = &builtin_x86_defs[i];
+ X86CPUDefinition *def = &builtin_x86_defs[i];
/* Look for specific "cpudef" models that */
/* have the QEMU version in .model_id */
@@ -2349,9 +2410,9 @@ static void x86_cpu_reset(CPUState *s)
xcc->parent_reset(s);
- memset(env, 0, offsetof(CPUX86State, breakpoints));
+ memset(env, 0, offsetof(CPUX86State, pat));
- tlb_flush(env, 1);
+ tlb_flush(s, 1);
env->old_exception = -1;
@@ -2412,8 +2473,8 @@ static void x86_cpu_reset(CPUState *s)
memset(env->dr, 0, sizeof(env->dr));
env->dr[6] = DR6_FIXED_1;
env->dr[7] = DR7_FIXED_1;
- cpu_breakpoint_remove_all(env, BP_CPU);
- cpu_watchpoint_remove_all(env, BP_CPU);
+ cpu_breakpoint_remove_all(s, BP_CPU);
+ cpu_watchpoint_remove_all(s, BP_CPU);
env->tsc_adjust = 0;
env->tsc = 0;
@@ -2613,6 +2674,7 @@ static void x86_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
X86CPU *cpu = X86_CPU(obj);
+ X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
CPUX86State *env = &cpu->env;
static int inited;
@@ -2656,6 +2718,8 @@ static void x86_cpu_initfn(Object *obj)
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
+ x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
+
/* init various static tables used in TCG mode */
if (tcg_enabled() && !inited) {
inited = 1;
@@ -2695,6 +2759,20 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
cpu->env.eip = tb->pc - tb->cs_base;
}
+static bool x86_cpu_has_work(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_POLL)) &&
+ (env->eflags & IF_MASK)) ||
+ (cs->interrupt_request & (CPU_INTERRUPT_NMI |
+ CPU_INTERRUPT_INIT |
+ CPU_INTERRUPT_SIPI |
+ CPU_INTERRUPT_MCE));
+}
+
static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
{ .name = "hv-spinlocks", .info = &qdev_prop_spinlocks },
@@ -2721,6 +2799,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->reset = x86_cpu_reset;
cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
+ cc->class_by_name = x86_cpu_class_by_name;
+ cc->parse_features = x86_cpu_parse_featurestr;
+ cc->has_work = x86_cpu_has_work;
cc->do_interrupt = x86_cpu_do_interrupt;
cc->dump_state = x86_cpu_dump_state;
cc->set_pc = x86_cpu_set_pc;
@@ -2729,7 +2810,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->gdb_write_register = x86_cpu_gdb_write_register;
cc->get_arch_id = x86_cpu_get_arch_id;
cc->get_paging_enabled = x86_cpu_get_paging_enabled;
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+ cc->handle_mmu_fault = x86_cpu_handle_mmu_fault;
+#else
cc->get_memory_mapping = x86_cpu_get_memory_mapping;
cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
cc->write_elf64_note = x86_cpu_write_elf64_note;
@@ -2746,14 +2829,22 @@ static const TypeInfo x86_cpu_type_info = {
.parent = TYPE_CPU,
.instance_size = sizeof(X86CPU),
.instance_init = x86_cpu_initfn,
- .abstract = false,
+ .abstract = true,
.class_size = sizeof(X86CPUClass),
.class_init = x86_cpu_common_class_init,
};
static void x86_cpu_register_types(void)
{
+ int i;
+
type_register_static(&x86_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
+ x86_register_cpudef_type(&builtin_x86_defs[i]);
+ }
+#ifdef CONFIG_KVM
+ type_register_static(&host_x86_cpu_type_info);
+#endif
}
type_init(x86_cpu_register_types)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 0014acc..4d1374c 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -875,8 +875,8 @@ typedef struct CPUX86State {
target_ulong exception_next_eip;
target_ulong dr[8]; /* debug registers */
union {
- CPUBreakpoint *cpu_breakpoint[4];
- CPUWatchpoint *cpu_watchpoint[4];
+ struct CPUBreakpoint *cpu_breakpoint[4];
+ struct CPUWatchpoint *cpu_watchpoint[4];
}; /* break/watchpoints for dr[0..3] */
uint32_t smbase;
int old_exception; /* exception in flight */
@@ -887,6 +887,7 @@ typedef struct CPUX86State {
CPU_COMMON
+ /* Fields from here on are preserved across CPU reset. */
uint64_t pat;
/* processor features (e.g. for CPUID insn) */
@@ -1067,9 +1068,8 @@ void host_cpuid(uint32_t function, uint32_t count,
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
/* helper.c */
-int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr,
int is_write, int mmu_idx);
-#define cpu_handle_mmu_fault cpu_x86_handle_mmu_fault
void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
static inline bool hw_local_breakpoint_enabled(unsigned long dr7, int index)
@@ -1186,20 +1186,6 @@ void optimize_flags_init(void);
#include "hw/i386/apic.h"
#endif
-static inline bool cpu_has_work(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
- CPU_INTERRUPT_POLL)) &&
- (env->eflags & IF_MASK)) ||
- (cs->interrupt_request & (CPU_INTERRUPT_NMI |
- CPU_INTERRUPT_INIT |
- CPU_INTERRUPT_SIPI |
- CPU_INTERRUPT_MCE));
-}
-
#include "exec/exec-all.h"
static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
@@ -1276,11 +1262,11 @@ void do_smm_enter(X86CPU *cpu);
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
-void disable_kvm_pv_eoi(void);
-
void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
uint32_t feat_add, uint32_t feat_remove);
+void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features);
+
/* Return name of 32-bit register, from a R_* constant */
const char *get_register_name_32(unsigned int reg);
diff --git a/target-i386/excp_helper.c b/target-i386/excp_helper.c
index 5319aef..f337fd2 100644
--- a/target-i386/excp_helper.c
+++ b/target-i386/excp_helper.c
@@ -94,6 +94,8 @@ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno,
int is_int, int error_code,
int next_eip_addend)
{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
if (!is_int) {
cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
error_code);
@@ -102,11 +104,11 @@ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno,
cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0);
}
- env->exception_index = intno;
+ cs->exception_index = intno;
env->error_code = error_code;
env->exception_is_int = is_int;
env->exception_next_eip = env->eip + next_eip_addend;
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
/* shortcuts to generate exceptions */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 55c0457..4f447b8 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -385,22 +385,25 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
a20_state = (a20_state != 0);
if (a20_state != ((env->a20_mask >> 20) & 1)) {
+ CPUState *cs = CPU(cpu);
+
#if defined(DEBUG_MMU)
printf("A20 update: a20=%d\n", a20_state);
#endif
/* if the cpu is currently executing code, we must unlink it and
all the potentially executing TB */
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_EXITTB);
+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
/* when a20 is changed, all the MMU mappings are invalid, so
we must flush everything */
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
env->a20_mask = ~(1 << 20) | (a20_state << 20);
}
}
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
int pe_state;
#if defined(DEBUG_MMU)
@@ -408,7 +411,7 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
#endif
if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
(env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
#ifdef TARGET_X86_64
@@ -444,24 +447,28 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
the PDPT */
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
env->cr[3] = new_cr3;
if (env->cr[0] & CR0_PG_MASK) {
#if defined(DEBUG_MMU)
printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
#endif
- tlb_flush(env, 0);
+ tlb_flush(CPU(cpu), 0);
}
}
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
#if defined(DEBUG_MMU)
printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
#endif
if ((new_cr4 ^ env->cr[4]) &
(CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
CR4_SMEP_MASK | CR4_SMAP_MASK)) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
/* SSE handling */
if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
@@ -485,15 +492,18 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
#if defined(CONFIG_USER_ONLY)
-int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
int is_write, int mmu_idx)
{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
/* user mode only emulation */
is_write &= 1;
env->cr[2] = addr;
env->error_code = (is_write << PG_ERROR_W_BIT);
env->error_code |= PG_ERROR_U_MASK;
- env->exception_index = EXCP0E_PAGE;
+ cs->exception_index = EXCP0E_PAGE;
return 1;
}
@@ -508,14 +518,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
# endif
/* return value:
- -1 = cannot handle fault
- 0 = nothing more to do
- 1 = generate PF fault
-*/
-int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+ * -1 = cannot handle fault
+ * 0 = nothing more to do
+ * 1 = generate PF fault
+ */
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
int is_write1, int mmu_idx)
{
- CPUState *cs = ENV_GET_CPU(env);
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
uint64_t ptep, pte;
target_ulong pde_addr, pte_addr;
int error_code, is_dirty, prot, page_size, is_write, is_user;
@@ -525,7 +536,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
is_user = mmu_idx == MMU_USER_IDX;
#if defined(DEBUG_MMU)
- printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
+ printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
addr, is_write1, is_user, env->eip);
#endif
is_write = is_write1 & 1;
@@ -557,7 +568,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
sext = (int64_t)addr >> 47;
if (sext != 0 && sext != -1) {
env->error_code = 0;
- env->exception_index = EXCP0D_GPF;
+ cs->exception_index = EXCP0D_GPF;
return 1;
}
@@ -866,7 +877,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
vaddr = virt_addr + page_offset;
- tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+ tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
return 0;
do_fault_protect:
error_code = PG_ERROR_P_MASK;
@@ -888,7 +899,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
env->cr[2] = addr;
}
env->error_code = error_code;
- env->exception_index = EXCP0E_PAGE;
+ cs->exception_index = EXCP0E_PAGE;
return 1;
}
@@ -989,12 +1000,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
void hw_breakpoint_insert(CPUX86State *env, int index)
{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
int type = 0, err = 0;
switch (hw_breakpoint_type(env->dr[7], index)) {
case DR7_TYPE_BP_INST:
if (hw_breakpoint_enabled(env->dr[7], index)) {
- err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU,
+ err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
&env->cpu_breakpoint[index]);
}
break;
@@ -1010,7 +1022,7 @@ void hw_breakpoint_insert(CPUX86State *env, int index)
}
if (type != 0) {
- err = cpu_watchpoint_insert(env, env->dr[index],
+ err = cpu_watchpoint_insert(cs, env->dr[index],
hw_breakpoint_len(env->dr[7], index),
type, &env->cpu_watchpoint[index]);
}
@@ -1022,17 +1034,21 @@ void hw_breakpoint_insert(CPUX86State *env, int index)
void hw_breakpoint_remove(CPUX86State *env, int index)
{
- if (!env->cpu_breakpoint[index])
+ CPUState *cs;
+
+ if (!env->cpu_breakpoint[index]) {
return;
+ }
+ cs = CPU(x86_env_get_cpu(env));
switch (hw_breakpoint_type(env->dr[7], index)) {
case DR7_TYPE_BP_INST:
if (hw_breakpoint_enabled(env->dr[7], index)) {
- cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]);
+ cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
}
break;
case DR7_TYPE_DATA_WR:
case DR7_TYPE_DATA_RW:
- cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]);
+ cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
break;
case DR7_TYPE_IO_RW:
/* No support for I/O watchpoints yet */
@@ -1084,19 +1100,20 @@ bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
void breakpoint_handler(CPUX86State *env)
{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
CPUBreakpoint *bp;
- if (env->watchpoint_hit) {
- if (env->watchpoint_hit->flags & BP_CPU) {
- env->watchpoint_hit = NULL;
+ if (cs->watchpoint_hit) {
+ if (cs->watchpoint_hit->flags & BP_CPU) {
+ cs->watchpoint_hit = NULL;
if (check_hw_breakpoints(env, false)) {
raise_exception(env, EXCP01_DB);
} else {
- cpu_resume_from_signal(env, NULL);
+ cpu_resume_from_signal(cs, NULL);
}
}
} else {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry)
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == env->eip) {
if (bp->flags & BP_CPU) {
check_hw_breakpoints(env, true);
@@ -1104,6 +1121,7 @@ void breakpoint_handler(CPUX86State *env)
}
break;
}
+ }
}
}
@@ -1250,13 +1268,14 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
{
X86CPU *cpu = x86_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
if (kvm_enabled()) {
env->tpr_access_type = access;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TPR);
+ cpu_interrupt(cs, CPU_INTERRUPT_TPR);
} else {
- cpu_restore_state(env, env->mem_io_pc);
+ cpu_restore_state(cs, cs->mem_io_pc);
apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
}
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e555040..7a295f6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -2277,13 +2277,13 @@ static int kvm_handle_debug(X86CPU *cpu,
break;
case 0x1:
ret = EXCP_DEBUG;
- env->watchpoint_hit = &hw_watchpoint;
+ cs->watchpoint_hit = &hw_watchpoint;
hw_watchpoint.vaddr = hw_breakpoint[n].addr;
hw_watchpoint.flags = BP_MEM_WRITE;
break;
case 0x3:
ret = EXCP_DEBUG;
- env->watchpoint_hit = &hw_watchpoint;
+ cs->watchpoint_hit = &hw_watchpoint;
hw_watchpoint.vaddr = hw_breakpoint[n].addr;
hw_watchpoint.flags = BP_MEM_ACCESS;
break;
@@ -2291,11 +2291,11 @@ static int kvm_handle_debug(X86CPU *cpu,
}
}
}
- } else if (kvm_find_sw_breakpoint(CPU(cpu), arch_info->pc)) {
+ } else if (kvm_find_sw_breakpoint(cs, arch_info->pc)) {
ret = EXCP_DEBUG;
}
if (ret == 0) {
- cpu_synchronize_state(CPU(cpu));
+ cpu_synchronize_state(cs);
assert(env->exception_injected == -1);
/* pass to guest */
diff --git a/target-i386/machine.c b/target-i386/machine.c
index d548c05..24bc373 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -290,6 +290,7 @@ static void cpu_pre_save(void *opaque)
static int cpu_post_load(void *opaque, int version_id)
{
X86CPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
CPUX86State *env = &cpu->env;
int i;
@@ -319,12 +320,12 @@ static int cpu_post_load(void *opaque, int version_id)
env->fptags[i] = (env->fptag_vmstate >> i) & 1;
}
- cpu_breakpoint_remove_all(env, BP_CPU);
- cpu_watchpoint_remove_all(env, BP_CPU);
+ cpu_breakpoint_remove_all(cs, BP_CPU);
+ cpu_watchpoint_remove_all(cs, BP_CPU);
for (i = 0; i < DR7_MAX_BP; i++) {
hw_breakpoint_insert(env, i);
}
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
return 0;
}
diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c
index 319a219..b3b811b 100644
--- a/target-i386/mem_helper.c
+++ b/target-i386/mem_helper.c
@@ -129,21 +129,25 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v)
#if !defined(CONFIG_USER_ONLY)
/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
+ * NULL, it means that the function was called in C code (i.e. not
+ * from generated code or from helper.c)
+ */
/* XXX: fix it to restore all registers */
-void tlb_fill(CPUX86State *env, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
int ret;
- ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ ret = x86_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
if (ret) {
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
if (retaddr) {
/* now we have a real cpu fault */
- cpu_restore_state(env, retaddr);
+ cpu_restore_state(cs, retaddr);
}
- raise_exception_err(env, env->exception_index, env->error_code);
+ raise_exception_err(env, cs->exception_index, env->error_code);
}
}
#endif
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 47f6a2f..1e2da1e 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -221,8 +221,10 @@ void helper_lmsw(CPUX86State *env, target_ulong t0)
void helper_invlpg(CPUX86State *env, target_ulong addr)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
- tlb_flush_page(env, addr);
+ tlb_flush_page(CPU(cpu), addr);
}
void helper_rdtsc(CPUX86State *env)
@@ -568,11 +570,11 @@ void helper_rdmsr(CPUX86State *env)
static void do_pause(X86CPU *cpu)
{
- CPUX86State *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
/* Just let another CPU run. */
- env->exception_index = EXCP_INTERRUPT;
- cpu_loop_exit(env);
+ cs->exception_index = EXCP_INTERRUPT;
+ cpu_loop_exit(cs);
}
static void do_hlt(X86CPU *cpu)
@@ -582,8 +584,8 @@ static void do_hlt(X86CPU *cpu)
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
cs->halted = 1;
- env->exception_index = EXCP_HLT;
- cpu_loop_exit(env);
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
}
void helper_hlt(CPUX86State *env, int next_eip_addend)
@@ -638,6 +640,8 @@ void helper_pause(CPUX86State *env, int next_eip_addend)
void helper_debug(CPUX86State *env)
{
- env->exception_index = EXCP_DEBUG;
- cpu_loop_exit(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
+ cs->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(cs);
}
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 959212b..8c3f92c 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -95,6 +95,7 @@ static inline void load_seg_vm(CPUX86State *env, int seg, int selector)
static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr,
uint32_t *esp_ptr, int dpl)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
int type, index, shift;
#if 0
@@ -112,11 +113,11 @@ static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr,
#endif
if (!(env->tr.flags & DESC_P_MASK)) {
- cpu_abort(env, "invalid tss");
+ cpu_abort(CPU(cpu), "invalid tss");
}
type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
if ((type & 7) != 1) {
- cpu_abort(env, "invalid tss type");
+ cpu_abort(CPU(cpu), "invalid tss type");
}
shift = type >> 3;
index = (dpl * 4 + 2) << shift;
@@ -782,6 +783,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
int index;
#if 0
@@ -790,7 +792,7 @@ static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level)
#endif
if (!(env->tr.flags & DESC_P_MASK)) {
- cpu_abort(env, "invalid tss");
+ cpu_abort(CPU(cpu), "invalid tss");
}
index = 8 * level + 4;
if ((index + 7) > env->tr.limit) {
@@ -935,9 +937,11 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
#if defined(CONFIG_USER_ONLY)
void helper_syscall(CPUX86State *env, int next_eip_addend)
{
- env->exception_index = EXCP_SYSCALL;
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
+ cs->exception_index = EXCP_SYSCALL;
env->exception_next_eip = env->eip + next_eip_addend;
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
#else
void helper_syscall(CPUX86State *env, int next_eip_addend)
@@ -1131,7 +1135,7 @@ static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
static void handle_even_inj(CPUX86State *env, int intno, int is_int,
int error_code, int is_hw, int rm)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
uint32_t event_inj = ldl_phys(cs->as, env->vm_vmcb + offsetof(struct vmcb,
control.event_inj));
@@ -1248,7 +1252,7 @@ void x86_cpu_do_interrupt(CPUState *cs)
/* if user mode only, we simulate a fake exception
which will be handled outside the cpu execution
loop */
- do_interrupt_user(env, env->exception_index,
+ do_interrupt_user(env, cs->exception_index,
env->exception_is_int,
env->error_code,
env->exception_next_eip);
@@ -1258,7 +1262,7 @@ void x86_cpu_do_interrupt(CPUState *cs)
/* simulate a real cpu exception. On i386, it can
trigger new exceptions, but we do not handle
double or triple faults yet. */
- do_interrupt_all(cpu, env->exception_index,
+ do_interrupt_all(cpu, cs->exception_index,
env->exception_is_int,
env->error_code,
env->exception_next_eip, 0);
diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c
index 71c64b2..35901c9 100644
--- a/target-i386/smm_helper.c
+++ b/target-i386/smm_helper.c
@@ -181,8 +181,8 @@ void do_smm_enter(X86CPU *cpu)
void helper_rsm(CPUX86State *env)
{
- CPUState *cs = ENV_GET_CPU(env);
X86CPU *cpu = x86_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
target_ulong sm_state;
int i, offset;
uint32_t val;
diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c
index b38d450..aa17ecd 100644
--- a/target-i386/svm_helper.c
+++ b/target-i386/svm_helper.c
@@ -88,7 +88,8 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
static inline void svm_save_seg(CPUX86State *env, hwaddr addr,
const SegmentCache *sc)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
stw_phys(cs->as, addr + offsetof(struct vmcb_seg, selector),
sc->selector);
stq_phys(cs->as, addr + offsetof(struct vmcb_seg, base),
@@ -102,7 +103,7 @@ static inline void svm_save_seg(CPUX86State *env, hwaddr addr,
static inline void svm_load_seg(CPUX86State *env, hwaddr addr,
SegmentCache *sc)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
unsigned int flags;
sc->selector = lduw_phys(cs->as,
@@ -125,7 +126,7 @@ static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr,
void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
uint32_t event_inj;
uint32_t int_ctl;
@@ -293,7 +294,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
break;
case TLB_CONTROL_FLUSH_ALL_ASID:
/* FIXME: this is not 100% correct but should work for now */
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
break;
}
@@ -319,7 +320,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
/* FIXME: need to implement valid_err */
switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
case SVM_EVTINJ_TYPE_INTR:
- env->exception_index = vector;
+ cs->exception_index = vector;
env->error_code = event_inj_err;
env->exception_is_int = 0;
env->exception_next_eip = -1;
@@ -328,31 +329,31 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
do_interrupt_x86_hardirq(env, vector, 1);
break;
case SVM_EVTINJ_TYPE_NMI:
- env->exception_index = EXCP02_NMI;
+ cs->exception_index = EXCP02_NMI;
env->error_code = event_inj_err;
env->exception_is_int = 0;
env->exception_next_eip = env->eip;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
break;
case SVM_EVTINJ_TYPE_EXEPT:
- env->exception_index = vector;
+ cs->exception_index = vector;
env->error_code = event_inj_err;
env->exception_is_int = 0;
env->exception_next_eip = -1;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
break;
case SVM_EVTINJ_TYPE_SOFT:
- env->exception_index = vector;
+ cs->exception_index = vector;
env->error_code = event_inj_err;
env->exception_is_int = 1;
env->exception_next_eip = env->eip;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
break;
}
- qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index,
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", cs->exception_index,
env->error_code);
}
}
@@ -365,7 +366,7 @@ void helper_vmmcall(CPUX86State *env)
void helper_vmload(CPUX86State *env, int aflag)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0);
@@ -405,7 +406,7 @@ void helper_vmload(CPUX86State *env, int aflag)
void helper_vmsave(CPUX86State *env, int aflag)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0);
@@ -468,6 +469,7 @@ void helper_skinit(CPUX86State *env)
void helper_invlpga(CPUX86State *env, int aflag)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0);
@@ -480,13 +482,13 @@ void helper_invlpga(CPUX86State *env, int aflag)
/* XXX: could use the ASID to see if it is needed to do the
flush */
- tlb_flush_page(env, addr);
+ tlb_flush_page(CPU(cpu), addr);
}
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
if (likely(!(env->hflags & HF_SVMI_MASK))) {
return;
@@ -568,7 +570,8 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
uint32_t next_eip_addend)
{
- CPUState *cs = ENV_GET_CPU(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
/* FIXME: this should be read in at vmrun (faster this way?) */
uint64_t addr = ldq_phys(cs->as, env->vm_vmcb +
@@ -766,11 +769,11 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
#GP fault is delivered inside the host. */
/* remove any pending exception */
- env->exception_index = -1;
+ cs->exception_index = -1;
env->error_code = 0;
env->old_exception = -1;
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 707ebd5..02625e3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7965,8 +7965,8 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
gen_tb_start();
for(;;) {
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == pc_ptr &&
!((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
gen_debug(dc, pc_ptr - dc->cs_base);