xref: /OK3568_Linux_fs/u-boot/arch/x86/include/asm/cpu.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2014 The Chromium OS Authors.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Part of this file is adapted from coreboot
5*4882a593Smuzhiyun  * src/arch/x86/include/arch/cpu.h and
6*4882a593Smuzhiyun  * src/arch/x86/lib/cpu.c
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #ifndef _ASM_CPU_H
12*4882a593Smuzhiyun #define _ASM_CPU_H
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun enum {
15*4882a593Smuzhiyun 	X86_VENDOR_INVALID = 0,
16*4882a593Smuzhiyun 	X86_VENDOR_INTEL,
17*4882a593Smuzhiyun 	X86_VENDOR_CYRIX,
18*4882a593Smuzhiyun 	X86_VENDOR_AMD,
19*4882a593Smuzhiyun 	X86_VENDOR_UMC,
20*4882a593Smuzhiyun 	X86_VENDOR_NEXGEN,
21*4882a593Smuzhiyun 	X86_VENDOR_CENTAUR,
22*4882a593Smuzhiyun 	X86_VENDOR_RISE,
23*4882a593Smuzhiyun 	X86_VENDOR_TRANSMETA,
24*4882a593Smuzhiyun 	X86_VENDOR_NSC,
25*4882a593Smuzhiyun 	X86_VENDOR_SIS,
26*4882a593Smuzhiyun 	X86_VENDOR_ANY = 0xfe,
27*4882a593Smuzhiyun 	X86_VENDOR_UNKNOWN = 0xff
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* Global descriptor table (GDT) bits */
31*4882a593Smuzhiyun enum {
32*4882a593Smuzhiyun 	GDT_4KB			= 1ULL << 55,
33*4882a593Smuzhiyun 	GDT_32BIT		= 1ULL << 54,
34*4882a593Smuzhiyun 	GDT_LONG		= 1ULL << 53,
35*4882a593Smuzhiyun 	GDT_PRESENT		= 1ULL << 47,
36*4882a593Smuzhiyun 	GDT_NOTSYS		= 1ULL << 44,
37*4882a593Smuzhiyun 	GDT_CODE		= 1ULL << 43,
38*4882a593Smuzhiyun 	GDT_LIMIT_LOW_SHIFT	= 0,
39*4882a593Smuzhiyun 	GDT_LIMIT_LOW_MASK	= 0xffff,
40*4882a593Smuzhiyun 	GDT_LIMIT_HIGH_SHIFT	= 48,
41*4882a593Smuzhiyun 	GDT_LIMIT_HIGH_MASK	= 0xf,
42*4882a593Smuzhiyun 	GDT_BASE_LOW_SHIFT	= 16,
43*4882a593Smuzhiyun 	GDT_BASE_LOW_MASK	= 0xffff,
44*4882a593Smuzhiyun 	GDT_BASE_HIGH_SHIFT	= 56,
45*4882a593Smuzhiyun 	GDT_BASE_HIGH_MASK	= 0xf,
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun  * System controllers in an x86 system. We mostly need to just find these and
50*4882a593Smuzhiyun  * use them on PCI. At some point these might have their own uclass (e.g.
51*4882a593Smuzhiyun  * UCLASS_VIDEO for the GMA device).
52*4882a593Smuzhiyun  */
53*4882a593Smuzhiyun enum {
54*4882a593Smuzhiyun 	X86_NONE,
55*4882a593Smuzhiyun 	X86_SYSCON_ME,		/* Intel Management Engine */
56*4882a593Smuzhiyun 	X86_SYSCON_PINCONF,	/* Intel x86 pin configuration */
57*4882a593Smuzhiyun 	X86_SYSCON_PMU,		/* Power Management Unit */
58*4882a593Smuzhiyun 	X86_SYSCON_SCU,		/* System Controller Unit */
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct cpuid_result {
62*4882a593Smuzhiyun 	uint32_t eax;
63*4882a593Smuzhiyun 	uint32_t ebx;
64*4882a593Smuzhiyun 	uint32_t ecx;
65*4882a593Smuzhiyun 	uint32_t edx;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun  * Generic CPUID function
70*4882a593Smuzhiyun  */
cpuid(int op)71*4882a593Smuzhiyun static inline struct cpuid_result cpuid(int op)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct cpuid_result result;
74*4882a593Smuzhiyun 	asm volatile(
75*4882a593Smuzhiyun 		"mov %%ebx, %%edi;"
76*4882a593Smuzhiyun 		"cpuid;"
77*4882a593Smuzhiyun 		"mov %%ebx, %%esi;"
78*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
79*4882a593Smuzhiyun 		: "=a" (result.eax),
80*4882a593Smuzhiyun 		  "=S" (result.ebx),
81*4882a593Smuzhiyun 		  "=c" (result.ecx),
82*4882a593Smuzhiyun 		  "=d" (result.edx)
83*4882a593Smuzhiyun 		: "0" (op)
84*4882a593Smuzhiyun 		: "edi");
85*4882a593Smuzhiyun 	return result;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun  * Generic Extended CPUID function
90*4882a593Smuzhiyun  */
cpuid_ext(int op,unsigned ecx)91*4882a593Smuzhiyun static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	struct cpuid_result result;
94*4882a593Smuzhiyun 	asm volatile(
95*4882a593Smuzhiyun 		"mov %%ebx, %%edi;"
96*4882a593Smuzhiyun 		"cpuid;"
97*4882a593Smuzhiyun 		"mov %%ebx, %%esi;"
98*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
99*4882a593Smuzhiyun 		: "=a" (result.eax),
100*4882a593Smuzhiyun 		  "=S" (result.ebx),
101*4882a593Smuzhiyun 		  "=c" (result.ecx),
102*4882a593Smuzhiyun 		  "=d" (result.edx)
103*4882a593Smuzhiyun 		: "0" (op), "2" (ecx)
104*4882a593Smuzhiyun 		: "edi");
105*4882a593Smuzhiyun 	return result;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /*
109*4882a593Smuzhiyun  * CPUID functions returning a single datum
110*4882a593Smuzhiyun  */
cpuid_eax(unsigned int op)111*4882a593Smuzhiyun static inline unsigned int cpuid_eax(unsigned int op)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	unsigned int eax;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	__asm__("mov %%ebx, %%edi;"
116*4882a593Smuzhiyun 		"cpuid;"
117*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
118*4882a593Smuzhiyun 		: "=a" (eax)
119*4882a593Smuzhiyun 		: "0" (op)
120*4882a593Smuzhiyun 		: "ecx", "edx", "edi");
121*4882a593Smuzhiyun 	return eax;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
cpuid_ebx(unsigned int op)124*4882a593Smuzhiyun static inline unsigned int cpuid_ebx(unsigned int op)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	unsigned int eax, ebx;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	__asm__("mov %%ebx, %%edi;"
129*4882a593Smuzhiyun 		"cpuid;"
130*4882a593Smuzhiyun 		"mov %%ebx, %%esi;"
131*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
132*4882a593Smuzhiyun 		: "=a" (eax), "=S" (ebx)
133*4882a593Smuzhiyun 		: "0" (op)
134*4882a593Smuzhiyun 		: "ecx", "edx", "edi");
135*4882a593Smuzhiyun 	return ebx;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
cpuid_ecx(unsigned int op)138*4882a593Smuzhiyun static inline unsigned int cpuid_ecx(unsigned int op)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	unsigned int eax, ecx;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	__asm__("mov %%ebx, %%edi;"
143*4882a593Smuzhiyun 		"cpuid;"
144*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
145*4882a593Smuzhiyun 		: "=a" (eax), "=c" (ecx)
146*4882a593Smuzhiyun 		: "0" (op)
147*4882a593Smuzhiyun 		: "edx", "edi");
148*4882a593Smuzhiyun 	return ecx;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
cpuid_edx(unsigned int op)151*4882a593Smuzhiyun static inline unsigned int cpuid_edx(unsigned int op)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	unsigned int eax, edx;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	__asm__("mov %%ebx, %%edi;"
156*4882a593Smuzhiyun 		"cpuid;"
157*4882a593Smuzhiyun 		"mov %%edi, %%ebx;"
158*4882a593Smuzhiyun 		: "=a" (eax), "=d" (edx)
159*4882a593Smuzhiyun 		: "0" (op)
160*4882a593Smuzhiyun 		: "ecx", "edi");
161*4882a593Smuzhiyun 	return edx;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(X86_64)
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun /* Standard macro to see if a specific flag is changeable */
flag_is_changeable_p(uint32_t flag)167*4882a593Smuzhiyun static inline int flag_is_changeable_p(uint32_t flag)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	uint32_t f1, f2;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	asm(
172*4882a593Smuzhiyun 		"pushfl\n\t"
173*4882a593Smuzhiyun 		"pushfl\n\t"
174*4882a593Smuzhiyun 		"popl %0\n\t"
175*4882a593Smuzhiyun 		"movl %0,%1\n\t"
176*4882a593Smuzhiyun 		"xorl %2,%0\n\t"
177*4882a593Smuzhiyun 		"pushl %0\n\t"
178*4882a593Smuzhiyun 		"popfl\n\t"
179*4882a593Smuzhiyun 		"pushfl\n\t"
180*4882a593Smuzhiyun 		"popl %0\n\t"
181*4882a593Smuzhiyun 		"popfl\n\t"
182*4882a593Smuzhiyun 		: "=&r" (f1), "=&r" (f2)
183*4882a593Smuzhiyun 		: "ir" (flag));
184*4882a593Smuzhiyun 	return ((f1^f2) & flag) != 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun #endif
187*4882a593Smuzhiyun 
mfence(void)188*4882a593Smuzhiyun static inline void mfence(void)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	__asm__ __volatile__("mfence" : : : "memory");
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun /**
194*4882a593Smuzhiyun  * cpu_enable_paging_pae() - Enable PAE-paging
195*4882a593Smuzhiyun  *
196*4882a593Smuzhiyun  * @cr3:	Value to set in cr3 (PDPT or PML4T)
197*4882a593Smuzhiyun  */
198*4882a593Smuzhiyun void cpu_enable_paging_pae(ulong cr3);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /**
201*4882a593Smuzhiyun  * cpu_disable_paging_pae() - Disable paging and PAE
202*4882a593Smuzhiyun  */
203*4882a593Smuzhiyun void cpu_disable_paging_pae(void);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun /**
206*4882a593Smuzhiyun  * cpu_has_64bit() - Check if the CPU has 64-bit support
207*4882a593Smuzhiyun  *
208*4882a593Smuzhiyun  * @return 1 if this CPU supports long mode (64-bit), 0 if not
209*4882a593Smuzhiyun  */
210*4882a593Smuzhiyun int cpu_has_64bit(void);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun /**
213*4882a593Smuzhiyun  * cpu_vendor_name() - Get CPU vendor name
214*4882a593Smuzhiyun  *
215*4882a593Smuzhiyun  * @vendor:	CPU vendor enumeration number
216*4882a593Smuzhiyun  *
217*4882a593Smuzhiyun  * @return:	Address to hold the CPU vendor name string
218*4882a593Smuzhiyun  */
219*4882a593Smuzhiyun const char *cpu_vendor_name(int vendor);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun #define CPU_MAX_NAME_LEN	49
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /**
224*4882a593Smuzhiyun  * cpu_get_name() - Get the name of the current cpu
225*4882a593Smuzhiyun  *
226*4882a593Smuzhiyun  * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
227*4882a593Smuzhiyun  * @return pointer to name, which will likely be a few bytes after the start
228*4882a593Smuzhiyun  * of @name
229*4882a593Smuzhiyun  * \0 terminator
230*4882a593Smuzhiyun  */
231*4882a593Smuzhiyun char *cpu_get_name(char *name);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /**
234*4882a593Smuzhiyun  * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
235*4882a593Smuzhiyun  *
236*4882a593Smuzhiyun  * The kernel is uncompressed and the 64-bit entry point is expected to be
237*4882a593Smuzhiyun  * at @target.
238*4882a593Smuzhiyun  *
239*4882a593Smuzhiyun  * This function is used internally - see cpu_jump_to_64bit() for a more
240*4882a593Smuzhiyun  * useful function.
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  * @pgtable:	Address of 24KB area containing the page table
243*4882a593Smuzhiyun  * @setup_base:	Pointer to the setup.bin information for the kernel
244*4882a593Smuzhiyun  * @target:	Pointer to the start of the kernel image
245*4882a593Smuzhiyun  */
246*4882a593Smuzhiyun void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun /**
249*4882a593Smuzhiyun  * cpu_call32() - Jump to a 32-bit entry point
250*4882a593Smuzhiyun  *
251*4882a593Smuzhiyun  * @code_seg32:	32-bit code segment to use (GDT offset, e.g. 0x20)
252*4882a593Smuzhiyun  * @target:	Pointer to the start of the 32-bit U-Boot image/entry point
253*4882a593Smuzhiyun  * @table:	Pointer to start of info table to pass to U-Boot
254*4882a593Smuzhiyun  */
255*4882a593Smuzhiyun void cpu_call32(ulong code_seg32, ulong target, ulong table);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun /**
258*4882a593Smuzhiyun  * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  * The kernel is uncompressed and the 64-bit entry point is expected to be
261*4882a593Smuzhiyun  * at @target.
262*4882a593Smuzhiyun  *
263*4882a593Smuzhiyun  * @setup_base:	Pointer to the setup.bin information for the kernel
264*4882a593Smuzhiyun  * @target:	Pointer to the start of the kernel image
265*4882a593Smuzhiyun  */
266*4882a593Smuzhiyun int cpu_jump_to_64bit(ulong setup_base, ulong target);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /**
269*4882a593Smuzhiyun  * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot
270*4882a593Smuzhiyun  *
271*4882a593Smuzhiyun  * This handles calling from 32-bit SPL to 64-bit U-Boot.
272*4882a593Smuzhiyun  *
273*4882a593Smuzhiyun  * @target:	Address of U-Boot in RAM
274*4882a593Smuzhiyun  */
275*4882a593Smuzhiyun int cpu_jump_to_64bit_uboot(ulong target);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun /**
278*4882a593Smuzhiyun  * cpu_get_family_model() - Get the family and model for the CPU
279*4882a593Smuzhiyun  *
280*4882a593Smuzhiyun  * @return the CPU ID masked with 0x0fff0ff0
281*4882a593Smuzhiyun  */
282*4882a593Smuzhiyun u32 cpu_get_family_model(void);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun /**
285*4882a593Smuzhiyun  * cpu_get_stepping() - Get the stepping value for the CPU
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  * @return the CPU ID masked with 0xf
288*4882a593Smuzhiyun  */
289*4882a593Smuzhiyun u32 cpu_get_stepping(void);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun #endif
292