soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / cpu / x86 / sipi_vector.S
blob39973dbc8b94dee261c06e5bb591fd45a58e5e91
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <cpu/x86/cr.h>
4 #include <cpu/amd/mtrr.h>
5 #include <cpu/x86/msr.h>
6 #include <arch/ram_segs.h>
8 #define __RAMSTAGE__
10 /* The SIPI vector is responsible for initializing the APs in the system. It
11  * loads microcode, sets up MSRs, and enables caching before calling into
12  * C code. */
14 .section ".module_parameters", "aw", @progbits
15 ap_start_params:
16 gdtaddr:
17 .word 0 /* limit */
18 .long 0 /* table */
19 .word 0 /* unused */
20 idt_ptr:
21 .long 0
22 per_cpu_segment_descriptors:
23 .long 0
24 per_cpu_segment_selector:
25 .long 0
26 stack_top:
27 .long 0
28 stack_size:
29 .long 0
30 microcode_lock:
31 .long 0
32 microcode_ptr:
33 .long 0
34 msr_table_ptr:
35 .long 0
36 msr_count:
37 .long 0
38 c_handler:
39 .long 0
40 ap_count:
41 .long 0
43 #define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
44 #define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
45 #define CR0_CLEAR_FLAGS \
46         (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
48 .text
49 .code16
50 .global _start
51 _start:
52         cli
53         xorl    %eax, %eax
54         movl    %eax, %cr3    /* Invalidate TLB*/
56         /* On hyper threaded cpus, invalidating the cache here is
57          * very very bad.  Don't.
58          */
60         /* setup the data segment */
61         movw    %cs, %ax
62         movw    %ax, %ds
64         /* The gdtaddr needs to be relative to the data segment in order
65          * to properly dereference it. The .text section comes first in an
66          * rmodule so _start can be used as a proxy for the load address. */
67         movl    $(gdtaddr), %ebx
68         sub     $(_start), %ebx
70         lgdtl   (%ebx)
72         movl    %cr0, %eax
73         andl    $~CR0_CLEAR_FLAGS, %eax
74         orl     $CR0_SET_FLAGS, %eax
75         movl    %eax, %cr0
77         ljmpl   $RAM_CODE_SEG, $1f
79         .code32
80         movw    $RAM_DATA_SEG, %ax
81         movw    %ax, %ds
82         movw    %ax, %es
83         movw    %ax, %ss
84         xor     %ax, %ax /* zero out the gs and fs segment index */
85         movw    %ax, %fs
86         movw    %ax, %gs /* Will be used for cpu_info */
88         /* Load the Interrupt descriptor table */
89         mov     idt_ptr, %ebx
90         lidt    (%ebx)
93         /* Obtain CPU number. */
94         movl    ap_count, %ecx
95         inc     %ecx
96         lock cmpxchg %ecx, ap_count
97         jnz     1b
99         /* Setup stacks for each CPU. */
100         movl    stack_size, %eax
101         mul     %ecx
102         movl    stack_top, %edx
103         subl    %eax, %edx
104         mov     %edx, %esp
106         /* Save CPU number for calling the AP entry */
107         push    %ecx
109         /*
110          * The following code only needs to run on Intel platforms and thus the caller
111          * doesn't provide a microcode_ptr if not on Intel.
112          * On Intel platforms which update microcode using FIT the version check will
113          * also skip the microcode update.
114          */
116         /* Determine if one should check microcode versions. */
117         mov     microcode_ptr, %edi
118         test    %edi, %edi
119         jz      microcode_done /* Bypass if no microde exists. */
121         /* Get the Microcode version. */
122         xorl    %eax, %eax
123         xorl    %edx, %edx
124         movl    $IA32_BIOS_SIGN_ID, %ecx
125         wrmsr
126         mov     $1, %eax
127         cpuid
128         mov     $IA32_BIOS_SIGN_ID, %ecx
129         rdmsr
130         /* If something already loaded skip loading again. */
131         test    %edx, %edx
132         jnz     microcode_done
134         /*
135          * Intel SDM and various BWGs specify to use a semaphore to update microcode
136          * on one thread per core on Hyper-Threading enabled CPUs. Due to this complex
137          * code would be necessary to determine the core #ID, initializing and picking
138          * the right semaphore out of CONFIG_MAX_CPUS / 2.
139          * Instead of the per core approachm, as recommended, use one global spinlock.
140          * Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
141          * most 8 threads will ever run into this condition, the boot delay is negligible.
142          */
144         /* Determine if parallel microcode loading is allowed. */
145         cmpl    $0xffffffff, microcode_lock
146         je      load_microcode
148         /* Protect microcode loading. */
149 lock_microcode:
150         lock btsl $0, microcode_lock
151         jc      lock_microcode
153 load_microcode:
154         /* Load new microcode. */
155         mov     $IA32_BIOS_UPDT_TRIG, %ecx
156         xor     %edx, %edx
157         mov     %edi, %eax
158         /* The microcode pointer is passed in pointing to the header. Adjust
159          * pointer to reflect the payload (header size is 48 bytes). */
160         add     $48, %eax
161         pusha
162         wrmsr
163         popa
165         /* Unconditionally unlock microcode loading. */
166         cmpl    $0xffffffff, microcode_lock
167         je      microcode_done
169         xor     %eax, %eax
170         mov     %eax, microcode_lock
172 microcode_done:
173         /*
174          * Load MSRs. Each entry in the table consists of:
175          * 0: index,
176          * 4: value[31:0]
177          * 8: value[63:32]
178          */
179         mov     msr_table_ptr, %edi
180         mov     msr_count, %ebx
181         test    %ebx, %ebx
182         jz      1f
184 #if CONFIG(X86_AMD_FIXED_MTRRS)
185         /* Allow modification of RdDram and WrDram bits */
186         mov     $SYSCFG_MSR, %ecx
187         rdmsr
188         or      $SYSCFG_MSR_MtrrFixDramModEn, %eax
189         wrmsr
190 #endif
192 load_msr:
193         mov     (%edi), %ecx
194         mov     4(%edi), %eax
195         mov     8(%edi), %edx
196         wrmsr
197         add     $12, %edi
198         dec     %ebx
199         jnz     load_msr
201 #if CONFIG(X86_AMD_FIXED_MTRRS)
202         mov     $SYSCFG_MSR, %ecx
203         rdmsr
204         and     $~SYSCFG_MSR_MtrrFixDramModEn, %eax
205         wrmsr
206 #endif
209         /* Enable caching. */
210         mov     %cr0, %eax
211         and     $~(CR0_CLEAR_FLAGS_CACHE_ENABLE), %eax
212         mov     %eax, %cr0
214 #if CONFIG(SSE)
215         /* Enable sse instructions. */
216         mov     %cr4, %eax
217         orl     $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
218         mov     %eax, %cr4
219 #endif
221         pop     %edi /* Retrieve cpu index */
222         andl    $0xfffffff0, %esp /* ensure stack alignment */
224 #if ENV_X86_64
225         /* entry64.inc preserves ebx, esi, edi, ebp */
226 #include <cpu/x86/64bit/entry64.inc>
227         movabs  c_handler, %eax
228         call    *%rax
229 #else
230         push    $0
231         push    $0
232         push    $0
233         push    %edi
234         mov     c_handler, %eax
235         call    *%eax
236 #endif
239 halt_jump:
240         hlt
241         jmp     halt_jump