Commit 168c9069 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] handle out of spec SMP athlons.

Newer Athlons have means of checking if they are SMP capable or not.
This code adds checks that printk a warning on systems not intended
for SMP, and set the taint flag that modutils is already aware of.
The taint code is also improved to use defines instead of magic numbers.
parent e0278a2f
...@@ -219,6 +219,11 @@ characters, each representing a particular tainted value. ...@@ -219,6 +219,11 @@ characters, each representing a particular tainted value.
2: 'F' if any module was force loaded by insmod -f, ' ' if all 2: 'F' if any module was force loaded by insmod -f, ' ' if all
modules were loaded normally. modules were loaded normally.
3: 'S' if the oops occured on an SMP kernel running on hardware that
hasn't been certified as safe to run multiprocessor.
Currently this occurs only on various Athlons that are not
SMP capable.
The primary reason for the 'Tainted: ' string is to tell kernel The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent, even if an offending module is occurred. Tainting is permanent, even if an offending module is
......
...@@ -2652,7 +2652,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -2652,7 +2652,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* AMD-defined */ /* AMD-defined */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, "mmxext", NULL, NULL, NULL, NULL, "mp", NULL, NULL, "mmxext", NULL,
NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
/* Transmeta-defined */ /* Transmeta-defined */
......
...@@ -30,10 +30,12 @@ ...@@ -30,10 +30,12 @@
* Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
* Maciej W. Rozycki : Bits for genuine 82489DX APICs * Maciej W. Rozycki : Bits for genuine 82489DX APICs
* Martin J. Bligh : Added support for multi-quad systems * Martin J. Bligh : Added support for multi-quad systems
* Dave Jones : Report invalid combinations of Athlon CPUs.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
...@@ -160,6 +162,35 @@ void __init smp_store_cpu_info(int id) ...@@ -160,6 +162,35 @@ void __init smp_store_cpu_info(int id)
* Remember we have B step Pentia with bugs * Remember we have B step Pentia with bugs
*/ */
smp_b_stepping = 1; smp_b_stepping = 1;
/*
* Certain Athlons might work (for various values of 'work') in SMP
* but they are not certified as MP capable.
*/
if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
/* Athlon 660/661 is valid. */
if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
goto valid_k7;
/* Duron 670 is valid */
if ((c->x86_model==7) && (c->x86_mask==0))
goto valid_k7;
/* Athlon 662, Duron 671, and Athlon >model 7 have capability bit */
if (((c->x86_model==6) && (c->x86_mask>=2)) ||
((c->x86_model==7) && (c->x86_mask>=1)) ||
(c->x86_model> 7))
if (cpu_has_mp)
goto valid_k7;
/* If we get here, it's not a certified SMP capable AMD system. */
printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
tainted |= TAINT_UNSAFE_SMP;
}
valid_k7:
} }
/* /*
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ /* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
/* Don't duplicate feature flags which are redundant with Intel! */ /* Don't duplicate feature flags which are redundant with Intel! */
#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ #define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */
#define X86_FEATURE_MP (1*32+19) /* MP Capable. */
#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ #define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ #define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
......
...@@ -90,6 +90,7 @@ extern struct cpuinfo_x86 cpu_data[]; ...@@ -90,6 +90,7 @@ extern struct cpuinfo_x86 cpu_data[];
#define cpu_has_xmm (test_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability)) #define cpu_has_xmm (test_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability))
#define cpu_has_fpu (test_bit(X86_FEATURE_FPU, boot_cpu_data.x86_capability)) #define cpu_has_fpu (test_bit(X86_FEATURE_FPU, boot_cpu_data.x86_capability))
#define cpu_has_apic (test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) #define cpu_has_apic (test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability))
#define cpu_has_mp (test_bit(X86_FEATURE_MP, boot_cpu_data.x86_capability))
extern char ignore_irq13; extern char ignore_irq13;
......
...@@ -91,6 +91,9 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in ...@@ -91,6 +91,9 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in
extern int tainted; extern int tainted;
extern const char *print_tainted(void); extern const char *print_tainted(void);
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
#if DEBUG #if DEBUG
#define pr_debug(fmt,arg...) \ #define pr_debug(fmt,arg...) \
......
...@@ -103,6 +103,10 @@ NORET_TYPE void panic(const char * fmt, ...) ...@@ -103,6 +103,10 @@ NORET_TYPE void panic(const char * fmt, ...)
/** /**
* print_tainted - return a string to represent the kernel taint state. * print_tainted - return a string to represent the kernel taint state.
* *
* 'P' - Proprietory module has been loaded.
* 'F' - Module has been forcibly loaded.
* 'S' - SMP with CPUs not designed for SMP.
*
* The string is overwritten by the next call to print_taint(). * The string is overwritten by the next call to print_taint().
*/ */
...@@ -110,9 +114,10 @@ const char *print_tainted() ...@@ -110,9 +114,10 @@ const char *print_tainted()
{ {
static char buf[20]; static char buf[20];
if (tainted) { if (tainted) {
snprintf(buf, sizeof(buf), "Tainted: %c%c", snprintf(buf, sizeof(buf), "Tainted: %c%c%c",
tainted & 1 ? 'P' : 'G', tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
tainted & 2 ? 'F' : ' '); tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
} }
else else
snprintf(buf, sizeof(buf), "Not tainted"); snprintf(buf, sizeof(buf), "Not tainted");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment