提交 11fdd252 编写于 作者: Y Yinghai Lu 提交者: Ingo Molnar

x86: cpu make amd.c more like amd_64.c v2

1. make 32bit have early_init_amd_mc and amd_detect_cmp
2. seperate init_amd_k5/k6/k7 ...

v2: fix compiling for !CONFIG_SMP
Signed-off-by: NYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: NIngo Molnar <mingo@elte.hu>
上级 2d9cd6c2
...@@ -24,56 +24,9 @@ ...@@ -24,56 +24,9 @@
extern void vide(void); extern void vide(void);
__asm__(".align 4\nvide: ret"); __asm__(".align 4\nvide: ret");
static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c)
{ {
if (c->x86_power & (1<<8)) /*
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
/* Set MTRR capability flag if appropriate */
if (c->x86_model == 13 || c->x86_model == 9 ||
(c->x86_model == 8 && c->x86_mask >= 8))
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
}
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
#ifdef CONFIG_SMP
unsigned long long value;
/*
* Disable TLB flush filter by setting HWCR.FFDIS on K8
* bit 6 of msr C001_0015
*
* Errata 63 for SH-B3 steppings
* Errata 122 for all steppings (F+ have it disabled by default)
*/
if (c->x86 == 15) {
rdmsrl(MSR_K7_HWCR, value);
value |= 1 << 6;
wrmsrl(MSR_K7_HWCR, value);
}
#endif
early_init_amd(c);
/*
* FIXME: We should handle the K5 here. Set up the write
* range and also turn on MSR 83 bits 4 and 31 (write alloc,
* no bus pipeline)
*/
/*
* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
* 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
*/
clear_cpu_cap(c, 0*32+31);
switch (c->x86) {
case 4:
/*
* General Systems BIOSen alias the cpu frequency registers * General Systems BIOSen alias the cpu frequency registers
* of the Elan at 0x000df000. Unfortuantly, one of the Linux * of the Elan at 0x000df000. Unfortuantly, one of the Linux
* drivers subsequently pokes it, and changes the CPU speed. * drivers subsequently pokes it, and changes the CPU speed.
...@@ -86,15 +39,21 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -86,15 +39,21 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
if (inl (CBAR) & CBAR_ENB) if (inl (CBAR) & CBAR_ENB)
outl (0 | CBAR_KEY, CBAR); outl (0 | CBAR_KEY, CBAR);
} }
break; }
case 5:
static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)
{
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
if (c->x86_model < 6) { if (c->x86_model < 6) {
/* Based on AMD doc 20734R - June 2000 */ /* Based on AMD doc 20734R - June 2000 */
if (c->x86_model == 0) { if (c->x86_model == 0) {
clear_cpu_cap(c, X86_FEATURE_APIC); clear_cpu_cap(c, X86_FEATURE_APIC);
set_cpu_cap(c, X86_FEATURE_PGE); set_cpu_cap(c, X86_FEATURE_PGE);
} }
break; return;
} }
if (c->x86_model == 6 && c->x86_mask == 1) { if (c->x86_model == 6 && c->x86_mask == 1) {
...@@ -143,7 +102,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -143,7 +102,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
mbytes); mbytes);
} }
break; return;
} }
if ((c->x86_model == 8 && c->x86_mask > 7) || if ((c->x86_model == 8 && c->x86_mask > 7) ||
...@@ -165,16 +124,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -165,16 +124,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
mbytes); mbytes);
} }
break; return;
} }
if (c->x86_model == 10) { if (c->x86_model == 10) {
/* AMD Geode LX is model 10 */ /* AMD Geode LX is model 10 */
/* placeholder for any needed mods */ /* placeholder for any needed mods */
break; return;
} }
break; }
case 6: /* An Athlon/Duron */
static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
{
u32 l, h;
/* /*
* Bit 15 of Athlon specific MSR 15, needs to be 0 * Bit 15 of Athlon specific MSR 15, needs to be 0
...@@ -204,61 +166,151 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -204,61 +166,151 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
} }
} }
break;
}
switch (c->x86) {
case 15:
/* Use K8 tuning for Fam10h and Fam11h */
case 0x10:
case 0x11:
set_cpu_cap(c, X86_FEATURE_K8);
break;
case 6:
set_cpu_cap(c, X86_FEATURE_K7); set_cpu_cap(c, X86_FEATURE_K7);
break; }
}
if (c->x86 >= 6)
set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
display_cacheinfo(c); /*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
*/
static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_HT
unsigned bits;
bits = c->x86_coreid_bits;
if (cpuid_eax(0x80000000) >= 0x80000008) /* Low order bits define the core id (index of core in socket) */
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
/* Convert the initial APIC ID into the socket ID */
c->phys_proc_id = c->initial_apicid >> bits;
#endif
}
static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_HT #ifdef CONFIG_X86_HT
/* unsigned bits, ecx;
* On a AMD multi core setup the lower bits of the APIC id
* distinguish the cores. /* Multi core CPU? */
*/ if (c->extended_cpuid_level < 0x80000008)
if (c->x86_max_cores > 1) { return;
int cpu = smp_processor_id();
unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
ecx = cpuid_ecx(0x80000008);
c->x86_max_cores = (ecx & 0xff) + 1;
/* CPU telling us the core id bits shift? */
bits = (ecx >> 12) & 0xF;
/* Otherwise recompute */
if (bits == 0) { if (bits == 0) {
while ((1 << bits) < c->x86_max_cores) while ((1 << bits) < c->x86_max_cores)
bits++; bits++;
} }
c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
c->phys_proc_id >>= bits; c->x86_coreid_bits = bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n", #endif
cpu, c->x86_max_cores, c->cpu_core_id); }
static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
{
early_init_amd_mc(c);
if (c->x86_power & (1<<8))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
/* Set MTRR capability flag if appropriate */
if (c->x86_model == 13 || c->x86_model == 9 ||
(c->x86_model == 8 && c->x86_mask >= 8))
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
}
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
unsigned long long value;
/*
* Disable TLB flush filter by setting HWCR.FFDIS on K8
* bit 6 of msr C001_0015
*
* Errata 63 for SH-B3 steppings
* Errata 122 for all steppings (F+ have it disabled by default)
*/
if (c->x86 == 0xf) {
rdmsrl(MSR_K7_HWCR, value);
value |= 1 << 6;
wrmsrl(MSR_K7_HWCR, value);
} }
#endif #endif
if (cpuid_eax(0x80000000) >= 0x80000006) { early_init_amd(c);
if ((c->x86 == 0x10) && (cpuid_edx(0x80000006) & 0xf000))
num_cache_leaves = 4; /*
else * FIXME: We should handle the K5 here. Set up the write
num_cache_leaves = 3; * range and also turn on MSR 83 bits 4 and 31 (write alloc,
* no bus pipeline)
*/
/*
* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
* 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
*/
clear_cpu_cap(c, 0*32+31);
switch (c->x86) {
case 4:
init_amd_k5(c);
break;
case 5:
init_amd_k6(c);
break;
case 6: /* An Athlon/Duron */
init_amd_k7(c);
break;
} }
/* K6s reports MCEs but don't actually have all the MSRs */ /* K6s reports MCEs but don't actually have all the MSRs */
if (c->x86 < 6) if (c->x86 < 6)
clear_cpu_cap(c, X86_FEATURE_MCE); clear_cpu_cap(c, X86_FEATURE_MCE);
if (cpu_has_xmm2) if (c->x86 >= 6)
set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
if (!c->x86_model_id[0]) {
switch (c->x86) {
case 0xf:
/* Should distinguish Models here, but this is only
a fallback anyways. */
strcpy(c->x86_model_id, "Hammer");
break;
}
}
display_cacheinfo(c);
/* Multi core CPU? */
if (c->extended_cpuid_level >= 0x80000008)
amd_detect_cmp(c);
detect_ht(c);
if (c->extended_cpuid_level >= 0x80000006) {
if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
num_cache_leaves = 4;
else
num_cache_leaves = 3;
}
if (c->x86 >= 0xf && c->x86 <= 0x11)
set_cpu_cap(c, X86_FEATURE_K8);
if (cpu_has_xmm2) {
/* MFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
}
} }
static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
......
...@@ -174,17 +174,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -174,17 +174,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
if (c->extended_cpuid_level >= 0x80000008) if (c->extended_cpuid_level >= 0x80000008)
amd_detect_cmp(c); amd_detect_cmp(c);
if (c->extended_cpuid_level >= 0x80000006 && if (c->extended_cpuid_level >= 0x80000006) {
(cpuid_edx(0x80000006) & 0xf000)) if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
num_cache_leaves = 4; num_cache_leaves = 4;
else else
num_cache_leaves = 3; num_cache_leaves = 3;
}
if (c->x86 >= 0xf && c->x86 <= 0x11) if (c->x86 >= 0xf && c->x86 <= 0x11)
set_cpu_cap(c, X86_FEATURE_K8); set_cpu_cap(c, X86_FEATURE_K8);
if (cpu_has_xmm2) {
/* MFENCE stops RDTSC speculation */ /* MFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
}
if (c->x86 == 0x10) { if (c->x86 == 0x10) {
/* do this for boot cpu */ /* do this for boot cpu */
......
...@@ -629,8 +629,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) ...@@ -629,8 +629,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */
c->x86_max_cores = 1; c->x86_max_cores = 1;
#ifdef CONFIG_X86_64
c->x86_coreid_bits = 0; c->x86_coreid_bits = 0;
#ifdef CONFIG_X86_64
c->x86_clflush_size = 64; c->x86_clflush_size = 64;
#else #else
c->cpuid_level = -1; /* CPUID not detected */ c->cpuid_level = -1; /* CPUID not detected */
......
...@@ -75,9 +75,9 @@ struct cpuinfo_x86 { ...@@ -75,9 +75,9 @@ struct cpuinfo_x86 {
int x86_tlbsize; int x86_tlbsize;
__u8 x86_virt_bits; __u8 x86_virt_bits;
__u8 x86_phys_bits; __u8 x86_phys_bits;
#endif
/* CPUID returned core id bits: */ /* CPUID returned core id bits: */
__u8 x86_coreid_bits; __u8 x86_coreid_bits;
#endif
/* Max extended CPUID function supported: */ /* Max extended CPUID function supported: */
__u32 extended_cpuid_level; __u32 extended_cpuid_level;
/* Maximum supported CPUID level, -1=no CPUID: */ /* Maximum supported CPUID level, -1=no CPUID: */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册