blob: 5d24c17f8a37c23e1395f12d477c368e11c9b97e [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
Simon Glasse61b6832025-03-15 14:25:44 +0000112static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
113 unsigned int *ecx, unsigned int *edx)
Bin Meng035c1d22014-11-09 22:18:56 +0800114{
Simon Glasse61b6832025-03-15 14:25:44 +0000115 /* ecx is often an input as well as an output. */
116 asm volatile("cpuid"
117 : "=a" (*eax),
118 "=b" (*ebx),
119 "=c" (*ecx),
120 "=d" (*edx)
121 : "0" (*eax), "2" (*ecx)
122 : "memory");
Bin Meng035c1d22014-11-09 22:18:56 +0800123}
124
Simon Glasse61b6832025-03-15 14:25:44 +0000125#define native_cpuid_reg(reg) \
126static inline unsigned int cpuid_##reg(unsigned int op) \
127{ \
128 unsigned int eax = op, ebx, ecx = 0, edx; \
129 \
130 native_cpuid(&eax, &ebx, &ecx, &edx); \
131 \
132 return reg; \
Bin Meng035c1d22014-11-09 22:18:56 +0800133}
Simon Glassd8d9fec2014-10-10 08:21:52 -0600134
Simon Glasse61b6832025-03-15 14:25:44 +0000135/*
136 * Native CPUID functions returning a single datum.
137 */
138native_cpuid_reg(eax)
139native_cpuid_reg(ebx)
140native_cpuid_reg(ecx)
141native_cpuid_reg(edx)
Bin Meng035c1d22014-11-09 22:18:56 +0800142
Simon Glassad00dde2025-03-15 14:25:41 +0000143#if CONFIG_IS_ENABLED(X86_64)
144static inline int flag_is_changeable_p(u32 flag)
145{
146 return 1;
147}
148#else
Bin Meng035c1d22014-11-09 22:18:56 +0800149/* Standard macro to see if a specific flag is changeable */
Simon Glassad00dde2025-03-15 14:25:41 +0000150static inline int flag_is_changeable_p(u32 flag)
Bin Meng035c1d22014-11-09 22:18:56 +0800151{
Simon Glassad00dde2025-03-15 14:25:41 +0000152 u32 f1, f2;
Bin Meng035c1d22014-11-09 22:18:56 +0800153
154 asm(
155 "pushfl\n\t"
156 "pushfl\n\t"
157 "popl %0\n\t"
158 "movl %0,%1\n\t"
159 "xorl %2,%0\n\t"
160 "pushl %0\n\t"
161 "popfl\n\t"
162 "pushfl\n\t"
163 "popl %0\n\t"
164 "popfl\n\t"
165 : "=&r" (f1), "=&r" (f2)
166 : "ir" (flag));
Simon Glassad00dde2025-03-15 14:25:41 +0000167 return ((f1 ^ f2) & flag) != 0;
Bin Meng035c1d22014-11-09 22:18:56 +0800168}
Simon Glassad00dde2025-03-15 14:25:41 +0000169#endif /* X86_64 */
Bin Meng035c1d22014-11-09 22:18:56 +0800170
171/**
Simon Glassd8d9fec2014-10-10 08:21:52 -0600172 * cpu_enable_paging_pae() - Enable PAE-paging
173 *
Bin Meng035c1d22014-11-09 22:18:56 +0800174 * @cr3: Value to set in cr3 (PDPT or PML4T)
Simon Glassd8d9fec2014-10-10 08:21:52 -0600175 */
176void cpu_enable_paging_pae(ulong cr3);
177
178/**
179 * cpu_disable_paging_pae() - Disable paging and PAE
180 */
181void cpu_disable_paging_pae(void);
182
Simon Glass2f2efbc2014-10-10 08:21:54 -0600183/**
184 * cpu_has_64bit() - Check if the CPU has 64-bit support
185 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100186 * Return: 1 if this CPU supports long mode (64-bit), 0 if not
Simon Glass2f2efbc2014-10-10 08:21:54 -0600187 */
188int cpu_has_64bit(void);
189
Simon Glass463fac22014-10-10 08:21:55 -0600190/**
Bin Meng035c1d22014-11-09 22:18:56 +0800191 * cpu_vendor_name() - Get CPU vendor name
192 *
193 * @vendor: CPU vendor enumeration number
194 *
195 * @return: Address to hold the CPU vendor name string
196 */
197const char *cpu_vendor_name(int vendor);
198
Simon Glass543bb142014-11-10 18:00:26 -0700199#define CPU_MAX_NAME_LEN 49
200
Bin Meng035c1d22014-11-09 22:18:56 +0800201/**
Simon Glass543bb142014-11-10 18:00:26 -0700202 * cpu_get_name() - Get the name of the current cpu
Bin Meng035c1d22014-11-09 22:18:56 +0800203 *
Simon Glass543bb142014-11-10 18:00:26 -0700204 * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100205 * Return: pointer to name, which will likely be a few bytes after the start
Simon Glass543bb142014-11-10 18:00:26 -0700206 * of @name
207 * \0 terminator
Bin Meng035c1d22014-11-09 22:18:56 +0800208 */
Simon Glass543bb142014-11-10 18:00:26 -0700209char *cpu_get_name(char *name);
Bin Meng035c1d22014-11-09 22:18:56 +0800210
211/**
Simon Glass463fac22014-10-10 08:21:55 -0600212 * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
213 *
214 * The kernel is uncompressed and the 64-bit entry point is expected to be
215 * at @target.
216 *
217 * This function is used internally - see cpu_jump_to_64bit() for a more
218 * useful function.
219 *
220 * @pgtable: Address of 24KB area containing the page table
221 * @setup_base: Pointer to the setup.bin information for the kernel
222 * @target: Pointer to the start of the kernel image
223 */
224void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
225
226/**
Simon Glassbae81c72015-08-04 12:33:55 -0600227 * cpu_call32() - Jump to a 32-bit entry point
228 *
229 * @code_seg32: 32-bit code segment to use (GDT offset, e.g. 0x20)
230 * @target: Pointer to the start of the 32-bit U-Boot image/entry point
231 * @table: Pointer to start of info table to pass to U-Boot
232 */
233void cpu_call32(ulong code_seg32, ulong target, ulong table);
234
235/**
Simon Glass463fac22014-10-10 08:21:55 -0600236 * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
237 *
238 * The kernel is uncompressed and the 64-bit entry point is expected to be
239 * at @target.
240 *
241 * @setup_base: Pointer to the setup.bin information for the kernel
242 * @target: Pointer to the start of the kernel image
Simon Glass39fd78e2023-03-20 08:30:07 +1300243 * Return: -EFAULT if the kernel returned; otherwise does not return
Simon Glass463fac22014-10-10 08:21:55 -0600244 */
245int cpu_jump_to_64bit(ulong setup_base, ulong target);
246
Simon Glass2f462fd2016-03-11 22:06:52 -0700247/**
Simon Glass1e32ede2017-01-16 07:04:15 -0700248 * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot
249 *
250 * This handles calling from 32-bit SPL to 64-bit U-Boot.
251 *
252 * @target: Address of U-Boot in RAM
253 */
254int cpu_jump_to_64bit_uboot(ulong target);
255
256/**
Simon Glass2f462fd2016-03-11 22:06:52 -0700257 * cpu_get_family_model() - Get the family and model for the CPU
258 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100259 * Return: the CPU ID masked with 0x0fff0ff0
Simon Glass2f462fd2016-03-11 22:06:52 -0700260 */
261u32 cpu_get_family_model(void);
262
263/**
264 * cpu_get_stepping() - Get the stepping value for the CPU
265 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100266 * Return: the CPU ID masked with 0xf
Simon Glass2f462fd2016-03-11 22:06:52 -0700267 */
268u32 cpu_get_stepping(void);
269
Andy Shevchenko6ab207b2024-10-05 22:11:59 +0300270void board_final_init(void);
271void board_final_cleanup(void);
272
273#ifndef CONFIG_EFI_STUB
274int reserve_arch(void);
275#endif
276
Simon Glassd8d9fec2014-10-10 08:21:52 -0600277#endif