Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7f81c94 authored by Andi Kleen's avatar Andi Kleen Committed by Andi Kleen
Browse files

[PATCH] i386: Verify important CPUID bits in real mode



Check some CPUID bits that are needed for compiler generated early in boot.
When the system is still in real mode before changing the VESA BIOS mode
it is possible to still display an visible error message on the screen.

Similar to x86-64.

Includes cleanups from Eric Biederman

Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 484ad393
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -240,14 +240,19 @@ config X86_L1_CACHE_SHIFT
	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
	default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7

config X86_XADD
	bool
	depends on !M386
	default y

config RWSEM_GENERIC_SPINLOCK
	bool
	depends on M386
	depends on !X86_XADD
	default y

config RWSEM_XCHGADD_ALGORITHM
	bool
	depends on !M386
	depends on X86_XADD
	default y

config ARCH_HAS_ILOG2_U32
@@ -331,3 +336,16 @@ config X86_TSC
	bool
	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
	default y

# this should be set for all -march=.. options where the compiler
# generates cmov.
config X86_CMOV
	bool
	depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
	default y

config X86_MINIMUM_CPU_MODEL
	int
	default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP
	default "0"
+17 −0
Original line number Diff line number Diff line
@@ -302,7 +302,24 @@ good_sig:

loader_panic_mess: .string "Wrong loader, giving up..."

# check minimum cpuid
# we do this here because it is the last place we can actually
# show a user visible error message. Later the video modus
# might be already messed up.
loader_ok:
	call verify_cpu
	testl  %eax,%eax
	jz	cpu_ok
	lea	cpu_panic_mess,%si
	call	prtstr
1:	jmp	1b

cpu_panic_mess:
	.asciz  "PANIC: CPU too old for this kernel."

#include "../kernel/verify_cpu.S"

cpu_ok:
# Get memory size (extended mem, kB)

	xorl	%eax, %eax
+65 −0
Original line number Diff line number Diff line
/* Check if CPU has some minimum CPUID bits
   This runs in 16bit mode so that the caller can still use the BIOS
   to output errors on the screen */
#include <asm/cpufeature.h>

verify_cpu:
	pushfl				# Save caller passed flags
	pushl	$0			# Kill any dangerous flags
	popfl

#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
	pushfl
	orl	$(1<<18),(%esp)		# try setting AC
	popfl
	pushfl
	popl    %eax
	testl	$(1<<18),%eax
	jz	bad
#endif
#if REQUIRED_MASK1 != 0
	pushfl				# standard way to check for cpuid
	popl	%eax
	movl	%eax,%ebx
	xorl	$0x200000,%eax
	pushl	%eax
	popfl
	pushfl
	popl	%eax
	cmpl	%eax,%ebx
	pushfl				# standard way to check for cpuid
	popl	%eax
	movl	%eax,%ebx
	xorl	$0x200000,%eax
	pushl	%eax
	popfl
	pushfl
	popl	%eax
	cmpl	%eax,%ebx
	jz	bad			# REQUIRED_MASK1 != 0 requires CPUID

	movl	$0x0,%eax		# See if cpuid 1 is implemented
	cpuid
	cmpl	$0x1,%eax
	jb	bad			# no cpuid 1

	movl    $0x1,%eax		# Does the cpu have what it takes
	cpuid

#if CONFIG_X86_MINIMUM_CPU_MODEL > 4
#error	add proper model checking here
#endif

	andl	$REQUIRED_MASK1,%edx
	xorl	$REQUIRED_MASK1,%edx
	jnz	bad
#endif /* REQUIRED_MASK1 */

	popfl
	xor	%eax,%eax
	ret

bad:
	popfl
	movl	$1,%eax
	ret
+3 −0
Original line number Diff line number Diff line
@@ -7,7 +7,10 @@
#ifndef __ASM_I386_CPUFEATURE_H
#define __ASM_I386_CPUFEATURE_H

#ifndef __ASSEMBLY__
#include <linux/bitops.h>
#endif
#include <asm/required-features.h>

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

+34 −0
Original line number Diff line number Diff line
#ifndef _ASM_REQUIRED_FEATURES_H
#define _ASM_REQUIRED_FEATURES_H 1

/* Define minimum CPUID feature set for kernel These bits are checked
   really early to actually display a visible error message before the
   kernel dies.  Only add word 0 bits here

   Some requirements that are not in CPUID yet are also in the
   CONFIG_X86_MINIMUM_CPU mode which is checked too.

   The real information is in arch/i386/Kconfig.cpu, this just converts
   the CONFIGs into a bitmask */

#ifdef CONFIG_X86_PAE
#define NEED_PAE	(1<<X86_FEATURE_PAE)
#else
#define NEED_PAE	0
#endif

#ifdef CONFIG_X86_CMOV
#define NEED_CMOV	(1<<X86_FEATURE_CMOV)
#else
#define NEED_CMOV	0
#endif

#ifdef CONFIG_X86_CMPXCHG64
#define NEED_CMPXCHG64  (1<<X86_FEATURE_CX8)
#else
#define NEED_CMPXCHG64  0
#endif

#define REQUIRED_MASK1	(NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)

#endif