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

Commit dd78b973 authored by Kees Cook's avatar Kees Cook Committed by H. Peter Anvin
Browse files

x86, boot: Move CPU flags out of cpucheck



Refactor the CPU flags handling out of the cpucheck routines so that
they can be reused by the future ASLR routines (in order to detect CPU
features like RDRAND and RDTSC).

This reworks has_eflag() and has_fpu() to be used on both 32-bit and
64-bit, and refactors the calls to cpuid to make them PIC-safe on 32-bit.

Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Link: http://lkml.kernel.org/r/1381450698-28710-2-git-send-email-keescook@chromium.org


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent d751c169
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir-		:= compressed

setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o
setup-y		+= early_serial_console.o edd.o header.o main.o mca.o memory.o
setup-y		+= pm.o pmjump.o printf.o regs.o string.o tty.o video.o
setup-y		+= video-mode.o version.o
+1 −9
Original line number Diff line number Diff line
@@ -26,9 +26,8 @@
#include <asm/boot.h>
#include <asm/setup.h>
#include "bitops.h"
#include <asm/cpufeature.h>
#include <asm/processor-flags.h>
#include "ctype.h"
#include "cpuflags.h"

/* Useful macros */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -307,14 +306,7 @@ static inline int cmdline_find_option_bool(const char *option)
	return __cmdline_find_option_bool(cmd_line_ptr, 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);

+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include

VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
	$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
	$(obj)/piggy.o
	$(obj)/piggy.o $(obj)/cpuflags.o

$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone

+12 −0
Original line number Diff line number Diff line
#ifdef CONFIG_RANDOMIZE_BASE

#include "../cpuflags.c"

bool has_cpuflag(int flag)
{
	get_flags();

	return test_bit(flag, cpu.flags);
}

#endif
+0 −86
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@
#include <asm/required-features.h>
#include <asm/msr-index.h>

struct cpu_features cpu;
static u32 cpu_vendor[3];
static u32 err_flags[NCAPINTS];

static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
@@ -69,90 +67,6 @@ static int is_transmeta(void)
	       cpu_vendor[2] == A32('M', 'x', '8', '6');
}

static int has_fpu(void)
{
	u16 fcw = -1, fsw = -1;
	u32 cr0;

	asm("movl %%cr0,%0" : "=r" (cr0));
	if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
		cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
		asm volatile("movl %0,%%cr0" : : "r" (cr0));
	}

	asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
		     : "+m" (fsw), "+m" (fcw));

	return fsw == 0 && (fcw & 0x103f) == 0x003f;
}

static int has_eflag(u32 mask)
{
	u32 f0, f1;

	asm("pushfl ; "
	    "pushfl ; "
	    "popl %0 ; "
	    "movl %0,%1 ; "
	    "xorl %2,%1 ; "
	    "pushl %1 ; "
	    "popfl ; "
	    "pushfl ; "
	    "popl %1 ; "
	    "popfl"
	    : "=&r" (f0), "=&r" (f1)
	    : "ri" (mask));

	return !!((f0^f1) & mask);
}

static void get_flags(void)
{
	u32 max_intel_level, max_amd_level;
	u32 tfms;

	if (has_fpu())
		set_bit(X86_FEATURE_FPU, cpu.flags);

	if (has_eflag(X86_EFLAGS_ID)) {
		asm("cpuid"
		    : "=a" (max_intel_level),
		      "=b" (cpu_vendor[0]),
		      "=d" (cpu_vendor[1]),
		      "=c" (cpu_vendor[2])
		    : "a" (0));

		if (max_intel_level >= 0x00000001 &&
		    max_intel_level <= 0x0000ffff) {
			asm("cpuid"
			    : "=a" (tfms),
			      "=c" (cpu.flags[4]),
			      "=d" (cpu.flags[0])
			    : "a" (0x00000001)
			    : "ebx");
			cpu.level = (tfms >> 8) & 15;
			cpu.model = (tfms >> 4) & 15;
			if (cpu.level >= 6)
				cpu.model += ((tfms >> 16) & 0xf) << 4;
		}

		asm("cpuid"
		    : "=a" (max_amd_level)
		    : "a" (0x80000000)
		    : "ebx", "ecx", "edx");

		if (max_amd_level >= 0x80000001 &&
		    max_amd_level <= 0x8000ffff) {
			u32 eax = 0x80000001;
			asm("cpuid"
			    : "+a" (eax),
			      "=c" (cpu.flags[6]),
			      "=d" (cpu.flags[1])
			    : : "ebx");
		}
	}
}

/* Returns a bitmask of which words we have error bits in */
static int check_flags(void)
{
Loading