Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 136526
b: refs/heads/master
c: b38b066
h: refs/heads/master
v: v3
  • Loading branch information
H. Peter Anvin committed Jan 24, 2009
1 parent 3b564b8 commit 857a042
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 75a048119e76540d73132cfc8e0fa0c0a8bb6c83
refs/heads/master: b38b0665905538e76e26f2a4c686179abb1f69f6
47 changes: 47 additions & 0 deletions trunk/arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,49 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
}
#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;
Expand Down Expand Up @@ -573,6 +616,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
#ifdef CONFIG_SMP
c->cpu_index = boot_cpu_id;
#endif
filter_cpuid_features(c, false);
}

void __init early_cpu_init(void)
Expand Down Expand Up @@ -706,6 +750,9 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
* 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;
Expand Down

0 comments on commit 857a042

Please sign in to comment.