blob: f9b29576bdd7ec3384ce8f29e28779f7d61ef910 [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__
9
Elyes HAOUASece26962018-08-07 12:24:16 +020010/* The SIPI vector is responsible for initializing the APs in the system. It
Aaron Durbine0785c02013-10-21 12:15:29 -050011 * loads microcode, sets up MSRs, and enables caching before calling into
12 * C code. */
13
Aaron Durbine0785c02013-10-21 12:15:29 -050014.section ".module_parameters", "aw", @progbits
15ap_start_params:
16gdtaddr:
17.word 0 /* limit */
18.long 0 /* table */
19.word 0 /* unused */
20idt_ptr:
21.long 0
22stack_top:
23.long 0
24stack_size:
25.long 0
26microcode_lock:
27.long 0
28microcode_ptr:
29.long 0
30msr_table_ptr:
31.long 0
32msr_count:
33.long 0
34c_handler:
35.long 0
36ap_count:
37.long 0
38
Aaron Durbin154d2092017-06-16 14:20:10 -050039#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
40#define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
41#define CR0_CLEAR_FLAGS \
42 (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
43
Aaron Durbine0785c02013-10-21 12:15:29 -050044.text
45.code16
Aaron Durbindde76292015-09-05 12:59:26 -050046.global _start
47_start:
Aaron Durbine0785c02013-10-21 12:15:29 -050048 cli
49 xorl %eax, %eax
50 movl %eax, %cr3 /* Invalidate TLB*/
51
52 /* On hyper threaded cpus, invalidating the cache here is
53 * very very bad. Don't.
54 */
55
56 /* setup the data segment */
57 movw %cs, %ax
58 movw %ax, %ds
59
60 /* The gdtaddr needs to be releative to the data segment in order
61 * to properly dereference it. The .text section comes first in an
Aaron Durbindde76292015-09-05 12:59:26 -050062 * rmodule so _start can be used as a proxy for the load address. */
Aaron Durbine0785c02013-10-21 12:15:29 -050063 movl $(gdtaddr), %ebx
Aaron Durbindde76292015-09-05 12:59:26 -050064 sub $(_start), %ebx
Aaron Durbine0785c02013-10-21 12:15:29 -050065
Edward O'Callaghan4e2294b2017-01-08 19:14:42 +110066 lgdtl (%ebx)
Aaron Durbine0785c02013-10-21 12:15:29 -050067
68 movl %cr0, %eax
Aaron Durbin154d2092017-06-16 14:20:10 -050069 andl $~CR0_CLEAR_FLAGS, %eax
70 orl $CR0_SET_FLAGS, %eax
Aaron Durbine0785c02013-10-21 12:15:29 -050071 movl %eax, %cr0
72
Patrick Rudolph776da082019-10-25 08:09:33 +020073 ljmpl $RAM_CODE_SEG, $1f
Aaron Durbine0785c02013-10-21 12:15:29 -0500741:
75 .code32
Patrick Rudolph776da082019-10-25 08:09:33 +020076 movw $RAM_DATA_SEG, %ax
Aaron Durbine0785c02013-10-21 12:15:29 -050077 movw %ax, %ds
78 movw %ax, %es
79 movw %ax, %ss
80 movw %ax, %fs
81 movw %ax, %gs
82
83 /* Load the Interrupt descriptor table */
84 mov idt_ptr, %ebx
85 lidt (%ebx)
86
Aaron Durbine0785c02013-10-21 12:15:29 -0500871:
Patrick Rudolph72c60712020-11-18 13:26:10 +010088 /* Obtain CPU number. */
89 movl ap_count, %ecx
Aaron Durbine0785c02013-10-21 12:15:29 -050090 inc %ecx
91 lock cmpxchg %ecx, ap_count
92 jnz 1b
93
94 /* Setup stacks for each CPU. */
95 movl stack_size, %eax
96 mul %ecx
97 movl stack_top, %edx
98 subl %eax, %edx
99 mov %edx, %esp
Marshall Dawsondf319042017-09-29 11:14:44 -0600100 andl $0xfffffff0, %esp /* ensure stack alignment */
101
Elyes HAOUASd82be922016-07-28 18:58:27 +0200102 /* Save CPU number. */
Aaron Durbine0785c02013-10-21 12:15:29 -0500103 mov %ecx, %esi
104
Patrick Rudolphce51b342021-01-11 09:21:58 +0100105 /*
106 * The following code only needs to run on Intel platforms and thus the caller
107 * doesn't provide a microcode_ptr if not on Intel.
108 * On Intel platforms which update microcode using FIT the version check will
109 * also skip the microcode update.
110 */
111
Aaron Durbine0785c02013-10-21 12:15:29 -0500112 /* Determine if one should check microcode versions. */
113 mov microcode_ptr, %edi
114 test %edi, %edi
115 jz microcode_done /* Bypass if no microde exists. */
116
117 /* Get the Microcode version. */
Arthur Heymans193aac82021-01-18 19:50:26 +0100118 xorl %eax, %eax
119 xorl %edx, %edx
120 movl $IA32_BIOS_SIGN_ID, %ecx
121 wrmsr
Aaron Durbine0785c02013-10-21 12:15:29 -0500122 mov $1, %eax
123 cpuid
124 mov $IA32_BIOS_SIGN_ID, %ecx
125 rdmsr
126 /* If something already loaded skip loading again. */
127 test %edx, %edx
128 jnz microcode_done
129
Patrick Rudolphce51b342021-01-11 09:21:58 +0100130 /*
131 * Intel SDM and various BWGs specify to use a semaphore to update microcode
132 * on one thread per core on Hyper-Threading enabled CPUs. Due to this complex
133 * code would be necessary to determine the core #ID, initializing and picking
134 * the right semaphore out of CONFIG_MAX_CPUS / 2.
135 * Instead of the per core approachm, as recommended, use one global spinlock.
136 * Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
137 * most 8 threads will ever run into this condition, the boot delay is negligible.
138 */
139
Aaron Durbine0785c02013-10-21 12:15:29 -0500140 /* Determine if parallel microcode loading is allowed. */
Damien Zammit69331512017-09-02 20:30:39 +1000141 cmpl $0xffffffff, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500142 je load_microcode
143
144 /* Protect microcode loading. */
145lock_microcode:
Jacob Garber1627e2f2020-10-28 20:03:53 -0600146 lock btsl $0, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500147 jc lock_microcode
148
149load_microcode:
150 /* Load new microcode. */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200151 mov $IA32_BIOS_UPDT_TRIG, %ecx
Aaron Durbine0785c02013-10-21 12:15:29 -0500152 xor %edx, %edx
153 mov %edi, %eax
154 /* The microcode pointer is passed in pointing to the header. Adjust
155 * pointer to reflect the payload (header size is 48 bytes). */
156 add $48, %eax
157 pusha
158 wrmsr
159 popa
160
161 /* Unconditionally unlock microcode loading. */
Damien Zammit69331512017-09-02 20:30:39 +1000162 cmpl $0xffffffff, microcode_lock
Aaron Durbine0785c02013-10-21 12:15:29 -0500163 je microcode_done
164
165 xor %eax, %eax
166 mov %eax, microcode_lock
167
168microcode_done:
169 /*
170 * Load MSRs. Each entry in the table consists of:
171 * 0: index,
172 * 4: value[31:0]
173 * 8: value[63:32]
174 */
175 mov msr_table_ptr, %edi
176 mov msr_count, %ebx
177 test %ebx, %ebx
178 jz 1f
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600179
Julius Wernercd49cce2019-03-05 16:53:33 -0800180#if CONFIG(X86_AMD_FIXED_MTRRS)
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600181 /* Allow modification of RdDram and WrDram bits */
182 mov $SYSCFG_MSR, %ecx
183 rdmsr
184 or $SYSCFG_MSR_MtrrFixDramModEn, %eax
185 wrmsr
186#endif
187
Aaron Durbine0785c02013-10-21 12:15:29 -0500188load_msr:
189 mov (%edi), %ecx
190 mov 4(%edi), %eax
191 mov 8(%edi), %edx
192 wrmsr
193 add $12, %edi
194 dec %ebx
195 jnz load_msr
196
Julius Wernercd49cce2019-03-05 16:53:33 -0800197#if CONFIG(X86_AMD_FIXED_MTRRS)
Marshall Dawsonc0dbeda2017-10-19 09:45:16 -0600198 mov $SYSCFG_MSR, %ecx
199 rdmsr
200 and $~SYSCFG_MSR_MtrrFixDramModEn, %eax
201 wrmsr
202#endif
203
Aaron Durbine0785c02013-10-21 12:15:29 -05002041:
205 /* Enable caching. */
206 mov %cr0, %eax
Aaron Durbin154d2092017-06-16 14:20:10 -0500207 and $~(CR0_CLEAR_FLAGS_CACHE_ENABLE), %eax
Aaron Durbine0785c02013-10-21 12:15:29 -0500208 mov %eax, %cr0
209
Julius Wernercd49cce2019-03-05 16:53:33 -0800210#if CONFIG(SSE)
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500211 /* Enable sse instructions. */
212 mov %cr4, %eax
213 orl $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
214 mov %eax, %cr4
215#endif
216
Patrick Rudolpha1695502019-12-01 07:23:59 +0100217#ifdef __x86_64__
218 /* entry64.inc preserves ebx. */
219#include <cpu/x86/64bit/entry64.inc>
220
221 mov %rsi, %rdi /* cpu_num */
222
223 movl c_handler, %eax
224 call *%rax
225#else
Marshall Dawsondf319042017-09-29 11:14:44 -0600226 /* c_handler(cpu_num), preserve proper stack alignment */
227 sub $12, %esp
Aaron Durbine0785c02013-10-21 12:15:29 -0500228 push %esi /* cpu_num */
Patrick Rudolpha1695502019-12-01 07:23:59 +0100229
Aaron Durbine0785c02013-10-21 12:15:29 -0500230 mov c_handler, %eax
231 call *%eax
Patrick Rudolpha1695502019-12-01 07:23:59 +0100232#endif
233
234
Aaron Durbine0785c02013-10-21 12:15:29 -0500235halt_jump:
236 hlt
237 jmp halt_jump