On Thu, 25 Apr 2013 15:43:06 -0300 Eduardo Habkost <ehabk...@redhat.com> wrote:
> The current code handling the CPUID 0xA leaf simply forwards all data > from GET_SUPPORTED_CPUID directly to the guest, breaking migration > between hosts with different number of PMU counters. > > This patch disables this behavior, except on older machine-types (for > compatibility) and on the "host" CPU model. Please, make it static property and use compat properties. Result will be simpler and much less will have to be redone/discarded after converting to the rest to properties and sub-classes. > > Signed-off-by: Eduardo Habkost <ehabk...@redhat.com> > Cc: Gleb Natapov <g...@redhat.com> > --- > hw/i386/pc_piix.c | 1 + > hw/i386/pc_q35.c | 1 + > target-i386/cpu.c | 25 ++++++++++++++++++++++++- > target-i386/cpu.h | 7 +++++++ > 4 files changed, 33 insertions(+), 1 deletion(-) > > diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c > index 9372f77..bbc7064 100644 > --- a/hw/i386/pc_piix.c > +++ b/hw/i386/pc_piix.c > @@ -239,6 +239,7 @@ static void pc_init_pci_1_4(QEMUMachineInitArgs *args) > { > x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); > x86_cpu_compat_set_model("486", 0); > + x86_cpu_enable_pmu_passthrough(); > pc_init_pci(args); > } > > diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c > index fc566fd..9718e94 100644 > --- a/hw/i386/pc_q35.c > +++ b/hw/i386/pc_q35.c > @@ -213,6 +213,7 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args) > { > x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); > x86_cpu_compat_set_model("486", 0); > + x86_cpu_enable_pmu_passthrough(); > pc_q35_init(args); > } > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index 4fc7527..602d00f 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -245,6 +245,16 @@ static uint32_t kvm_default_features = (1 << > KVM_FEATURE_CLOCKSOURCE) | > (1 << KVM_FEATURE_PV_EOI) | > (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); > > +/* Enables passthrough of CPUID leaf 0xA by default, for compatibility with > old > + * machine-types. > + */ > +static bool default_pmu_passthrough; > + > +void x86_cpu_enable_pmu_passthrough(void) > +{ > + default_pmu_passthrough = true; > +} > + > void disable_kvm_pv_eoi(void) > { > kvm_default_features &= ~(1UL << KVM_FEATURE_PV_EOI); > @@ -375,6 +385,12 @@ typedef struct x86_def_t { > int stepping; > FeatureWordArray features; > char model_id[48]; > + > + /* Enable direct passthrough of PMU leaf from the GET_SUPPORTED_CPUID > + * data returned by the kernel. This is not migration-safe and should > + * never be enabled by default. > + */ > + bool cpuid_pmu_passthrough; > } x86_def_t; > > #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) > @@ -1120,6 +1136,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) > x86_cpu_def->features[FEAT_KVM] = > kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); > > + x86_cpu_def->cpuid_pmu_passthrough = true; > + > #endif /* CONFIG_KVM */ > } > > @@ -1735,9 +1753,13 @@ static void cpu_x86_register(X86CPU *cpu, const char > *name, Error **errp) > return; > } > > + /* Defaults & compat bits that are not in the builtin_x86_defs table: */ > if (kvm_enabled()) { > def->features[FEAT_KVM] |= kvm_default_features; > } > + if (default_pmu_passthrough) { > + def->cpuid_pmu_passthrough = true; > + } > def->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; > > object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp); > @@ -1755,6 +1777,7 @@ static void cpu_x86_register(X86CPU *cpu, const char > *name, Error **errp) > env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX]; > env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX]; > env->cpuid_xlevel2 = def->xlevel2; > + env->cpuid_pmu_passthrough = def->cpuid_pmu_passthrough; > > object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); > } > @@ -1986,7 +2009,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > uint32_t count, > break; > case 0xA: > /* Architectural Performance Monitoring Leaf */ > - if (kvm_enabled()) { > + if (kvm_enabled() && env->cpuid_pmu_passthrough) { > KVMState *s = cs->kvm_state; > > *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); > diff --git a/target-i386/cpu.h b/target-i386/cpu.h > index 1cd5d19..12c8bf1 100644 > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -843,6 +843,12 @@ typedef struct CPUX86State { > uint32_t cpuid_vendor3; > uint32_t cpuid_version; > FeatureWordArray features; > + > + /* Enable direct passthrough of PMU leaf from the GET_SUPPORTED_CPUID > + * data returned by the kernel. This is not migration-safe and should > + * never be enabled by default. > + */ > + bool cpuid_pmu_passthrough; > uint32_t cpuid_model[12]; > uint32_t cpuid_apic_id; > > @@ -1258,6 +1264,7 @@ void x86_cpu_compat_set_features(const char *cpu_model, > FeatureWord w, > uint32_t feat_add, uint32_t feat_remove); > void x86_cpu_compat_set_level(const char *cpu_model, uint32_t level); > void x86_cpu_compat_set_model(const char *cpu_model, uint32_t model); > +void x86_cpu_enable_pmu_passthrough(void); > > > /* Return name of 32-bit register, from a R_* constant */ > -- > 1.8.1.4 > -- Regards, Igor