}
 #endif
 
+/*
+ * Some CPU features depend on higher CPUID levels, which may not always
+ * be available due to CPUID level capping or broken virtualization
+ * software.  Add those features to this table to auto-disable them.
+ */
+struct cpuid_dependent_feature {
+       u32 feature;
+       u32 level;
+};
+static const struct cpuid_dependent_feature __cpuinitconst
+cpuid_dependent_features[] = {
+       { X86_FEATURE_MWAIT,            0x00000005 },
+       { X86_FEATURE_DCA,              0x00000009 },
+       { X86_FEATURE_XSAVE,            0x0000000d },
+       { 0, 0 }
+};
+
+static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
+{
+       const struct cpuid_dependent_feature *df;
+       for (df = cpuid_dependent_features; df->feature; df++) {
+               /*
+                * Note: cpuid_level is set to -1 if unavailable, but
+                * extended_extended_level is set to 0 if unavailable
+                * and the legitimate extended levels are all negative
+                * when signed; hence the weird messing around with
+                * signs here...
+                */
+               if (cpu_has(c, df->feature) &&
+                   ((s32)df->feature < 0 ?
+                    (u32)df->feature > (u32)c->extended_cpuid_level :
+                    (s32)df->feature > (s32)c->cpuid_level)) {
+                       clear_cpu_cap(c, df->feature);
+                       if (warn)
+                               printk(KERN_WARNING
+                                      "CPU: CPU feature %s disabled "
+                                      "due to lack of CPUID level 0x%x\n",
+                                      x86_cap_flags[df->feature],
+                                      df->level);
+               }
+       }
+}      
+
 /*
  * Naming convention should be: <Name> [(<Codename>)]
  * This table only is used unless init_<vendor>() below doesn't set it;
 #ifdef CONFIG_SMP
        c->cpu_index = boot_cpu_id;
 #endif
+       filter_cpuid_features(c, false);
 }
 
 void __init early_cpu_init(void)
         * we do "generic changes."
         */
 
+       /* Filter out anything that depends on CPUID levels we don't have */
+       filter_cpuid_features(c, true);
+
        /* If the model name is still unset, do table lookup. */
        if (!c->x86_model_id[0]) {
                char *p;