blob: b7d700fb3946b85b026c510c50246fd0100a688c [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbine0785c02013-10-21 12:15:29 -05002
Aaron Durbin154d2092017-06-16 14:20:10 -05003#include <cpu/x86/cr.h>
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -06004#include <cpu/amd/mtrr.h>
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +02005#include <cpu/x86/msr.h>
Patrick Rudolph776da082019-10-25 08:09:33 +02006#include <arch/ram_segs.h>
Aaron Durbin154d2092017-06-16 14:20:10 -05007
Patrick Rudolpha1695502019-12-01 07:23:59 +01008#define __RAMSTAGE__
Arthur Heymans3edf8402021-07-05 21:18:50 +02009#include <cpu/x86/64bit/entry64.inc>
Patrick Rudolpha1695502019-12-01 07:23:59 +010010
Elyes HAOUASece26962018-08-07 12:24:16 +020011/* The SIPI vector is responsible for initializing the APs in the system. It
Aaron Durbine0785c02013-10-21 12:15:29 -050012 * loads microcode, sets up MSRs, and enables caching before calling into
13 * C code. */
14
Aaron Durbine0785c02013-10-21 12:15:29 -050015.section ".module_parameters", "aw", @progbits
16ap_start_params:
17gdtaddr:
18.word 0 /* limit */
19.long 0 /* table */
20.word 0 /* unused */
21idt_ptr:
22.long 0
Raul E Rangelb2346a52021-09-22 14:56:51 -060023per_cpu_segment_descriptors:
24.long 0
25per_cpu_segment_selector:
26.long 0
Aaron Durbine0785c02013-10-21 12:15:29 -050027stack_top:
28.long 0
29stack_size:
30.long 0
31microcode_lock:
32.long 0
33microcode_ptr:
34.long 0
35msr_table_ptr:
36.long 0
37msr_count:
38.long 0
39c_handler:
40.long 0
Arthur Heymans3cfcffe2024-02-02 17:37:42 +010041cr3:
42.long 0
Aaron Durbine0785c02013-10-21 12:15:29 -050043ap_count:
44.long 0
45
Aaron Durbin154d2092017-06-16 14:20:10 -050046#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
47#define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
48#define CR0_CLEAR_FLAGS \
49 (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
50
Aaron Durbine0785c02013-10-21 12:15:29 -050051.text
52.code16
Aaron Durbindde76292015-09-05 12:59:26 -050053.global _start
54_start:
Aaron Durbine0785c02013-10-21 12:15:29 -050055 cli
56 xorl %eax, %eax
57 movl %eax, %cr3 /* Invalidate TLB*/
58
59 /* On hyper threaded cpus, invalidating the cache here is
60 * very very bad. Don't.
61 */
62
63 /* setup the data segment */
64 movw %cs, %ax
65 movw %ax, %ds
66
Martin Roth0949e732021-10-01 14:28:22 -060067 /* The gdtaddr needs to be relative to the data segment in order
Aaron Durbine0785c02013-10-21 12:15:29 -050068 * to properly dereference it. The .text section comes first in an
Aaron Durbindde76292015-09-05 12:59:26 -050069 * rmodule so _start can be used as a proxy for the load address. */
Aaron Durbine0785c02013-10-21 12:15:29 -050070 movl $(gdtaddr), %ebx
Aaron Durbindde76292015-09-05 12:59:26 -050071 sub $(_start), %ebx
Aaron Durbine0785c02013-10-21 12:15:29 -050072
Edward O'Callaghan4e2294b2017-01-08 19:14:42 +110073 lgdtl (%ebx)
Aaron Durbine0785c02013-10-21 12:15:29 -050074
75 movl %cr0, %eax
Aaron Durbin154d2092017-06-16 14:20:10 -050076 andl $~CR0_CLEAR_FLAGS, %eax
77 orl $CR0_SET_FLAGS, %eax
Aaron Durbine0785c02013-10-21 12:15:29 -050078 movl %eax, %cr0
79
Patrick Rudolph776da082019-10-25 08:09:33 +020080 ljmpl $RAM_CODE_SEG, $1f
Aaron Durbine0785c02013-10-21 12:15:29 -0500811:
82 .code32
Patrick Rudolph776da082019-10-25 08:09:33 +020083 movw $RAM_DATA_SEG, %ax
Aaron Durbine0785c02013-10-21 12:15:29 -050084 movw %ax, %ds
85 movw %ax, %es
86 movw %ax, %ss
Raul E Rangelea5c3112021-09-21 10:17:24 -060087 xor %ax, %ax /* zero out the gs and fs segment index */
Aaron Durbine0785c02013-10-21 12:15:29 -050088 movw %ax, %fs
Raul E Rangelea5c3112021-09-21 10:17:24 -060089 movw %ax, %gs /* Will be used for cpu_info */
Aaron Durbine0785c02013-10-21 12:15:29 -050090
91 /* Load the Interrupt descriptor table */
92 mov idt_ptr, %ebx
93 lidt (%ebx)
94
Aaron Durbine0785c02013-10-21 12:15:29 -0500951:
Patrick Rudolph72c60712020-11-18 13:26:10 +010096 /* Obtain CPU number. */
97 movl ap_count, %ecx
Aaron Durbine0785c02013-10-21 12:15:29 -050098 inc %ecx
99 lock cmpxchg %ecx, ap_count
100 jnz 1b
101
102 /* Setup stacks for each CPU. */
103 movl stack_size, %eax
104 mul %ecx
105 movl stack_top, %edx
106 subl %eax, %edx
107 mov %edx, %esp
Raul E Rangelb2346a52021-09-22 14:56:51 -0600108
Arthur Heymansd4dfc212022-11-10 13:34:49 +0100109 /* Save CPU number for calling the AP entry */
110 push %ecx
Raul E Rangelb2346a52021-09-22 14:56:51 -0600111
Patrick Rudolphce51b342021-01-11 09:21:58 +0100112 /*
113 * The following code only needs to run on Intel platforms and thus the caller
114 * doesn't provide a microcode_ptr if not on Intel.
115 * On Intel platforms which update microcode using FIT the version check will
116 * also skip the microcode update.
117 */
118
Aaron Durbine0785c02013-10-21 12:15:29 -0500119 /* Determine if one should check microcode versions. */
120 mov microcode_ptr, %edi
121 test %edi, %edi
122 jz microcode_done /* Bypass if no microde exists. */
123
124 /* Get the Microcode version. */
Arthur Heymans193aac82021-01-18 19:50:26 +0100125 xorl %eax, %eax
126 xorl %edx, %edx
127 movl $IA32_BIOS_SIGN_ID, %ecx
128 wrmsr
Aaron Durbine0785c02013-10-21 12:15:29 -0500129 mov $1, %eax
130 cpuid
131 mov $IA32_BIOS_SIGN_ID, %ecx
132 rdmsr
133 /* If something already loaded skip loading again. */
134 test %edx, %edx
135 jnz microcode_done
136
Patrick Rudolphce51b342021-01-11 09:21:58 +0100137 /*
138 * Intel SDM and various BWGs specify to use a semaphore to update microcode
139 * on one thread per core on Hyper-Threading enabled CPUs. Due to this complex
140 * code would be necessary to determine the core #ID, initializing and picking
141 * the right semaphore out of CONFIG_MAX_CPUS / 2.
142 * Instead of the per core approachm, as recommended, use one global spinlock.
143 * Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
144 * most 8 threads will ever run into this condition, the boot delay is negligible.
145 */
146
Aaron Durbine0785c02013-10-21 12:15:29 -0500147 /* Determine if parallel microcode loading is allowed. */
Damien Zammit69331512017-09-02 20:30:39 +1000148 cmpl $0xffffffff, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500149 je load_microcode
150
151 /* Protect microcode loading. */
152lock_microcode:
Jacob Garber1627e2f2020-10-28 20:03:53 -0600153 lock btsl $0, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500154 jc lock_microcode
155
156load_microcode:
157 /* Load new microcode. */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200158 mov $IA32_BIOS_UPDT_TRIG, %ecx
Aaron Durbine0785c02013-10-21 12:15:29 -0500159 xor %edx, %edx
160 mov %edi, %eax
161 /* The microcode pointer is passed in pointing to the header. Adjust
162 * pointer to reflect the payload (header size is 48 bytes). */
163 add $48, %eax
164 pusha
165 wrmsr
166 popa
167
168 /* Unconditionally unlock microcode loading. */
Damien Zammit69331512017-09-02 20:30:39 +1000169 cmpl $0xffffffff, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500170 je microcode_done
171
172 xor %eax, %eax
173 mov %eax, microcode_lock
174
175microcode_done:
176 /*
177 * Load MSRs. Each entry in the table consists of:
178 * 0: index,
179 * 4: value[31:0]
180 * 8: value[63:32]
181 */
182 mov msr_table_ptr, %edi
183 mov msr_count, %ebx
184 test %ebx, %ebx
185 jz 1f
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600186
Julius Wernercd49cce2019-03-05 16:53:33 -0800187#if CONFIG(X86_AMD_FIXED_MTRRS)
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600188 /* Allow modification of RdDram and WrDram bits */
189 mov $SYSCFG_MSR, %ecx
190 rdmsr
191 or $SYSCFG_MSR_MtrrFixDramModEn, %eax
192 wrmsr
193#endif
194
Aaron Durbine0785c02013-10-21 12:15:29 -0500195load_msr:
196 mov (%edi), %ecx
197 mov 4(%edi), %eax
198 mov 8(%edi), %edx
199 wrmsr
200 add $12, %edi
201 dec %ebx
202 jnz load_msr
203
Julius Wernercd49cce2019-03-05 16:53:33 -0800204#if CONFIG(X86_AMD_FIXED_MTRRS)
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600205 mov $SYSCFG_MSR, %ecx
206 rdmsr
207 and $~SYSCFG_MSR_MtrrFixDramModEn, %eax
208 wrmsr
209#endif
210
Aaron Durbine0785c02013-10-21 12:15:29 -05002111:
212 /* Enable caching. */
213 mov %cr0, %eax
Aaron Durbin154d2092017-06-16 14:20:10 -0500214 and $~(CR0_CLEAR_FLAGS_CACHE_ENABLE), %eax
Aaron Durbine0785c02013-10-21 12:15:29 -0500215 mov %eax, %cr0
216
Julius Wernercd49cce2019-03-05 16:53:33 -0800217#if CONFIG(SSE)
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500218 /* Enable sse instructions. */
219 mov %cr4, %eax
220 orl $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
221 mov %eax, %cr4
222#endif
223
Arthur Heymansd4dfc212022-11-10 13:34:49 +0100224 pop %edi /* Retrieve cpu index */
Raul E Rangel36715972021-10-08 13:10:38 -0600225 andl $0xfffffff0, %esp /* ensure stack alignment */
226
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200227#if ENV_X86_64
Arthur Heymansd4dfc212022-11-10 13:34:49 +0100228 /* entry64.inc preserves ebx, esi, edi, ebp */
Arthur Heymans3cfcffe2024-02-02 17:37:42 +0100229 setup_longmode cr3
Arthur Heymans3edf8402021-07-05 21:18:50 +0200230
Patrick Rudolphd0239092021-06-11 21:24:10 +0200231 movabs c_handler, %eax
Patrick Rudolpha1695502019-12-01 07:23:59 +0100232 call *%rax
233#else
Arthur Heymansd4dfc212022-11-10 13:34:49 +0100234 push $0
235 push $0
236 push $0
237 push %edi
Aaron Durbine0785c02013-10-21 12:15:29 -0500238 mov c_handler, %eax
239 call *%eax
Patrick Rudolpha1695502019-12-01 07:23:59 +0100240#endif
241
242
Aaron Durbine0785c02013-10-21 12:15:29 -0500243halt_jump:
244 hlt
245 jmp halt_jump