Skip to content

Commit

Permalink
Use a new CPU feature word to cover features that are spread around
Browse files Browse the repository at this point in the history
Some Intel features are spread around in different CPUID leafs like 0x5,
0x6 and 0xA.  Make this feature detection code common across i386 and
x86_64.

Display Intel Dynamic Acceleration feature in /proc/cpuinfo. This feature
will be enabled automatically by current acpi-cpufreq driver.

Refer to Intel Software Developer's Manual for more details about the feature.

Thanks to hpa (H Peter Anvin) for the making the actual code detecting the
scattered features data-driven.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Venki Pallipadi authored and Linus Torvalds committed Jul 12, 2007
1 parent e087db5 commit 1d67953
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 3 deletions.
2 changes: 1 addition & 1 deletion arch/i386/kernel/cpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
obj-y += transmeta.o
obj-y += intel.o intel_cacheinfo.o
obj-y += intel.o intel_cacheinfo.o addon_cpuid_features.o
obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o
Expand Down
50 changes: 50 additions & 0 deletions arch/i386/kernel/cpu/addon_cpuid_features.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

/*
* Routines to indentify additional cpu features that are scattered in
* cpuid space.
*/

#include <linux/cpu.h>

#include <asm/processor.h>

struct cpuid_bit {
u16 feature;
u8 reg;
u8 bit;
u32 level;
};

enum cpuid_regs {
CR_EAX = 0,
CR_ECX,
CR_EDX,
CR_EBX
};

void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
{
u32 max_level;
u32 regs[4];
const struct cpuid_bit *cb;

static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
{ 0, 0, 0, 0 }
};

for (cb = cpuid_bits; cb->feature; cb++) {

/* Verify that the level is valid */
max_level = cpuid_eax(cb->level & 0xffff0000);
if (max_level < cb->level ||
max_level > (cb->level | 0xffff))
continue;

cpuid(cb->level, &regs[CR_EAX], &regs[CR_EBX],
&regs[CR_ECX], &regs[CR_EDX]);

if (regs[cb->reg] & (1 << cb->bit))
set_bit(cb->feature, c->x86_capability);
}
}
2 changes: 2 additions & 0 deletions arch/i386/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
if ( xlvl >= 0x80000004 )
get_model_name(c); /* Default name */
}

init_scattered_cpuid_features(c);
}

early_intel_workaround(c);
Expand Down
6 changes: 6 additions & 0 deletions arch/i386/kernel/cpu/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"osvw", "ibs", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

/* Auxiliary (Linux-defined) */
"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static const char * const x86_power_flags[] = {
"ts", /* temperature sensor */
Expand Down
2 changes: 2 additions & 0 deletions arch/x86_64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ obj-$(CONFIG_PCI) += early-quirks.o

obj-y += topology.o
obj-y += intel_cacheinfo.o
obj-y += addon_cpuid_features.o
obj-y += pcspeaker.o

CFLAGS_vsyscall.o := $(PROFILING) -g0
Expand All @@ -55,6 +56,7 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o
topology-y += ../../i386/kernel/topology.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o
intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
addon_cpuid_features-y += ../../i386/kernel/cpu/addon_cpuid_features.o
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
Expand Down
8 changes: 8 additions & 0 deletions arch/x86_64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_capability[2] = cpuid_edx(0x80860001);
}

init_scattered_cpuid_features(c);

c->apicid = phys_pkg_id(0);

/*
Expand Down Expand Up @@ -973,6 +975,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"osvw", "ibs", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

/* Auxiliary (Linux-defined) */
"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static char *x86_power_flags[] = {
"ts", /* temperature sensor */
Expand Down
11 changes: 9 additions & 2 deletions include/asm-i386/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#endif
#include <asm/required-features.h>

#define NCAPINTS 7 /* N 32-bit words worth of info */
#define NCAPINTS 8 /* N 32-bit words worth of info */

/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
Expand Down Expand Up @@ -109,6 +109,12 @@
#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */
#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */

/*
* Auxiliary flags: Linux defined - For features scattered in various
* CPUID levels like 0x6, 0xA etc
*/
#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */

#define cpu_has(c, bit) \
(__builtin_constant_p(bit) && \
( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \
Expand All @@ -117,7 +123,8 @@
(((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) || \
(((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) || \
(((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) || \
(((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ) \
(((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \
(((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ) \
? 1 : \
test_bit(bit, (c)->x86_capability))
#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit)
Expand Down
1 change: 1 addition & 0 deletions include/asm-i386/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ void __init cpu_detect(struct cpuinfo_x86 *c);
extern void identify_boot_cpu(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern unsigned short num_cache_leaves;

Expand Down
1 change: 1 addition & 0 deletions include/asm-i386/required-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@
#define REQUIRED_MASK4 0
#define REQUIRED_MASK5 0
#define REQUIRED_MASK6 0
#define REQUIRED_MASK7 0

#endif
1 change: 1 addition & 0 deletions include/asm-x86_64/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ extern char ignore_irq13;

extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern unsigned short num_cache_leaves;

Expand Down
1 change: 1 addition & 0 deletions include/asm-x86_64/required-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
#define REQUIRED_MASK4 0
#define REQUIRED_MASK5 0
#define REQUIRED_MASK6 0
#define REQUIRED_MASK7 0

#endif

0 comments on commit 1d67953

Please sign in to comment.