blob: 1f1b545ea5071ed404bd7e0659eecc2c475a57da [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Simon Glassd8d9fec2014-10-10 08:21:52 -06002/*
3 * Copyright (c) 2014 The Chromium OS Authors.
4 *
Bin Meng035c1d22014-11-09 22:18:56 +08005 * Part of this file is adapted from coreboot
6 * src/arch/x86/include/arch/cpu.h and
7 * src/arch/x86/lib/cpu.c
Simon Glassd8d9fec2014-10-10 08:21:52 -06008 */
Bin Meng035c1d22014-11-09 22:18:56 +08009
10#ifndef _ASM_CPU_H
11#define _ASM_CPU_H
12
13enum {
14 X86_VENDOR_INVALID = 0,
15 X86_VENDOR_INTEL,
16 X86_VENDOR_CYRIX,
17 X86_VENDOR_AMD,
18 X86_VENDOR_UMC,
19 X86_VENDOR_NEXGEN,
20 X86_VENDOR_CENTAUR,
21 X86_VENDOR_RISE,
22 X86_VENDOR_TRANSMETA,
23 X86_VENDOR_NSC,
24 X86_VENDOR_SIS,
25 X86_VENDOR_ANY = 0xfe,
26 X86_VENDOR_UNKNOWN = 0xff
27};
28
Simon Glassd360b2f2015-08-04 12:33:54 -060029/* Global descriptor table (GDT) bits */
30enum {
31 GDT_4KB = 1ULL << 55,
32 GDT_32BIT = 1ULL << 54,
33 GDT_LONG = 1ULL << 53,
34 GDT_PRESENT = 1ULL << 47,
35 GDT_NOTSYS = 1ULL << 44,
36 GDT_CODE = 1ULL << 43,
37 GDT_LIMIT_LOW_SHIFT = 0,
38 GDT_LIMIT_LOW_MASK = 0xffff,
39 GDT_LIMIT_HIGH_SHIFT = 48,
40 GDT_LIMIT_HIGH_MASK = 0xf,
41 GDT_BASE_LOW_SHIFT = 16,
42 GDT_BASE_LOW_MASK = 0xffff,
43 GDT_BASE_HIGH_SHIFT = 56,
44 GDT_BASE_HIGH_MASK = 0xf,
45};
46
Simon Glass43a50342016-01-17 16:11:58 -070047/*
48 * System controllers in an x86 system. We mostly need to just find these and
Simon Glassa75abeb2016-01-17 16:11:59 -070049 * use them on PCI. At some point these might have their own uclass (e.g.
50 * UCLASS_VIDEO for the GMA device).
Simon Glass43a50342016-01-17 16:11:58 -070051 */
52enum {
53 X86_NONE,
54 X86_SYSCON_ME, /* Intel Management Engine */
Simon Glass11cd6312016-03-11 22:07:13 -070055 X86_SYSCON_PINCONF, /* Intel x86 pin configuration */
Andy Shevchenko7d2c2012017-04-01 16:21:34 +030056 X86_SYSCON_PMU, /* Power Management Unit */
Felipe Balbiee2e85f2017-04-01 16:21:33 +030057 X86_SYSCON_SCU, /* System Controller Unit */
Simon Glass0b3c5762019-10-20 21:37:49 -060058 X86_SYSCON_PUNIT, /* Power unit */
Simon Glass43a50342016-01-17 16:11:58 -070059};
60
Simon Glassad00dde2025-03-15 14:25:41 +000061#define CPUID_FEATURE_PAE BIT(6)
62#define CPUID_FEATURE_PSE36 BIT(17)
63#define CPUID_FEAURE_HTT BIT(28)
64
Bin Meng035c1d22014-11-09 22:18:56 +080065struct cpuid_result {
66 uint32_t eax;
67 uint32_t ebx;
68 uint32_t ecx;
69 uint32_t edx;
70};
71
72/*
73 * Generic CPUID function
74 */
75static inline struct cpuid_result cpuid(int op)
76{
77 struct cpuid_result result;
78 asm volatile(
79 "mov %%ebx, %%edi;"
80 "cpuid;"
81 "mov %%ebx, %%esi;"
82 "mov %%edi, %%ebx;"
83 : "=a" (result.eax),
84 "=S" (result.ebx),
85 "=c" (result.ecx),
86 "=d" (result.edx)
87 : "0" (op)
88 : "edi");
89 return result;
90}
91
92/*
93 * Generic Extended CPUID function
94 */
95static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
96{
97 struct cpuid_result result;
98 asm volatile(
99 "mov %%ebx, %%edi;"
100 "cpuid;"
101 "mov %%ebx, %%esi;"
102 "mov %%edi, %%ebx;"
103 : "=a" (result.eax),
104 "=S" (result.ebx),
105 "=c" (result.ecx),
106 "=d" (result.edx)
107 : "0" (op), "2" (ecx)
108 : "edi");
109 return result;
110}
111
112/*
113 * CPUID functions returning a single datum
114 */
115static inline unsigned int cpuid_eax(unsigned int op)
116{
117 unsigned int eax;
118
119 __asm__("mov %%ebx, %%edi;"
120 "cpuid;"
121 "mov %%edi, %%ebx;"
122 : "=a" (eax)
123 : "0" (op)
124 : "ecx", "edx", "edi");
125 return eax;
126}
127
128static inline unsigned int cpuid_ebx(unsigned int op)
129{
130 unsigned int eax, ebx;
131
132 __asm__("mov %%ebx, %%edi;"
133 "cpuid;"
134 "mov %%ebx, %%esi;"
135 "mov %%edi, %%ebx;"
136 : "=a" (eax), "=S" (ebx)
137 : "0" (op)
138 : "ecx", "edx", "edi");
139 return ebx;
140}
141
142static inline unsigned int cpuid_ecx(unsigned int op)
143{
144 unsigned int eax, ecx;
Simon Glassd8d9fec2014-10-10 08:21:52 -0600145
Bin Meng035c1d22014-11-09 22:18:56 +0800146 __asm__("mov %%ebx, %%edi;"
147 "cpuid;"
148 "mov %%edi, %%ebx;"
149 : "=a" (eax), "=c" (ecx)
150 : "0" (op)
151 : "edx", "edi");
152 return ecx;
153}
Simon Glassd8d9fec2014-10-10 08:21:52 -0600154
Bin Meng035c1d22014-11-09 22:18:56 +0800155static inline unsigned int cpuid_edx(unsigned int op)
156{
157 unsigned int eax, edx;
158
159 __asm__("mov %%ebx, %%edi;"
160 "cpuid;"
161 "mov %%edi, %%ebx;"
162 : "=a" (eax), "=d" (edx)
163 : "0" (op)
164 : "ecx", "edi");
165 return edx;
166}
167
Simon Glassad00dde2025-03-15 14:25:41 +0000168#if CONFIG_IS_ENABLED(X86_64)
169static inline int flag_is_changeable_p(u32 flag)
170{
171 return 1;
172}
173#else
Bin Meng035c1d22014-11-09 22:18:56 +0800174/* Standard macro to see if a specific flag is changeable */
Simon Glassad00dde2025-03-15 14:25:41 +0000175static inline int flag_is_changeable_p(u32 flag)
Bin Meng035c1d22014-11-09 22:18:56 +0800176{
Simon Glassad00dde2025-03-15 14:25:41 +0000177 u32 f1, f2;
Bin Meng035c1d22014-11-09 22:18:56 +0800178
179 asm(
180 "pushfl\n\t"
181 "pushfl\n\t"
182 "popl %0\n\t"
183 "movl %0,%1\n\t"
184 "xorl %2,%0\n\t"
185 "pushl %0\n\t"
186 "popfl\n\t"
187 "pushfl\n\t"
188 "popl %0\n\t"
189 "popfl\n\t"
190 : "=&r" (f1), "=&r" (f2)
191 : "ir" (flag));
Simon Glassad00dde2025-03-15 14:25:41 +0000192 return ((f1 ^ f2) & flag) != 0;
Bin Meng035c1d22014-11-09 22:18:56 +0800193}
Simon Glassad00dde2025-03-15 14:25:41 +0000194#endif /* X86_64 */
Bin Meng035c1d22014-11-09 22:18:56 +0800195
196/**
Simon Glassd8d9fec2014-10-10 08:21:52 -0600197 * cpu_enable_paging_pae() - Enable PAE-paging
198 *
Bin Meng035c1d22014-11-09 22:18:56 +0800199 * @cr3: Value to set in cr3 (PDPT or PML4T)
Simon Glassd8d9fec2014-10-10 08:21:52 -0600200 */
201void cpu_enable_paging_pae(ulong cr3);
202
203/**
204 * cpu_disable_paging_pae() - Disable paging and PAE
205 */
206void cpu_disable_paging_pae(void);
207
Simon Glass2f2efbc2014-10-10 08:21:54 -0600208/**
209 * cpu_has_64bit() - Check if the CPU has 64-bit support
210 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100211 * Return: 1 if this CPU supports long mode (64-bit), 0 if not
Simon Glass2f2efbc2014-10-10 08:21:54 -0600212 */
213int cpu_has_64bit(void);
214
Simon Glass463fac22014-10-10 08:21:55 -0600215/**
Bin Meng035c1d22014-11-09 22:18:56 +0800216 * cpu_vendor_name() - Get CPU vendor name
217 *
218 * @vendor: CPU vendor enumeration number
219 *
220 * @return: Address to hold the CPU vendor name string
221 */
222const char *cpu_vendor_name(int vendor);
223
Simon Glass543bb142014-11-10 18:00:26 -0700224#define CPU_MAX_NAME_LEN 49
225
Bin Meng035c1d22014-11-09 22:18:56 +0800226/**
Simon Glass543bb142014-11-10 18:00:26 -0700227 * cpu_get_name() - Get the name of the current cpu
Bin Meng035c1d22014-11-09 22:18:56 +0800228 *
Simon Glass543bb142014-11-10 18:00:26 -0700229 * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100230 * Return: pointer to name, which will likely be a few bytes after the start
Simon Glass543bb142014-11-10 18:00:26 -0700231 * of @name
232 * \0 terminator
Bin Meng035c1d22014-11-09 22:18:56 +0800233 */
Simon Glass543bb142014-11-10 18:00:26 -0700234char *cpu_get_name(char *name);
Bin Meng035c1d22014-11-09 22:18:56 +0800235
236/**
Simon Glass463fac22014-10-10 08:21:55 -0600237 * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
238 *
239 * The kernel is uncompressed and the 64-bit entry point is expected to be
240 * at @target.
241 *
242 * This function is used internally - see cpu_jump_to_64bit() for a more
243 * useful function.
244 *
245 * @pgtable: Address of 24KB area containing the page table
246 * @setup_base: Pointer to the setup.bin information for the kernel
247 * @target: Pointer to the start of the kernel image
248 */
249void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
250
251/**
Simon Glassbae81c72015-08-04 12:33:55 -0600252 * cpu_call32() - Jump to a 32-bit entry point
253 *
254 * @code_seg32: 32-bit code segment to use (GDT offset, e.g. 0x20)
255 * @target: Pointer to the start of the 32-bit U-Boot image/entry point
256 * @table: Pointer to start of info table to pass to U-Boot
257 */
258void cpu_call32(ulong code_seg32, ulong target, ulong table);
259
260/**
Simon Glass463fac22014-10-10 08:21:55 -0600261 * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
262 *
263 * The kernel is uncompressed and the 64-bit entry point is expected to be
264 * at @target.
265 *
266 * @setup_base: Pointer to the setup.bin information for the kernel
267 * @target: Pointer to the start of the kernel image
Simon Glass39fd78e2023-03-20 08:30:07 +1300268 * Return: -EFAULT if the kernel returned; otherwise does not return
Simon Glass463fac22014-10-10 08:21:55 -0600269 */
270int cpu_jump_to_64bit(ulong setup_base, ulong target);
271
Simon Glass2f462fd2016-03-11 22:06:52 -0700272/**
Simon Glass1e32ede2017-01-16 07:04:15 -0700273 * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot
274 *
275 * This handles calling from 32-bit SPL to 64-bit U-Boot.
276 *
277 * @target: Address of U-Boot in RAM
278 */
279int cpu_jump_to_64bit_uboot(ulong target);
280
281/**
Simon Glass2f462fd2016-03-11 22:06:52 -0700282 * cpu_get_family_model() - Get the family and model for the CPU
283 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100284 * Return: the CPU ID masked with 0x0fff0ff0
Simon Glass2f462fd2016-03-11 22:06:52 -0700285 */
286u32 cpu_get_family_model(void);
287
288/**
289 * cpu_get_stepping() - Get the stepping value for the CPU
290 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100291 * Return: the CPU ID masked with 0xf
Simon Glass2f462fd2016-03-11 22:06:52 -0700292 */
293u32 cpu_get_stepping(void);
294
Andy Shevchenko6ab207b2024-10-05 22:11:59 +0300295void board_final_init(void);
296void board_final_cleanup(void);
297
298#ifndef CONFIG_EFI_STUB
299int reserve_arch(void);
300#endif
301
Simon Glassd8d9fec2014-10-10 08:21:52 -0600302#endif