microcode.h 4.4 KB
Newer Older
H
H. Peter Anvin 已提交
1 2
#ifndef _ASM_X86_MICROCODE_H
#define _ASM_X86_MICROCODE_H
3

4
#include <asm/cpu.h>
5
#include <linux/earlycpio.h>
6
#include <linux/initrd.h>
7

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#define native_rdmsr(msr, val1, val2)			\
do {							\
	u64 __val = native_read_msr((msr));		\
	(void)((val1) = (u32)__val);			\
	(void)((val2) = (u32)(__val >> 32));		\
} while (0)

#define native_wrmsr(msr, low, high)			\
	native_write_msr(msr, low, high)

#define native_wrmsrl(msr, val)				\
	native_write_msr((msr),				\
			 (u32)((u64)(val)),		\
			 (u32)((u64)(val) >> 32))

23 24 25 26 27
struct cpu_signature {
	unsigned int sig;
	unsigned int pf;
	unsigned int rev;
};
P
Peter Oruba 已提交
28

D
Dmitry Adamushko 已提交
29
struct device;
30

31 32
enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };

33
struct microcode_ops {
34 35
	enum ucode_state (*request_microcode_user) (int cpu,
				const void __user *buf, size_t size);
D
Dmitry Adamushko 已提交
36

37 38
	enum ucode_state (*request_microcode_fw) (int cpu, struct device *,
						  bool refresh_fw);
D
Dmitry Adamushko 已提交
39 40

	void (*microcode_fini_cpu) (int cpu);
41 42 43 44 45 46 47 48 49

	/*
	 * The generic 'microcode_core' part guarantees that
	 * the callbacks below run on a target cpu when they
	 * are being called.
	 * See also the "Synchronization" section in microcode_core.c.
	 */
	int (*apply_microcode) (int cpu);
	int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
50 51
};

52
struct ucode_cpu_info {
53 54 55
	struct cpu_signature	cpu_sig;
	int			valid;
	void			*mc;
56
};
57 58
extern struct ucode_cpu_info ucode_cpu_info[];

59 60 61 62 63 64
#ifdef CONFIG_MICROCODE
int __init microcode_init(void);
#else
static inline int __init microcode_init(void)	{ return 0; };
#endif

65 66 67 68 69 70 71 72 73 74 75
#ifdef CONFIG_MICROCODE_INTEL
extern struct microcode_ops * __init init_intel_microcode(void);
#else
static inline struct microcode_ops * __init init_intel_microcode(void)
{
	return NULL;
}
#endif /* CONFIG_MICROCODE_INTEL */

#ifdef CONFIG_MICROCODE_AMD
extern struct microcode_ops * __init init_amd_microcode(void);
76
extern void __exit exit_amd_microcode(void);
77 78 79 80 81
#else
static inline struct microcode_ops * __init init_amd_microcode(void)
{
	return NULL;
}
82
static inline void __exit exit_amd_microcode(void) {}
83 84
#endif

85
#define MAX_UCODE_COUNT 128
86 87 88 89 90 91 92 93 94 95 96 97 98 99

#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I')
#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l')
#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h')
#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i')
#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D')

#define CPUID_IS(a, b, c, ebx, ecx, edx)	\
		(!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c))))

/*
 * In early loading microcode phase on BSP, boot_cpu_data is not set up yet.
100
 * x86_cpuid_vendor() gets vendor id for BSP.
101 102
 *
 * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify
103
 * coding, we still use x86_cpuid_vendor() to get vendor id for AP.
104
 *
105
 * x86_cpuid_vendor() gets vendor information directly from CPUID.
106
 */
107
static inline int x86_cpuid_vendor(void)
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
{
	u32 eax = 0x00000000;
	u32 ebx, ecx = 0, edx;

	native_cpuid(&eax, &ebx, &ecx, &edx);

	if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
		return X86_VENDOR_INTEL;

	if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx))
		return X86_VENDOR_AMD;

	return X86_VENDOR_UNKNOWN;
}

123
static inline unsigned int x86_cpuid_family(void)
124 125 126 127 128 129
{
	u32 eax = 0x00000001;
	u32 ebx, ecx = 0, edx;

	native_cpuid(&eax, &ebx, &ecx, &edx);

130
	return x86_family(eax);
131 132
}

133
#ifdef CONFIG_MICROCODE
134
extern void __init load_ucode_bsp(void);
135
extern void load_ucode_ap(void);
136
extern int __init save_microcode_in_initrd(void);
137
void reload_early_microcode(void);
138
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
139
#else
140 141 142 143 144 145
static inline void __init load_ucode_bsp(void)			{ }
static inline void load_ucode_ap(void)				{ }
static inline int __init save_microcode_in_initrd(void)		{ return 0; }
static inline void reload_early_microcode(void)			{ }
static inline bool
get_builtin_firmware(struct cpio_data *cd, const char *name)	{ return false; }
146
#endif
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

static inline unsigned long get_initrd_start(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
	return initrd_start;
#else
	return 0;
#endif
}

static inline unsigned long get_initrd_start_addr(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
#ifdef CONFIG_X86_32
	unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);

	return (unsigned long)__pa_nodebug(*initrd_start_p);
#else
	return get_initrd_start();
#endif
#else /* CONFIG_BLK_DEV_INITRD */
	return 0;
#endif
}

H
H. Peter Anvin 已提交
172
#endif /* _ASM_X86_MICROCODE_H */