2005-04-17 02:20:36 +04:00
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/bitops.h>
# include <linux/smp.h>
# include <linux/thread_info.h>
2005-11-14 03:07:23 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/processor.h>
2007-10-17 20:04:33 +04:00
# include <asm/pgtable.h>
2005-04-17 02:20:36 +04:00
# include <asm/msr.h>
# include <asm/uaccess.h>
2008-01-30 15:31:09 +03:00
# include <asm/ptrace.h>
# include <asm/ds.h>
2008-02-04 18:48:04 +03:00
# include <asm/bugs.h>
2005-04-17 02:20:36 +04:00
2008-09-10 03:40:35 +04:00
# ifdef CONFIG_X86_64
# include <asm/topology.h>
# include <asm/numa_64.h>
# endif
2005-04-17 02:20:36 +04:00
# include "cpu.h"
# ifdef CONFIG_X86_LOCAL_APIC
# include <asm/mpspec.h>
# include <asm/apic.h>
# include <mach_apic.h>
# endif
x86: use ELF section to list CPU vendor specific code
Replace the hardcoded list of initialization functions for each CPU
vendor by a list in an ELF section, which is read at initialization in
arch/x86/kernel/cpu/cpu.c to fill the cpu_devs[] array. The ELF
section, named .x86cpuvendor.init, is reclaimed after boot, and
contains entries of type "struct cpu_vendor_dev" which associates a
vendor number with a pointer to a "struct cpu_dev" structure.
This first modification allows to remove all the VENDOR_init_cpu()
functions.
This patch also removes the hardcoded calls to early_init_amd() and
early_init_intel(). Instead, we add a "c_early_init" member to the
cpu_dev structure, which is then called if not NULL by the generic CPU
initialization code. Unfortunately, in early_cpu_detect(), this_cpu is
not yet set, so we have to use the cpu_devs[] array directly.
This patch is part of the Linux Tiny project, and is needed for
further patch that will allow to disable compilation of unused CPU
support code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-02-15 14:00:23 +03:00
static void __cpuinit early_init_intel ( struct cpuinfo_x86 * c )
2005-04-17 02:20:36 +04:00
{
2008-01-30 15:32:40 +03:00
if ( ( c - > x86 = = 0xf & & c - > x86_model > = 0x03 ) | |
( c - > x86 = = 0x6 & & c - > x86_model > = 0x0e ) )
set_cpu_cap ( c , X86_FEATURE_CONSTANT_TSC ) ;
2008-09-10 03:40:35 +04:00
# ifdef CONFIG_X86_64
set_cpu_cap ( c , X86_FEATURE_SYSENTER32 ) ;
# else
/* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */
if ( c - > x86 = = 15 & & c - > x86_cache_alignment = = 64 )
c - > x86_cache_alignment = 128 ;
# endif
2005-04-17 02:20:36 +04:00
}
2008-09-10 03:40:35 +04:00
# ifdef CONFIG_X86_32
2005-04-17 02:20:36 +04:00
/*
* Early probe support logic for ppro memory erratum # 50
*
* This is called before we do cpu ident work
*/
2008-02-23 01:09:42 +03:00
2006-03-23 13:59:33 +03:00
int __cpuinit ppro_with_ram_bug ( void )
2005-04-17 02:20:36 +04:00
{
/* Uses data from early_cpu_detect now */
if ( boot_cpu_data . x86_vendor = = X86_VENDOR_INTEL & &
boot_cpu_data . x86 = = 6 & &
boot_cpu_data . x86_model = = 1 & &
boot_cpu_data . x86_mask < 8 ) {
printk ( KERN_INFO " Pentium Pro with Errata#50 detected. Taking evasive action. \n " ) ;
return 1 ;
}
return 0 ;
}
2008-02-23 01:09:42 +03:00
2008-09-10 03:40:38 +04:00
# ifdef CONFIG_X86_F00F_BUG
static void __cpuinit trap_init_f00f_bug ( void )
{
__set_fixmap ( FIX_F00F_IDT , __pa ( & idt_table ) , PAGE_KERNEL_RO ) ;
2005-04-17 02:20:36 +04:00
2008-09-10 03:40:38 +04:00
/*
* Update the IDT descriptor and reload the IDT so that
* it uses the read - only mapped virtual address .
*/
idt_descr . address = fix_to_virt ( FIX_F00F_IDT ) ;
load_idt ( & idt_descr ) ;
}
# endif
static void __cpuinit intel_workarounds ( struct cpuinfo_x86 * c )
2005-04-17 02:20:36 +04:00
{
unsigned long lo , hi ;
2008-09-10 03:40:38 +04:00
# ifdef CONFIG_X86_F00F_BUG
/*
* All current models of Pentium and Pentium with MMX technology CPUs
* have the F0 0F bug , which lets nonprivileged users lock up the system .
* Note that the workaround only should be initialized once . . .
*/
c - > f00f_bug = 0 ;
if ( ! paravirt_enabled ( ) & & c - > x86 = = 5 ) {
static int f00f_workaround_enabled ;
c - > f00f_bug = 1 ;
if ( ! f00f_workaround_enabled ) {
trap_init_f00f_bug ( ) ;
printk ( KERN_NOTICE " Intel Pentium with F0 0F bug - workaround enabled. \n " ) ;
f00f_workaround_enabled = 1 ;
}
}
# endif
/*
* SEP CPUID bug : Pentium Pro reports SEP but doesn ' t have it until
* model 3 mask 3
*/
if ( ( c - > x86 < < 8 | c - > x86_model < < 4 | c - > x86_mask ) < 0x633 )
clear_cpu_cap ( c , X86_FEATURE_SEP ) ;
/*
* P4 Xeon errata 037 workaround .
* Hardware prefetcher may cause stale data to be loaded into the cache .
*/
2005-04-17 02:20:36 +04:00
if ( ( c - > x86 = = 15 ) & & ( c - > x86_model = = 1 ) & & ( c - > x86_mask = = 1 ) ) {
2008-02-23 01:09:42 +03:00
rdmsr ( MSR_IA32_MISC_ENABLE , lo , hi ) ;
2005-04-17 02:20:36 +04:00
if ( ( lo & ( 1 < < 9 ) ) = = 0 ) {
printk ( KERN_INFO " CPU: C0 stepping P4 Xeon detected. \n " ) ;
printk ( KERN_INFO " CPU: Disabling hardware prefetching (Errata 037) \n " ) ;
lo | = ( 1 < < 9 ) ; /* Disable hw prefetching */
wrmsr ( MSR_IA32_MISC_ENABLE , lo , hi ) ;
}
}
2008-09-10 03:40:38 +04:00
/*
* See if we have a good local APIC by checking for buggy Pentia ,
* i . e . all B steppings and the C2 stepping of P54C when using their
* integrated APIC ( see 11 AP erratum in " Pentium Processor
* Specification Update " ).
*/
if ( cpu_has_apic & & ( c - > x86 < < 8 | c - > x86_model < < 4 ) = = 0x520 & &
( c - > x86_mask < 0x6 | | c - > x86_mask = = 0xb ) )
set_cpu_cap ( c , X86_FEATURE_11AP ) ;
2008-09-10 03:40:35 +04:00
2008-09-10 03:40:38 +04:00
# ifdef CONFIG_X86_INTEL_USERCOPY
2008-09-10 03:40:35 +04:00
/*
2008-09-10 03:40:38 +04:00
* Set up the preferred alignment for movsl bulk memory moves
2008-09-10 03:40:35 +04:00
*/
2008-09-10 03:40:38 +04:00
switch ( c - > x86 ) {
case 4 : /* 486: untested */
break ;
case 5 : /* Old Pentia: untested */
break ;
case 6 : /* PII/PIII only like movsl with 8-byte alignment */
movsl_mask . mask = 7 ;
break ;
case 15 : /* P4 is OK down to 8-byte alignment */
movsl_mask . mask = 7 ;
break ;
}
2008-09-10 03:40:35 +04:00
# endif
2008-09-10 03:40:38 +04:00
# ifdef CONFIG_X86_NUMAQ
numaq_tsc_disable ( ) ;
# endif
}
# else
static void __cpuinit intel_workarounds ( struct cpuinfo_x86 * c )
{
}
2008-09-10 03:40:35 +04:00
# endif
static void __cpuinit srat_detect_node ( void )
{
# if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
unsigned node ;
int cpu = smp_processor_id ( ) ;
int apicid = hard_smp_processor_id ( ) ;
/* Don't do the funky fallback heuristics the AMD version employs
for now . */
node = apicid_to_node [ apicid ] ;
if ( node = = NUMA_NO_NODE | | ! node_online ( node ) )
node = first_node ( node_online_map ) ;
numa_set_node ( cpu , node ) ;
printk ( KERN_INFO " CPU %d/%x -> Node %d \n " , cpu , apicid , node ) ;
# endif
}
2005-04-17 02:25:15 +04:00
/*
* find out the number of processor cores on the die
*/
2008-09-08 04:58:58 +04:00
static int __cpuinit intel_num_cpu_cores ( struct cpuinfo_x86 * c )
2005-04-17 02:25:15 +04:00
{
2005-09-04 02:56:42 +04:00
unsigned int eax , ebx , ecx , edx ;
2005-04-17 02:25:15 +04:00
if ( c - > cpuid_level < 4 )
return 1 ;
2005-09-04 02:56:42 +04:00
/* Intel has a non-standard dependency on %ecx for this CPUID level. */
cpuid_count ( 4 , 0 , & eax , & ebx , & ecx , & edx ) ;
2005-04-17 02:25:15 +04:00
if ( eax & 0x1f )
return ( ( eax > > 26 ) + 1 ) ;
else
return 1 ;
}
2008-09-10 14:53:34 +04:00
static void __cpuinit detect_vmx_virtcap ( struct cpuinfo_x86 * c )
{
/* Intel VMX MSR indicated features */
# define X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW 0x00200000
# define X86_VMX_FEATURE_PROC_CTLS_VNMI 0x00400000
# define X86_VMX_FEATURE_PROC_CTLS_2ND_CTLS 0x80000000
# define X86_VMX_FEATURE_PROC_CTLS2_VIRT_APIC 0x00000001
# define X86_VMX_FEATURE_PROC_CTLS2_EPT 0x00000002
# define X86_VMX_FEATURE_PROC_CTLS2_VPID 0x00000020
u32 vmx_msr_low , vmx_msr_high , msr_ctl , msr_ctl2 ;
clear_cpu_cap ( c , X86_FEATURE_TPR_SHADOW ) ;
clear_cpu_cap ( c , X86_FEATURE_VNMI ) ;
clear_cpu_cap ( c , X86_FEATURE_FLEXPRIORITY ) ;
clear_cpu_cap ( c , X86_FEATURE_EPT ) ;
clear_cpu_cap ( c , X86_FEATURE_VPID ) ;
rdmsr ( MSR_IA32_VMX_PROCBASED_CTLS , vmx_msr_low , vmx_msr_high ) ;
msr_ctl = vmx_msr_high | vmx_msr_low ;
if ( msr_ctl & X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW )
set_cpu_cap ( c , X86_FEATURE_TPR_SHADOW ) ;
if ( msr_ctl & X86_VMX_FEATURE_PROC_CTLS_VNMI )
set_cpu_cap ( c , X86_FEATURE_VNMI ) ;
if ( msr_ctl & X86_VMX_FEATURE_PROC_CTLS_2ND_CTLS ) {
rdmsr ( MSR_IA32_VMX_PROCBASED_CTLS2 ,
vmx_msr_low , vmx_msr_high ) ;
msr_ctl2 = vmx_msr_high | vmx_msr_low ;
if ( ( msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_VIRT_APIC ) & &
( msr_ctl & X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW ) )
set_cpu_cap ( c , X86_FEATURE_FLEXPRIORITY ) ;
if ( msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_EPT )
set_cpu_cap ( c , X86_FEATURE_EPT ) ;
if ( msr_ctl2 & X86_VMX_FEATURE_PROC_CTLS2_VPID )
set_cpu_cap ( c , X86_FEATURE_VPID ) ;
}
}
2006-03-23 13:59:33 +03:00
static void __cpuinit init_intel ( struct cpuinfo_x86 * c )
2005-04-17 02:20:36 +04:00
{
unsigned int l2 = 0 ;
2008-01-30 15:32:40 +03:00
early_init_intel ( c ) ;
2008-09-10 03:40:38 +04:00
intel_workarounds ( c ) ;
2005-04-17 02:20:36 +04:00
l2 = init_intel_cacheinfo ( c ) ;
2008-02-23 01:09:42 +03:00
if ( c - > cpuid_level > 9 ) {
2006-06-26 15:59:59 +04:00
unsigned eax = cpuid_eax ( 10 ) ;
/* Check for version and the number of counters */
if ( ( eax & 0xff ) & & ( ( ( eax > > 8 ) & 0xff ) > 1 ) )
2008-02-26 10:52:33 +03:00
set_cpu_cap ( c , X86_FEATURE_ARCH_PERFMON ) ;
2006-06-26 15:59:59 +04:00
}
2005-04-17 02:20:36 +04:00
2008-09-10 03:40:38 +04:00
if ( cpu_has_xmm2 )
set_cpu_cap ( c , X86_FEATURE_LFENCE_RDTSC ) ;
if ( cpu_has_ds ) {
unsigned int l1 ;
rdmsr ( MSR_IA32_MISC_ENABLE , l1 , l2 ) ;
if ( ! ( l1 & ( 1 < < 11 ) ) )
set_cpu_cap ( c , X86_FEATURE_BTS ) ;
if ( ! ( l1 & ( 1 < < 12 ) ) )
set_cpu_cap ( c , X86_FEATURE_PEBS ) ;
ds_init_intel ( c ) ;
}
2005-04-17 02:20:36 +04:00
2008-09-10 03:40:38 +04:00
# ifdef CONFIG_X86_64
if ( c - > x86 = = 15 )
c - > x86_cache_alignment = c - > x86_clflush_size * 2 ;
if ( c - > x86 = = 6 )
set_cpu_cap ( c , X86_FEATURE_REP_GOOD ) ;
# else
2008-02-23 01:09:42 +03:00
/*
* Names for the Pentium II / Celeron processors
* detectable only by also checking the cache size .
* Dixon is NOT a Celeron .
*/
2005-04-17 02:20:36 +04:00
if ( c - > x86 = = 6 ) {
2008-09-10 03:40:38 +04:00
char * p = NULL ;
2005-04-17 02:20:36 +04:00
switch ( c - > x86_model ) {
case 5 :
if ( c - > x86_mask = = 0 ) {
if ( l2 = = 0 )
p = " Celeron (Covington) " ;
else if ( l2 = = 256 )
p = " Mobile Pentium II (Dixon) " ;
}
break ;
2008-02-23 01:09:42 +03:00
2005-04-17 02:20:36 +04:00
case 6 :
if ( l2 = = 128 )
p = " Celeron (Mendocino) " ;
else if ( c - > x86_mask = = 0 | | c - > x86_mask = = 5 )
p = " Celeron-A " ;
break ;
2008-02-23 01:09:42 +03:00
2005-04-17 02:20:36 +04:00
case 8 :
if ( l2 = = 128 )
p = " Celeron (Coppermine) " ;
break ;
}
2008-09-10 03:40:38 +04:00
if ( p )
strcpy ( c - > x86_model_id , p ) ;
2005-04-17 02:20:36 +04:00
}
2008-09-10 03:40:35 +04:00
if ( c - > x86 = = 15 )
set_cpu_cap ( c , X86_FEATURE_P4 ) ;
if ( c - > x86 = = 6 )
set_cpu_cap ( c , X86_FEATURE_P3 ) ;
2008-01-30 15:31:09 +03:00
if ( cpu_has_bts )
2008-04-08 13:01:58 +04:00
ptrace_bts_init_intel ( c ) ;
2008-07-13 09:52:55 +04:00
2008-09-10 03:40:35 +04:00
# endif
detect_extended_topology ( c ) ;
if ( ! cpu_has ( c , X86_FEATURE_XTOPOLOGY ) ) {
/*
* let ' s use the legacy cpuid vector 0x1 and 0x4 for topology
* detection .
*/
c - > x86_max_cores = intel_num_cpu_cores ( c ) ;
# ifdef CONFIG_X86_32
detect_ht ( c ) ;
# endif
}
/* Work around errata */
srat_detect_node ( ) ;
2008-09-10 14:53:34 +04:00
if ( cpu_has ( c , X86_FEATURE_VMX ) )
detect_vmx_virtcap ( c ) ;
2006-12-07 04:14:01 +03:00
}
2005-04-17 02:20:36 +04:00
2008-09-10 03:40:35 +04:00
# ifdef CONFIG_X86_32
2008-02-23 01:09:42 +03:00
static unsigned int __cpuinit intel_size_cache ( struct cpuinfo_x86 * c , unsigned int size )
2005-04-17 02:20:36 +04:00
{
2008-02-23 01:09:42 +03:00
/*
* Intel PIII Tualatin . This comes in two flavours .
2005-04-17 02:20:36 +04:00
* One has 256 kb of cache , the other 512. We have no way
* to determine which , so we use a boottime override
* for the 512 kb model , and assume 256 otherwise .
*/
if ( ( c - > x86 = = 6 ) & & ( c - > x86_model = = 11 ) & & ( size = = 0 ) )
size = 256 ;
return size ;
}
2008-09-10 03:40:35 +04:00
# endif
2005-04-17 02:20:36 +04:00
2006-03-23 13:59:33 +03:00
static struct cpu_dev intel_cpu_dev __cpuinitdata = {
2005-04-17 02:20:36 +04:00
. c_vendor = " Intel " ,
2008-02-23 01:09:42 +03:00
. c_ident = { " GenuineIntel " } ,
2008-09-10 03:40:35 +04:00
# ifdef CONFIG_X86_32
2005-04-17 02:20:36 +04:00
. c_models = {
2008-02-23 01:09:42 +03:00
{ . vendor = X86_VENDOR_INTEL , . family = 4 , . model_names =
{
[ 0 ] = " 486 DX-25/33 " ,
[ 1 ] = " 486 DX-50 " ,
[ 2 ] = " 486 SX " ,
[ 3 ] = " 486 DX/2 " ,
[ 4 ] = " 486 SL " ,
[ 5 ] = " 486 SX/2 " ,
[ 7 ] = " 486 DX/2-WB " ,
[ 8 ] = " 486 DX/4 " ,
2005-04-17 02:20:36 +04:00
[ 9 ] = " 486 DX/4-WB "
}
} ,
{ . vendor = X86_VENDOR_INTEL , . family = 5 , . model_names =
2008-02-23 01:09:42 +03:00
{
[ 0 ] = " Pentium 60/66 A-step " ,
[ 1 ] = " Pentium 60/66 " ,
2005-04-17 02:20:36 +04:00
[ 2 ] = " Pentium 75 - 200 " ,
2008-02-23 01:09:42 +03:00
[ 3 ] = " OverDrive PODP5V83 " ,
2005-04-17 02:20:36 +04:00
[ 4 ] = " Pentium MMX " ,
2008-02-23 01:09:42 +03:00
[ 7 ] = " Mobile Pentium 75 - 200 " ,
2005-04-17 02:20:36 +04:00
[ 8 ] = " Mobile Pentium MMX "
}
} ,
{ . vendor = X86_VENDOR_INTEL , . family = 6 , . model_names =
2008-02-23 01:09:42 +03:00
{
2005-04-17 02:20:36 +04:00
[ 0 ] = " Pentium Pro A-step " ,
2008-02-23 01:09:42 +03:00
[ 1 ] = " Pentium Pro " ,
[ 3 ] = " Pentium II (Klamath) " ,
[ 4 ] = " Pentium II (Deschutes) " ,
[ 5 ] = " Pentium II (Deschutes) " ,
2005-04-17 02:20:36 +04:00
[ 6 ] = " Mobile Pentium II " ,
2008-02-23 01:09:42 +03:00
[ 7 ] = " Pentium III (Katmai) " ,
[ 8 ] = " Pentium III (Coppermine) " ,
2005-04-17 02:20:36 +04:00
[ 10 ] = " Pentium III (Cascades) " ,
[ 11 ] = " Pentium III (Tualatin) " ,
}
} ,
{ . vendor = X86_VENDOR_INTEL , . family = 15 , . model_names =
{
[ 0 ] = " Pentium 4 (Unknown) " ,
[ 1 ] = " Pentium 4 (Willamette) " ,
[ 2 ] = " Pentium 4 (Northwood) " ,
[ 4 ] = " Pentium 4 (Foster) " ,
[ 5 ] = " Pentium 4 (Foster) " ,
}
} ,
} ,
2008-09-10 03:40:35 +04:00
. c_size_cache = intel_size_cache ,
# endif
x86: use ELF section to list CPU vendor specific code
Replace the hardcoded list of initialization functions for each CPU
vendor by a list in an ELF section, which is read at initialization in
arch/x86/kernel/cpu/cpu.c to fill the cpu_devs[] array. The ELF
section, named .x86cpuvendor.init, is reclaimed after boot, and
contains entries of type "struct cpu_vendor_dev" which associates a
vendor number with a pointer to a "struct cpu_dev" structure.
This first modification allows to remove all the VENDOR_init_cpu()
functions.
This patch also removes the hardcoded calls to early_init_amd() and
early_init_intel(). Instead, we add a "c_early_init" member to the
cpu_dev structure, which is then called if not NULL by the generic CPU
initialization code. Unfortunately, in early_cpu_detect(), this_cpu is
not yet set, so we have to use the cpu_devs[] array directly.
This patch is part of the Linux Tiny project, and is needed for
further patch that will allow to disable compilation of unused CPU
support code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-02-15 14:00:23 +03:00
. c_early_init = early_init_intel ,
2005-04-17 02:20:36 +04:00
. c_init = init_intel ,
2008-09-04 23:09:45 +04:00
. c_x86_vendor = X86_VENDOR_INTEL ,
2005-04-17 02:20:36 +04:00
} ;
2008-09-04 23:09:45 +04:00
cpu_dev_register ( intel_cpu_dev ) ;
2005-04-17 02:20:36 +04:00