/* -*- linux-c -*- ------------------------------------------------------- *
 *
 *   Copyright (C) 1991, 1992 Linus Torvalds
 *   Copyright 2007 rPath, Inc. - All Rights Reserved
 *
 *   This file is part of the Linux kernel, and is made available under
 *   the terms of the GNU General Public License version 2.
 *
 * ----------------------------------------------------------------------- */

/*
 * arch/i386/boot/cpucheck.c
 *
 * Check for obligatory CPU features and abort if the features are not
 * present.  This code should be compilable as 16-, 32- or 64-bit
 * code, so be very careful with types and inline assembly.
 *
 * This code should not contain any messages; that requires an
 * additional wrapper.
 *
 * As written, this code is not safe for inclusion into the kernel
 * proper (after FPU initialization, in particular).
 */

#ifdef _SETUP
# include "boot.h"
# include "bitops.h"
#endif
#include <linux/types.h>
#include <asm/cpufeature.h>
#include <asm/processor-flags.h>
#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;
static u32 cpu_vendor[3];
static u32 err_flags[NCAPINTS];

#ifdef CONFIG_X86_64
static const int req_level = 64;
#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
#else
static const int req_level = 3;
#endif

static const u32 req_flags[NCAPINTS] =
{
	REQUIRED_MASK0,
	REQUIRED_MASK1,
	REQUIRED_MASK2,
	REQUIRED_MASK3,
	REQUIRED_MASK4,
	REQUIRED_MASK5,
	REQUIRED_MASK6,
	REQUIRED_MASK7,
};

#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))

static int is_amd(void)
{
	return cpu_vendor[0] == A32('A','u','t','h') &&
	       cpu_vendor[1] == A32('e','n','t','i') &&
	       cpu_vendor[2] == A32('c','A','M','D');
}

static int is_centaur(void)
{
	return cpu_vendor[0] == A32('C','e','n','t') &&
	       cpu_vendor[1] == A32('a','u','r','H') &&
	       cpu_vendor[2] == A32('a','u','l','s');
}

static int is_transmeta(void)
{
	return cpu_vendor[0] == A32('G','e','n','u') &&
	       cpu_vendor[1] == A32('i','n','e','T') &&
	       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("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)
{
	u32 err;
	int i;

	err = 0;
	for (i = 0; i < NCAPINTS; i++) {
		err_flags[i] = req_flags[i] & ~cpu.flags[i];
		if (err_flags[i])
			err |= 1 << i;
	}

	return err;
}

/*
 * Returns -1 on error.
 *
 * *cpu_level is set to the current CPU level; *req_level to the required
 * level.  x86-64 is considered level 64 for this purpose.
 *
 * *err_flags_ptr is set to the flags error array if there are flags missing.
 */
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
{
	int err;

	memset(&cpu.flags, 0, sizeof cpu.flags);
	cpu.level = 3;

	if (has_eflag(X86_EFLAGS_AC))
		cpu.level = 4;

	get_flags();
	err = check_flags();

	if (test_bit(X86_FEATURE_LM, cpu.flags))
		cpu.level = 64;

	if (err == 0x01 &&
	    !(err_flags[0] &
	      ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) &&
	    is_amd()) {
		/* If this is an AMD and we're only missing SSE+SSE2, try to
		   turn them on */

		u32 ecx = MSR_K7_HWCR;
		u32 eax, edx;

		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
		eax &= ~(1 << 15);
		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));

		get_flags();	/* Make sure it really did something */
		err = check_flags();
	} else if (err == 0x01 &&
		   !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
		   is_centaur() && cpu.model >= 6) {
		/* If this is a VIA C3, we might have to enable CX8
		   explicitly */

		u32 ecx = MSR_VIA_FCR;
		u32 eax, edx;

		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
		eax |= (1<<1)|(1<<7);
		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));

		set_bit(X86_FEATURE_CX8, cpu.flags);
		err = check_flags();
	} else if (err == 0x01 && is_transmeta()) {
		/* Transmeta might have masked feature bits in word 0 */

		u32 ecx = 0x80860004;
		u32 eax, edx;
		u32 level = 1;

		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
		asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
		asm("cpuid"
		    : "+a" (level), "=d" (cpu.flags[0])
		    : : "ecx", "ebx");
		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));

		err = check_flags();
	}

	if (err_flags_ptr)
		*err_flags_ptr = err ? err_flags : NULL;
	if (cpu_level_ptr)
		*cpu_level_ptr = cpu.level;
	if (req_level_ptr)
		*req_level_ptr = req_level;

	return (cpu.level < req_level || err) ? -1 : 0;
}
