x86: fix setup code crashes on my old 486 box
authorJoerg Roedel <joro@8bytes.org>
Wed, 13 Aug 2008 08:07:05 +0000 (10:07 +0200)
committerIngo Molnar <mingo@elte.hu>
Wed, 13 Aug 2008 09:59:18 +0000 (11:59 +0200)
yesterday I tried to reactivate my old 486 box and wanted to install a
current Linux with latest kernel on it. But it turned out that the
latest kernel does not boot because the machine crashes early in the
setup code.

After some debugging it turned out that the problem is the query_ist()
function. If this interrupt with that function is called the machine
simply locks up. It looks like a BIOS bug. Looking for a workaround for
this problem I wrote the attached patch. It checks for the CPUID
instruction and if it is not implemented it does not call the speedstep
BIOS function. As far as I know speedstep should be available since some
Pentium earliest.

Alan Cox observed that it's available since the Pentium II, so cpuid
levels 4 and 5 can be excluded altogether.

H. Peter Anvin cleaned up the code some more:

> Right in concept, but I dislike the implementation (duplication of the
> CPU detect code we already have).  Could you try this patch and see if
> it works for you?

which, with a small modification to fix a build error with it the
resulting kernel boots on my machine.

Signed-off-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: <stable@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/boot/boot.h
arch/x86/boot/cpucheck.c
arch/x86/boot/main.c

index a34b9982c7cbcf928bd96e3b17955a789f226f57..9d4b4b43d97af59f6ed45d8680b8d58a04469c5c 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/boot.h>
 #include <asm/setup.h>
 
+#define NCAPINTS   8
+
 /* Useful macros */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
 
@@ -242,6 +244,12 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize);
 int cmdline_find_option_bool(const char *option);
 
 /* cpu.c, cpucheck.c */
+struct cpu_features {
+       int level;              /* Family, or 64 for x86-64 */
+       int model;
+       u32 flags[NCAPINTS];
+};
+extern struct cpu_features cpu;
 int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
 int validate_cpu(void);
 
index 7804389ee0059eb8f4be589cccd24a2623f9567f..c1ce0303d994206faa386226dcba435dbba2aa97 100644 (file)
 #include <asm/required-features.h>
 #include <asm/msr-index.h>
 
-struct cpu_features {
-       int level;              /* Family, or 64 for x86-64 */
-       int model;
-       u32 flags[NCAPINTS];
-};
-
-static struct cpu_features cpu;
+struct cpu_features cpu;
 static u32 cpu_vendor[3];
 static u32 err_flags[NCAPINTS];
 
index 2296164b54d2abc3ad8edc343af2b76c830d6693..01aa64b5575bab043cd43df70b3f0ebedfe05025 100644 (file)
@@ -73,6 +73,10 @@ static void keyboard_set_repeat(void)
  */
 static void query_ist(void)
 {
+       /* Some 486 BIOSes apparently crash on this call */
+       if (cpu.level < 6)
+               return;
+
        asm("int $0x15"
            : "=a" (boot_params.ist_info.signature),
              "=b" (boot_params.ist_info.command),