From ed256144cd6f0ca2ff59fc3fc8dca547506f433b Mon Sep 17 00:00:00 2001 From: Chen Fan Date: Fri, 21 Aug 2015 17:34:45 +0800 Subject: [PATCH 01/12] cpu: Introduce X86CPUTopoInfo structure for argument simplification In order to simplify arguments of function, introduce a new struct named X86CPUTopoInfo. Signed-off-by: Chen Fan Signed-off-by: Zhu Guihua Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 6 +++--- include/hw/i386/topology.h | 33 +++++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index efbd41a1f1..01eefa3e09 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1935,10 +1935,10 @@ static void pc_machine_initfn(Object *obj) static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; + X86CPUTopoInfo topo; x86_topo_ids_from_idx(smp_cores, smp_threads, cpu_index, - &pkg_id, &core_id, &smt_id); - return pkg_id; + &topo); + return topo.pkg_id; } static void pc_machine_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h index 9c6f3a937a..148cc1bbc8 100644 --- a/include/hw/i386/topology.h +++ b/include/hw/i386/topology.h @@ -47,6 +47,12 @@ */ typedef uint32_t apic_id_t; +typedef struct X86CPUTopoInfo { + unsigned pkg_id; + unsigned core_id; + unsigned smt_id; +} X86CPUTopoInfo; + /* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count(unsigned count) @@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads) */ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores, unsigned nr_threads, - unsigned pkg_id, - unsigned core_id, - unsigned smt_id) + const X86CPUTopoInfo *topo) { - return (pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) | - (core_id << apicid_core_offset(nr_cores, nr_threads)) | - smt_id; + return (topo->pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) | + (topo->core_id << apicid_core_offset(nr_cores, nr_threads)) | + topo->smt_id; } /* Calculate thread/core/package IDs for a specific topology, @@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores, static inline void x86_topo_ids_from_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index, - unsigned *pkg_id, - unsigned *core_id, - unsigned *smt_id) + X86CPUTopoInfo *topo) { unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; } /* Make APIC ID for the CPU 'cpu_index' @@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; - x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); - return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id); + X86CPUTopoInfo topo; + x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo); + return apicid_from_topo_ids(nr_cores, nr_threads, &topo); } #endif /* HW_I386_TOPOLOGY_H */ From a32ef3bfc12c8d0588f43f74dcc5280885bbdb30 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 22 Jul 2015 15:59:50 +0200 Subject: [PATCH 02/12] vl: Add another sanity check to smp_parse() function The code in smp_parse already checks the topology information for sockets * cores * threads < cpus and bails out with an error in that case. However, it is still possible to supply a bad configuration the other way round, e.g. with: qemu-system-xxx -smp 4,sockets=1,cores=4,threads=2 QEMU then still starts the guest, with topology configuration that is rather incomprehensible and likely not what the user wanted. So let's add another check to refuse such wrong configurations. Signed-off-by: Thomas Huth Reviewed-by: Eduardo Habkost Acked-by: Cornelia Huck Acked-by: Bastian Koppelmann Signed-off-by: Eduardo Habkost --- vl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 8d1846c06c..f2bd8d20fb 100644 --- a/vl.c +++ b/vl.c @@ -1223,7 +1223,13 @@ static void smp_parse(QemuOpts *opts) exit(1); } - max_cpus = qemu_opt_get_number(opts, "maxcpus", 0); + max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus); + if (sockets * cores * threads > max_cpus) { + fprintf(stderr, "cpu topology: error: " + "sockets (%u) * cores (%u) * threads (%u) > maxcpus (%u)\n", + sockets, cores, threads, max_cpus); + exit(1); + } smp_cpus = cpus; smp_cores = cores > 0 ? cores : 1; From 5114e8422201190c3e2e1a4d77e38ad70cf001d2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 11 Sep 2015 12:40:27 -0300 Subject: [PATCH 03/12] target-i386: Convert kvm_default_*features to property/value pairs Convert the kvm_default_features and kvm_default_unset_features arrays into a simple list of property/value pairs that will be applied to X86CPU objects when using KVM. Acked-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- hw/i386/pc_piix.c | 8 ++--- hw/i386/pc_q35.c | 4 +-- target-i386/cpu.c | 87 +++++++++++++++++++++++++++-------------------- target-i386/cpu.h | 11 ++++-- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 4514cd1462..f6c7a4ab83 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -332,7 +332,7 @@ static void pc_compat_2_1(MachineState *machine) pc_compat_2_2(machine); smbios_uuid_encoded = false; - x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM); + x86_cpu_change_kvm_default("svm", NULL); pcms->enforce_aligned_dimm = false; } @@ -368,7 +368,7 @@ static void pc_compat_1_7(MachineState *machine) gigabyte_align = false; option_rom_has_mr = true; legacy_acpi_table_size = 6414; - x86_cpu_compat_kvm_no_autoenable(FEAT_1_ECX, CPUID_EXT_X2APIC); + x86_cpu_change_kvm_default("x2apic", NULL); } static void pc_compat_1_6(MachineState *machine) @@ -398,7 +398,7 @@ static void pc_compat_1_3(MachineState *machine) static void pc_compat_1_2(MachineState *machine) { pc_compat_1_3(machine); - x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI); + x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); } /* PC compat function for pc-0.10 to pc-0.13 */ @@ -421,7 +421,7 @@ static void pc_init_isa(MachineState *machine) if (!machine->cpu_model) { machine->cpu_model = "486"; } - x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI); + x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); enable_compat_apic_id_mode(); pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 1f100b1a69..4356728d18 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -316,7 +316,7 @@ static void pc_compat_2_1(MachineState *machine) pc_compat_2_2(machine); pcms->enforce_aligned_dimm = false; smbios_uuid_encoded = false; - x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM); + x86_cpu_change_kvm_default("svm", NULL); } static void pc_compat_2_0(MachineState *machine) @@ -333,7 +333,7 @@ static void pc_compat_1_7(MachineState *machine) smbios_defaults = false; gigabyte_align = false; option_rom_has_mr = true; - x86_cpu_compat_kvm_no_autoenable(FEAT_1_ECX, CPUID_EXT_X2APIC); + x86_cpu_change_kvm_default("x2apic", NULL); } static void pc_compat_1_6(MachineState *machine) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bd411b9d8d..6cccc772f6 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -478,38 +478,6 @@ const char *get_register_name_32(unsigned int reg) return x86_reg_info_32[reg].name; } -/* 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), - [FEAT_1_ECX] = CPUID_EXT_X2APIC, -}; - -/* Features that are not added by default to any CPU model when KVM is enabled. - */ -static uint32_t kvm_default_unset_features[FEATURE_WORDS] = { - [FEAT_1_EDX] = CPUID_ACPI, - [FEAT_1_ECX] = CPUID_EXT_MONITOR, - [FEAT_8000_0001_ECX] = CPUID_EXT3_SVM, -}; - -void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features) -{ - kvm_default_features[w] &= ~features; -} - -void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features) -{ - kvm_default_unset_features[w] &= ~features; -} - /* * Returns the set of feature flags that are supported and migratable by * QEMU, for a given FeatureWord. @@ -1392,6 +1360,43 @@ static X86CPUDefinition builtin_x86_defs[] = { }, }; +typedef struct PropValue { + const char *prop, *value; +} PropValue; + +/* KVM-specific features that are automatically added/removed + * from all CPU models when KVM is enabled. + */ +static PropValue kvm_default_props[] = { + { "kvmclock", "on" }, + { "kvm-nopiodelay", "on" }, + { "kvm-asyncpf", "on" }, + { "kvm-steal-time", "on" }, + { "kvm-pv-eoi", "on" }, + { "kvmclock-stable-bit", "on" }, + { "x2apic", "on" }, + { "acpi", "off" }, + { "monitor", "off" }, + { "svm", "off" }, + { NULL, NULL }, +}; + +void x86_cpu_change_kvm_default(const char *prop, const char *value) +{ + PropValue *pv; + for (pv = kvm_default_props; pv->prop; pv++) { + if (!strcmp(pv->prop, prop)) { + pv->value = value; + break; + } + } + + /* It is valid to call this function only for properties that + * are already present in the kvm_default_props table. + */ + assert(pv->prop); +} + static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, bool migratable_only); @@ -2061,6 +2066,18 @@ static int x86_cpu_filter_features(X86CPU *cpu) return rv; } +static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) +{ + PropValue *pv; + for (pv = props; pv->prop; pv++) { + if (!pv->value) { + continue; + } + object_property_parse(OBJECT(cpu), pv->value, pv->prop, + &error_abort); + } +} + /* Load data from X86CPUDefinition */ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) @@ -2084,11 +2101,7 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) /* Special cases not set in the X86CPUDefinition structs: */ if (kvm_enabled()) { - FeatureWord w; - for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] |= kvm_default_features[w]; - env->features[w] &= ~kvm_default_unset_features[w]; - } + x86_cpu_apply_props(cpu, kvm_default_props); } env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 034fab6f39..dc7654d370 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1341,8 +1341,15 @@ void cpu_smm_update(X86CPU *cpu); void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); -void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features); -void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features); +/* Change the value of a KVM-specific default + * + * If value is NULL, no default will be set and the original + * value from the CPU model table will be kept. + * + * It is valid to call this funciton only for properties that + * are already present in the kvm_default_props table. + */ +void x86_cpu_change_kvm_default(const char *prop, const char *value); /* Return name of 32-bit register, from a R_* constant */ From ba4b5c65a98ea91dc3b13e42dd9404808c999dda Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 15 Sep 2015 11:45:06 -0700 Subject: [PATCH 04/12] target-i386: Move breakpoint related functions to new file Reviewed-by: Eduardo Habkost Signed-off-by: Richard Henderson Signed-off-by: Eduardo Habkost --- target-i386/Makefile.objs | 2 +- target-i386/bpt_helper.c | 182 ++++++++++++++++++++++++++++++++++++++ target-i386/helper.c | 128 --------------------------- target-i386/misc_helper.c | 34 ------- 4 files changed, 183 insertions(+), 163 deletions(-) create mode 100644 target-i386/bpt_helper.c diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index 3da413e8bd..437d9975b9 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o bpt_helper.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o diff --git a/target-i386/bpt_helper.c b/target-i386/bpt_helper.c new file mode 100644 index 0000000000..6f6537d58c --- /dev/null +++ b/target-i386/bpt_helper.c @@ -0,0 +1,182 @@ +/* + * i386 breakpoint helpers + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "exec/helper-proto.h" + + +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(cs, env->dr[index], BP_CPU, + &env->cpu_breakpoint[index]); + } + break; + case DR7_TYPE_DATA_WR: + type = BP_CPU | BP_MEM_WRITE; + break; + case DR7_TYPE_IO_RW: + /* No support for I/O watchpoints yet */ + break; + case DR7_TYPE_DATA_RW: + type = BP_CPU | BP_MEM_ACCESS; + break; + } + + if (type != 0) { + err = cpu_watchpoint_insert(cs, env->dr[index], + hw_breakpoint_len(env->dr[7], index), + type, &env->cpu_watchpoint[index]); + } + + if (err) { + env->cpu_breakpoint[index] = NULL; + } +} + +void hw_breakpoint_remove(CPUX86State *env, int 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(cs, env->cpu_breakpoint[index]); + } + break; + case DR7_TYPE_DATA_WR: + case DR7_TYPE_DATA_RW: + cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]); + break; + case DR7_TYPE_IO_RW: + /* No support for I/O watchpoints yet */ + break; + } +} + +bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) +{ + target_ulong dr6; + int reg; + bool hit_enabled = false; + + dr6 = env->dr[6] & ~0xf; + for (reg = 0; reg < DR7_MAX_BP; reg++) { + bool bp_match = false; + bool wp_match = false; + + switch (hw_breakpoint_type(env->dr[7], reg)) { + case DR7_TYPE_BP_INST: + if (env->dr[reg] == env->eip) { + bp_match = true; + } + break; + case DR7_TYPE_DATA_WR: + case DR7_TYPE_DATA_RW: + if (env->cpu_watchpoint[reg] && + env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) { + wp_match = true; + } + break; + case DR7_TYPE_IO_RW: + break; + } + if (bp_match || wp_match) { + dr6 |= 1 << reg; + if (hw_breakpoint_enabled(env->dr[7], reg)) { + hit_enabled = true; + } + } + } + + if (hit_enabled || force_dr6_update) { + env->dr[6] = dr6; + } + + return hit_enabled; +} + +void breakpoint_handler(CPUState *cs) +{ + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + CPUBreakpoint *bp; + + 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(cs, NULL); + } + } + } else { + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { + if (bp->pc == env->eip) { + if (bp->flags & BP_CPU) { + check_hw_breakpoints(env, true); + raise_exception(env, EXCP01_DB); + } + break; + } + } + } +} + +void helper_single_step(CPUX86State *env) +{ +#ifndef CONFIG_USER_ONLY + check_hw_breakpoints(env, true); + env->dr[6] |= DR6_BS; +#endif + raise_exception(env, EXCP01_DB); +} + +void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) +{ +#ifndef CONFIG_USER_ONLY + int i; + + if (reg < 4) { + hw_breakpoint_remove(env, reg); + env->dr[reg] = t0; + hw_breakpoint_insert(env, reg); + } else if (reg == 7) { + for (i = 0; i < DR7_MAX_BP; i++) { + hw_breakpoint_remove(env, i); + } + env->dr[7] = t0; + for (i = 0; i < DR7_MAX_BP; i++) { + hw_breakpoint_insert(env, i); + } + } else { + env->dr[reg] = t0; + } +#endif +} diff --git a/target-i386/helper.c b/target-i386/helper.c index 9364d96f96..d18be95c3f 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1096,134 +1096,6 @@ out: return pte | page_offset; } -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(cs, env->dr[index], BP_CPU, - &env->cpu_breakpoint[index]); - } - break; - case DR7_TYPE_DATA_WR: - type = BP_CPU | BP_MEM_WRITE; - break; - case DR7_TYPE_IO_RW: - /* No support for I/O watchpoints yet */ - break; - case DR7_TYPE_DATA_RW: - type = BP_CPU | BP_MEM_ACCESS; - break; - } - - if (type != 0) { - err = cpu_watchpoint_insert(cs, env->dr[index], - hw_breakpoint_len(env->dr[7], index), - type, &env->cpu_watchpoint[index]); - } - - if (err) { - env->cpu_breakpoint[index] = NULL; - } -} - -void hw_breakpoint_remove(CPUX86State *env, int 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(cs, env->cpu_breakpoint[index]); - } - break; - case DR7_TYPE_DATA_WR: - case DR7_TYPE_DATA_RW: - cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]); - break; - case DR7_TYPE_IO_RW: - /* No support for I/O watchpoints yet */ - break; - } -} - -bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) -{ - target_ulong dr6; - int reg; - bool hit_enabled = false; - - dr6 = env->dr[6] & ~0xf; - for (reg = 0; reg < DR7_MAX_BP; reg++) { - bool bp_match = false; - bool wp_match = false; - - switch (hw_breakpoint_type(env->dr[7], reg)) { - case DR7_TYPE_BP_INST: - if (env->dr[reg] == env->eip) { - bp_match = true; - } - break; - case DR7_TYPE_DATA_WR: - case DR7_TYPE_DATA_RW: - if (env->cpu_watchpoint[reg] && - env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) { - wp_match = true; - } - break; - case DR7_TYPE_IO_RW: - break; - } - if (bp_match || wp_match) { - dr6 |= 1 << reg; - if (hw_breakpoint_enabled(env->dr[7], reg)) { - hit_enabled = true; - } - } - } - - if (hit_enabled || force_dr6_update) { - env->dr[6] = dr6; - } - - return hit_enabled; -} - -void breakpoint_handler(CPUState *cs) -{ - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - CPUBreakpoint *bp; - - 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(cs, NULL); - } - } - } else { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == env->eip) { - if (bp->flags & BP_CPU) { - check_hw_breakpoints(env, true); - raise_exception(env, EXCP01_DB); - } - break; - } - } - } -} - typedef struct MCEInjectionParams { Monitor *mon; X86CPU *cpu; diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index 6bfc7dd24e..13bd4f5eec 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -95,15 +95,6 @@ void helper_into(CPUX86State *env, int next_eip_addend) } } -void helper_single_step(CPUX86State *env) -{ -#ifndef CONFIG_USER_ONLY - check_hw_breakpoints(env, true); - env->dr[6] |= DR6_BS; -#endif - raise_exception(env, EXCP01_DB); -} - void helper_cpuid(CPUX86State *env) { uint32_t eax, ebx, ecx, edx; @@ -127,10 +118,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg) void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) { } - -void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) -{ -} #else target_ulong helper_read_crN(CPUX86State *env, int reg) { @@ -176,27 +163,6 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) break; } } - -void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) -{ - int i; - - if (reg < 4) { - hw_breakpoint_remove(env, reg); - env->dr[reg] = t0; - hw_breakpoint_insert(env, reg); - } else if (reg == 7) { - for (i = 0; i < DR7_MAX_BP; i++) { - hw_breakpoint_remove(env, i); - } - env->dr[7] = t0; - for (i = 0; i < DR7_MAX_BP; i++) { - hw_breakpoint_insert(env, i); - } - } else { - env->dr[reg] = t0; - } -} #endif void helper_lmsw(CPUX86State *env, target_ulong t0) From dd941cdcfec536aad6a310a153778142ed9f3e92 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 15 Sep 2015 11:45:07 -0700 Subject: [PATCH 05/12] target-i386: Make check_hw_breakpoints static The function is now only used from within a single file. Reviewed-by: Eduardo Habkost Signed-off-by: Richard Henderson Signed-off-by: Eduardo Habkost --- target-i386/bpt_helper.c | 2 +- target-i386/cpu.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/target-i386/bpt_helper.c b/target-i386/bpt_helper.c index 6f6537d58c..c071c24782 100644 --- a/target-i386/bpt_helper.c +++ b/target-i386/bpt_helper.c @@ -79,7 +79,7 @@ void hw_breakpoint_remove(CPUX86State *env, int index) } } -bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) +static bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) { target_ulong dr6; int reg; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index dc7654d370..92426dc1f9 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1154,7 +1154,6 @@ static inline int hw_breakpoint_len(unsigned long dr7, int index) void hw_breakpoint_insert(CPUX86State *env, int index); void hw_breakpoint_remove(CPUX86State *env, int index); -bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update); void breakpoint_handler(CPUState *cs); /* will be suppressed */ From c9b8f6b6210847b4381c5b2ee172b1c7eb9985d6 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Wed, 23 Sep 2015 11:57:33 +0530 Subject: [PATCH 06/12] target-i386: get/put MSR_TSC_AUX across reset and migration There's one report of migration breaking due to missing MSR_TSC_AUX save/restore. Fix this by adding a new subsection that saves the state of this MSR. https://bugzilla.redhat.com/show_bug.cgi?id=1261797 Reported-by: Xiaoqing Wei Signed-off-by: Amit Shah CC: Paolo Bonzini CC: Juan Quintela CC: "Dr. David Alan Gilbert" CC: Marcelo Tosatti CC: Richard Henderson CC: Eduardo Habkost Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7b0ba179cc..80d1a7e01e 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -67,6 +67,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static bool has_msr_star; static bool has_msr_hsave_pa; +static bool has_msr_tsc_aux; static bool has_msr_tsc_adjust; static bool has_msr_tsc_deadline; static bool has_msr_feature_control; @@ -825,6 +826,10 @@ static int kvm_get_supported_msrs(KVMState *s) has_msr_hsave_pa = true; continue; } + if (kvm_msr_list->indices[i] == MSR_TSC_AUX) { + has_msr_tsc_aux = true; + continue; + } if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) { has_msr_tsc_adjust = true; continue; @@ -1299,6 +1304,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) if (has_msr_hsave_pa) { kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave); } + if (has_msr_tsc_aux) { + kvm_msr_entry_set(&msrs[n++], MSR_TSC_AUX, env->tsc_aux); + } if (has_msr_tsc_adjust) { kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust); } @@ -1671,6 +1679,9 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_hsave_pa) { msrs[n++].index = MSR_VM_HSAVE_PA; } + if (has_msr_tsc_aux) { + msrs[n++].index = MSR_TSC_AUX; + } if (has_msr_tsc_adjust) { msrs[n++].index = MSR_TSC_ADJUST; } @@ -1820,6 +1831,9 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_IA32_TSC: env->tsc = msrs[i].data; break; + case MSR_TSC_AUX: + env->tsc_aux = msrs[i].data; + break; case MSR_TSC_ADJUST: env->tsc_adjust = msrs[i].data; break; From becb66673ec30cb604926d247ab9449a60ad8b11 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 28 Sep 2015 14:00:18 +0200 Subject: [PATCH 07/12] target-i386: add ABM to Haswell* and Broadwell* CPU models ABM is only implemented as a single instruction set by AMD; all AMD processors support both instructions or neither. Intel considers POPCNT as part of SSE4.2, and LZCNT as part of BMI1, but Intel also uses AMD's ABM flag to indicate support for both POPCNT and LZCNT. It has to be added to Haswell and Broadwell because Haswell, by adding LZCNT, has completed the ABM. Tested with "qemu-kvm -cpu Haswell-noTSX,enforce" (and also with older machine types) on an Haswell-EP machine. Signed-off-by: Paolo Bonzini Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost --- include/hw/i386/pc.h | 22 +++++++++++++++++++++- target-i386/cpu.c | 8 ++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index c13e91ddde..8662a298f4 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -298,7 +298,27 @@ int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_4 \ - HW_COMPAT_2_4 + HW_COMPAT_2_4 \ + {\ + .driver = "Haswell-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Haswell-noTSX-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + },\ + {\ + .driver = "Broadwell-noTSX-" TYPE_X86_CPU,\ + .property = "abm",\ + .value = "off",\ + }, #define PC_COMPAT_2_3 \ PC_COMPAT_2_4 \ diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6cccc772f6..21bad5927d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1081,7 +1081,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, + CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | @@ -1116,7 +1116,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, + CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | @@ -1153,7 +1153,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, + CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | @@ -1191,7 +1191,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, + CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | From 2188cc52cb363433751f72b991d8fb05fc60e39d Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Wed, 30 Sep 2015 15:33:29 -0700 Subject: [PATCH 08/12] Correctly re-init EFER state during INIT IPI When doing a re-initialization of a CPU core, the default state is to _not_ have 64-bit long mode enabled. This means the LME (long mode enable) and LMA (long mode active) bits in the EFER model-specific register should be cleared. However, the EFER state is part of the CPU environment which is preserved by do_cpu_init(), so if EFER.LME and EFER.LMA were set at the time an INIT IPI was received, they will remain set after the init completes. This is contrary to what the Intel architecture manual describes and what happens on real hardware, and it leaves the CPU in a weird state that the guest can't clear. To fix this, the 'efer' member of the CPUX86State structure has been moved to an area outside the region preserved by do_cpu_init(), so that it can be properly re-initialized by x86_cpu_reset(). Signed-off-by: Bill Paul CC: Paolo Bonzini CC: Richard Henderson CC: Eduardo Habkost Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 92426dc1f9..8926780e85 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -833,6 +833,7 @@ typedef struct CPUX86State { BNDReg bnd_regs[4]; BNDCSReg bndcs_regs; uint64_t msr_bndcfgs; + uint64_t efer; /* Beginning of state preserved by INIT (dummy marker). */ struct {} start_init_save; @@ -865,7 +866,6 @@ typedef struct CPUX86State { uint32_t sysenter_cs; target_ulong sysenter_esp; target_ulong sysenter_eip; - uint64_t efer; uint64_t star; uint64_t vm_hsave; From 8d42d2d32b508484106f1c600f5cdd5496bc867e Mon Sep 17 00:00:00 2001 From: Chen Fan Date: Wed, 16 Sep 2015 17:19:11 +0800 Subject: [PATCH 09/12] apic: move APIC's MMIO region mapping into APIC When ICC bus/bridge is removed, APIC MMIO will be left unmapped since it was mapped into system's address space indirectly by ICC bridge. Fix it by moving mapping into APIC code, so it would be possible to remove ICC bus/bridge code later. Signed-off-by: Chen Fan Signed-off-by: Zhu Guihua Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 7 ------- hw/intc/apic_common.c | 6 ------ target-i386/cpu.c | 15 +++++++++++++++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 01eefa3e09..6a20e16e3f 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1158,13 +1158,6 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) object_unref(OBJECT(cpu)); } - /* map APIC MMIO area if CPU has APIC */ - if (cpu && cpu->apic_state) { - /* XXX: what if the base changes? */ - sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0, - APIC_DEFAULT_ADDRESS, 0x1000); - } - /* tell smbios about cpuid version and features */ smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); } diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 0032b97c5f..c0b32eb8eb 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -296,7 +296,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp) APICCommonClass *info; static DeviceState *vapic; static int apic_no; - static bool mmio_registered; if (apic_no >= MAX_APICS) { error_setg(errp, "%s initialization failed.", @@ -307,11 +306,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp) info = APIC_COMMON_GET_CLASS(s); info->realize(dev, errp); - if (!mmio_registered) { - ICCBus *b = ICC_BUS(qdev_get_parent_bus(dev)); - memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory); - mmio_registered = true; - } /* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 21bad5927d..dba77d3eac 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2758,15 +2758,30 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) /* TODO: convert to link<> */ apic = APIC_COMMON(cpu->apic_state); apic->cpu = cpu; + apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE; } static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) { + APICCommonState *apic; + static bool apic_mmio_map_once; + if (cpu->apic_state == NULL) { return; } object_property_set_bool(OBJECT(cpu->apic_state), true, "realized", errp); + + /* Map APIC MMIO area */ + apic = APIC_COMMON(cpu->apic_state); + if (!apic_mmio_map_once) { + memory_region_add_subregion_overlap(get_system_memory(), + apic->apicbase & + MSR_IA32_APICBASE_BASE, + &apic->io_memory, + 0x1000); + apic_mmio_map_once = true; + } } static void x86_cpu_machine_done(Notifier *n, void *unused) From ae50c55a09b8a90205972518d8129447000ae188 Mon Sep 17 00:00:00 2001 From: Zhu Guihua Date: Wed, 16 Sep 2015 17:19:13 +0800 Subject: [PATCH 10/12] x86: use new method to correct reset sequence During reset some devices (such as hpet, rtc) might send IRQ to APIC which changes APIC's state from default one it's supposed to have at machine startup time. Fix this by resetting APIC after devices have been reset to cancel any changes that qemu_devices_reset() might have done to its state. Signed-off-by: Zhu Guihua Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 6a20e16e3f..02e0b427ac 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1926,6 +1926,25 @@ static void pc_machine_initfn(Object *obj) NULL, &error_abort); } +static void pc_machine_reset(void) +{ + CPUState *cs; + X86CPU *cpu; + + qemu_devices_reset(); + + /* Reset APIC after devices have been reset to cancel + * any changes that qemu_devices_reset() might have done. + */ + CPU_FOREACH(cs) { + cpu = X86_CPU(cs); + + if (cpu->apic_state) { + device_reset(cpu->apic_state); + } + } +} + static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) { X86CPUTopoInfo topo; @@ -1947,6 +1966,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->default_boot_order = "cad"; mc->hot_add_cpu = pc_hot_add_cpu; mc->max_cpus = 255; + mc->reset = pc_machine_reset; hc->plug = pc_machine_device_plug_cb; hc->unplug_request = pc_machine_device_unplug_request_cb; hc->unplug = pc_machine_device_unplug_cb; From 46232aaacb66733d3e16dcbd0d26c32ec388801d Mon Sep 17 00:00:00 2001 From: Chen Fan Date: Wed, 16 Sep 2015 17:19:14 +0800 Subject: [PATCH 11/12] cpu/apic: drop icc bus/bridge After CPU hotplug has been converted to BUS-less hot-plug infrastructure, the only function ICC bus performs is to propagate reset to LAPICs. However LAPIC could be reset by registering its reset handler after all device are initialized. Do so and drop ~30LOC of not needed anymore ICCBus related code. Signed-off-by: Chen Fan Signed-off-by: Zhu Guihua Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 19 ++++--------------- hw/i386/pc_piix.c | 9 +-------- hw/i386/pc_q35.c | 9 +-------- hw/intc/apic_common.c | 5 ++--- include/hw/i386/apic_internal.h | 7 ++++--- include/hw/i386/pc.h | 2 +- target-i386/cpu.c | 9 +-------- 7 files changed, 14 insertions(+), 46 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 02e0b427ac..9275297adc 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -59,7 +59,6 @@ #include "qemu/error-report.h" #include "hw/acpi/acpi.h" #include "hw/acpi/cpu_hotplug.h" -#include "hw/cpu/icc_bus.h" #include "hw/boards.h" #include "hw/pci/pci_host.h" #include "acpi-build.h" @@ -1052,23 +1051,16 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, - DeviceState *icc_bridge, Error **errp) + Error **errp) { X86CPU *cpu = NULL; Error *local_err = NULL; - if (icc_bridge == NULL) { - error_setg(&local_err, "Invalid icc-bridge value"); - goto out; - } - cpu = cpu_x86_create(cpu_model, &local_err); if (local_err != NULL) { goto out; } - qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc")); - object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); @@ -1085,7 +1077,6 @@ static const char *current_cpu_model; void pc_hot_add_cpu(const int64_t id, Error **errp) { - DeviceState *icc_bridge; X86CPU *cpu; int64_t apic_id = x86_cpu_apic_id_from_index(id); Error *local_err = NULL; @@ -1114,9 +1105,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) return; } - icc_bridge = DEVICE(object_resolve_path_type("icc-bridge", - TYPE_ICC_BRIDGE, NULL)); - cpu = pc_new_cpu(current_cpu_model, apic_id, icc_bridge, &local_err); + cpu = pc_new_cpu(current_cpu_model, apic_id, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1124,7 +1113,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) object_unref(OBJECT(cpu)); } -void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) +void pc_cpus_init(const char *cpu_model) { int i; X86CPU *cpu = NULL; @@ -1150,7 +1139,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) for (i = 0; i < smp_cpus; i++) { cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), - icc_bridge, &error); + &error); if (error) { error_report_err(error); exit(1); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index f6c7a4ab83..ae7bbebd0f 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -39,7 +39,6 @@ #include "hw/kvm/clock.h" #include "sysemu/sysemu.h" #include "hw/sysbus.h" -#include "hw/cpu/icc_bus.h" #include "sysemu/arch_init.h" #include "sysemu/block-backend.h" #include "hw/i2c/smbus.h" @@ -98,7 +97,6 @@ static void pc_init1(MachineState *machine, MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; - DeviceState *icc_bridge; PcGuestInfo *guest_info; ram_addr_t lowmem; @@ -141,11 +139,7 @@ static void pc_init1(MachineState *machine, exit(1); } - icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); - object_property_add_child(qdev_get_machine(), "icc-bridge", - OBJECT(icc_bridge), NULL); - - pc_cpus_init(machine->cpu_model, icc_bridge); + pc_cpus_init(machine->cpu_model); if (kvm_enabled() && kvmclock_enabled) { kvmclock_create(); @@ -226,7 +220,6 @@ static void pc_init1(MachineState *machine, if (pci_enabled) { ioapic_init_gsi(gsi_state, "i440fx"); } - qdev_init_nofail(icc_bridge); pc_register_ferr_irq(gsi[13]); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 4356728d18..19e66702e0 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -43,7 +43,6 @@ #include "hw/ide/pci.h" #include "hw/ide/ahci.h" #include "hw/usb.h" -#include "hw/cpu/icc_bus.h" #include "qemu/error-report.h" #include "migration/migration.h" @@ -83,7 +82,6 @@ static void pc_q35_init(MachineState *machine) int i; ICH9LPCState *ich9_lpc; PCIDevice *ahci; - DeviceState *icc_bridge; PcGuestInfo *guest_info; ram_addr_t lowmem; DriveInfo *hd[MAX_SATA_PORTS]; @@ -130,11 +128,7 @@ static void pc_q35_init(MachineState *machine) exit(1); } - icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); - object_property_add_child(qdev_get_machine(), "icc-bridge", - OBJECT(icc_bridge), NULL); - - pc_cpus_init(machine->cpu_model, icc_bridge); + pc_cpus_init(machine->cpu_model); pc_acpi_init("q35-acpi-dsdt.aml"); kvmclock_create(); @@ -236,7 +230,6 @@ static void pc_q35_init(MachineState *machine) if (pci_enabled) { ioapic_init_gsi(gsi_state, "q35"); } - qdev_init_nofail(icc_bridge); pc_register_ferr_irq(gsi[13]); diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index c0b32eb8eb..ad959c4e77 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -419,13 +419,12 @@ static Property apic_properties_common[] = { static void apic_common_class_init(ObjectClass *klass, void *data) { - ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); dc->vmsd = &vmstate_apic_common; dc->reset = apic_reset_common; dc->props = apic_properties_common; - idc->realize = apic_common_realize; + dc->realize = apic_common_realize; /* * Reason: APIC and CPU need to be wired up by * x86_cpu_apic_create() @@ -435,7 +434,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data) static const TypeInfo apic_common_type = { .name = TYPE_APIC_COMMON, - .parent = TYPE_ICC_DEVICE, + .parent = TYPE_DEVICE, .instance_size = sizeof(APICCommonState), .class_size = sizeof(APICCommonClass), .class_init = apic_common_class_init, diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 7813396e49..74fe935e8e 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -22,7 +22,6 @@ #include "cpu.h" #include "exec/memory.h" -#include "hw/cpu/icc_bus.h" #include "qemu/timer.h" /* APIC Local Vector Table */ @@ -135,7 +134,7 @@ typedef struct APICCommonState APICCommonState; typedef struct APICCommonClass { - ICCDeviceClass parent_class; + DeviceClass parent_class; DeviceRealize realize; void (*set_base)(APICCommonState *s, uint64_t val); @@ -150,7 +149,9 @@ typedef struct APICCommonClass } APICCommonClass; struct APICCommonState { - ICCDevice busdev; + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ MemoryRegion io_memory; X86CPU *cpu; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 8662a298f4..0503485cd0 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -168,7 +168,7 @@ bool pc_machine_is_smm_enabled(PCMachineState *pcms); void pc_register_ferr_irq(qemu_irq irq); void pc_acpi_smi_interrupt(void *opaque, int irq, int level); -void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); +void pc_cpus_init(const char *cpu_model); void pc_hot_add_cpu(const int64_t id, Error **errp); void pc_acpi_init(const char *default_dsdt); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index dba77d3eac..c793812cc2 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -43,7 +43,6 @@ #include "sysemu/sysemu.h" #include "hw/qdev-properties.h" -#include "hw/cpu/icc_bus.h" #ifndef CONFIG_USER_ONLY #include "exec/address-spaces.h" #include "hw/xen/xen.h" @@ -2736,7 +2735,6 @@ static void mce_init(X86CPU *cpu) #ifndef CONFIG_USER_ONLY static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) { - DeviceState *dev = DEVICE(cpu); APICCommonState *apic; const char *apic_type = "apic"; @@ -2746,11 +2744,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) apic_type = "xen-apic"; } - cpu->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type); - if (cpu->apic_state == NULL) { - error_setg(errp, "APIC device '%s' could not be created", apic_type); - return; - } + cpu->apic_state = DEVICE(object_new(apic_type)); object_property_add_child(OBJECT(cpu), "apic", OBJECT(cpu->apic_state), NULL); @@ -3161,7 +3155,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) xcc->parent_realize = dc->realize; dc->realize = x86_cpu_realizefn; - dc->bus_type = TYPE_ICC_BUS; dc->props = x86_cpu_properties; xcc->parent_reset = cc->reset; From dfeb8679db358e1f8e0ee4dd84f903d71f000378 Mon Sep 17 00:00:00 2001 From: Zhu Guihua Date: Wed, 16 Sep 2015 17:19:15 +0800 Subject: [PATCH 12/12] icc_bus: drop the unused files ICC bus impl has been droped, so all icc related files are not useful any more; delete them. Signed-off-by: Zhu Guihua Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- default-configs/i386-softmmu.mak | 1 - default-configs/x86_64-softmmu.mak | 1 - hw/cpu/Makefile.objs | 1 - hw/cpu/icc_bus.c | 118 ----------------------------- include/hw/cpu/icc_bus.h | 82 -------------------- 5 files changed, 203 deletions(-) delete mode 100644 hw/cpu/icc_bus.c delete mode 100644 include/hw/cpu/icc_bus.h diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 9393cf0ac9..43c96d1c91 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -44,7 +44,6 @@ CONFIG_LPC_ICH9=y CONFIG_PCI_Q35=y CONFIG_APIC=y CONFIG_IOAPIC=y -CONFIG_ICC_BUS=y CONFIG_PVPANIC=y CONFIG_MEM_HOTPLUG=y CONFIG_XIO3130=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 28e2099187..dfb80954d4 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -44,7 +44,6 @@ CONFIG_LPC_ICH9=y CONFIG_PCI_Q35=y CONFIG_APIC=y CONFIG_IOAPIC=y -CONFIG_ICC_BUS=y CONFIG_PVPANIC=y CONFIG_MEM_HOTPLUG=y CONFIG_XIO3130=y diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs index 6381238cc5..0954a1872f 100644 --- a/hw/cpu/Makefile.objs +++ b/hw/cpu/Makefile.objs @@ -2,5 +2,4 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o obj-$(CONFIG_REALVIEW) += realview_mpcore.o obj-$(CONFIG_A9MPCORE) += a9mpcore.o obj-$(CONFIG_A15MPCORE) += a15mpcore.o -obj-$(CONFIG_ICC_BUS) += icc_bus.o diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c deleted file mode 100644 index 6646ea2b34..0000000000 --- a/hw/cpu/icc_bus.c +++ /dev/null @@ -1,118 +0,0 @@ -/* icc_bus.c - * emulate x86 ICC (Interrupt Controller Communications) bus - * - * Copyright (c) 2013 Red Hat, Inc - * - * Authors: - * Igor Mammedov - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see - */ -#include "hw/cpu/icc_bus.h" -#include "hw/sysbus.h" - -/* icc-bridge implementation */ - -static const TypeInfo icc_bus_info = { - .name = TYPE_ICC_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(ICCBus), -}; - - -/* icc-device implementation */ - -static void icc_device_realize(DeviceState *dev, Error **errp) -{ - ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(dev); - - /* convert to QOM */ - if (idc->realize) { - idc->realize(dev, errp); - } - -} - -static void icc_device_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = icc_device_realize; - dc->bus_type = TYPE_ICC_BUS; -} - -static const TypeInfo icc_device_info = { - .name = TYPE_ICC_DEVICE, - .parent = TYPE_DEVICE, - .abstract = true, - .instance_size = sizeof(ICCDevice), - .class_size = sizeof(ICCDeviceClass), - .class_init = icc_device_class_init, -}; - - -/* icc-bridge implementation */ - -typedef struct ICCBridgeState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - ICCBus icc_bus; - MemoryRegion apic_container; -} ICCBridgeState; - -#define ICC_BRIDGE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE) - -static void icc_bridge_init(Object *obj) -{ - ICCBridgeState *s = ICC_BRIDGE(obj); - SysBusDevice *sb = SYS_BUS_DEVICE(obj); - - qbus_create_inplace(&s->icc_bus, sizeof(s->icc_bus), TYPE_ICC_BUS, - DEVICE(s), "icc"); - - /* Do not change order of registering regions, - * APIC must be first registered region, board maps it by 0 index - */ - memory_region_init(&s->apic_container, obj, "icc-apic-container", - APIC_SPACE_SIZE); - sysbus_init_mmio(sb, &s->apic_container); - s->icc_bus.apic_address_space = &s->apic_container; -} - -static void icc_bridge_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo icc_bridge_info = { - .name = TYPE_ICC_BRIDGE, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_init = icc_bridge_init, - .instance_size = sizeof(ICCBridgeState), - .class_init = icc_bridge_class_init, -}; - - -static void icc_bus_register_types(void) -{ - type_register_static(&icc_bus_info); - type_register_static(&icc_device_info); - type_register_static(&icc_bridge_info); -} - -type_init(icc_bus_register_types) diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h deleted file mode 100644 index 98a979fa1c..0000000000 --- a/include/hw/cpu/icc_bus.h +++ /dev/null @@ -1,82 +0,0 @@ -/* icc_bus.h - * emulate x86 ICC (Interrupt Controller Communications) bus - * - * Copyright (c) 2013 Red Hat, Inc - * - * Authors: - * Igor Mammedov - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see - */ -#ifndef ICC_BUS_H -#define ICC_BUS_H - -#include "exec/memory.h" -#include "hw/qdev-core.h" - -#define TYPE_ICC_BUS "icc-bus" - -#ifndef CONFIG_USER_ONLY - -/** - * ICCBus: - * - * ICC bus - */ -typedef struct ICCBus { - /*< private >*/ - BusState parent_obj; - /*< public >*/ - - MemoryRegion *apic_address_space; -} ICCBus; - -#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS) - -/** - * ICCDevice: - * - * ICC device - */ -typedef struct ICCDevice { - /*< private >*/ - DeviceState qdev; - /*< public >*/ -} ICCDevice; - -/** - * ICCDeviceClass: - * @init: Initialization callback for derived classes. - * - * ICC device class - */ -typedef struct ICCDeviceClass { - /*< private >*/ - DeviceClass parent_class; - /*< public >*/ - - DeviceRealize realize; -} ICCDeviceClass; - -#define TYPE_ICC_DEVICE "icc-device" -#define ICC_DEVICE(obj) OBJECT_CHECK(ICCDevice, (obj), TYPE_ICC_DEVICE) -#define ICC_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(ICCDeviceClass, (klass), TYPE_ICC_DEVICE) -#define ICC_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ICCDeviceClass, (obj), TYPE_ICC_DEVICE) - -#define TYPE_ICC_BRIDGE "icc-bridge" - -#endif /* CONFIG_USER_ONLY */ -#endif