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