diff options
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu-qom.h | 15 | ||||
-rw-r--r-- | target-i386/cpu.c | 307 | ||||
-rw-r--r-- | target-i386/cpu.h | 26 | ||||
-rw-r--r-- | target-i386/excp_helper.c | 6 | ||||
-rw-r--r-- | target-i386/helper.c | 77 | ||||
-rw-r--r-- | target-i386/kvm.c | 8 | ||||
-rw-r--r-- | target-i386/machine.c | 7 | ||||
-rw-r--r-- | target-i386/mem_helper.c | 16 | ||||
-rw-r--r-- | target-i386/misc_helper.c | 20 | ||||
-rw-r--r-- | target-i386/seg_helper.c | 20 | ||||
-rw-r--r-- | target-i386/smm_helper.c | 2 | ||||
-rw-r--r-- | target-i386/svm_helper.c | 41 | ||||
-rw-r--r-- | target-i386/translate.c | 4 |
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); |