cpu/x86/sipi_vector.S: Use correct op suffix
[coreboot.git] / src / cpu / x86 / sipi_vector.S
blobb40ea76f76c74a5d9834d5f15d59a0d73de07dea
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2013 Google Inc.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; version 2 of
9  * the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
17 #include <cpu/x86/cr.h>
19 /* The SIPI vector is responsible for initializing the APs in the sytem. It
20  * loads microcode, sets up MSRs, and enables caching before calling into
21  * C code. */
23 /* These segment selectors need to match the gdt entries in c_start.S. */
24 #define CODE_SEG 0x10
25 #define DATA_SEG 0x18
27 #define IA32_UPDT_TRIG 0x79
28 #define IA32_BIOS_SIGN_ID 0x8b
30 .section ".module_parameters", "aw", @progbits
31 ap_start_params:
32 gdtaddr:
33 .word 0 /* limit */
34 .long 0 /* table */
35 .word 0 /* unused */
36 idt_ptr:
37 .long 0
38 stack_top:
39 .long 0
40 stack_size:
41 .long 0
42 microcode_lock:
43 .long 0
44 microcode_ptr:
45 .long 0
46 msr_table_ptr:
47 .long 0
48 msr_count:
49 .long 0
50 c_handler:
51 .long 0
52 ap_count:
53 .long 0
55 #define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
56 #define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
57 #define CR0_CLEAR_FLAGS \
58         (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
60 .text
61 .code16
62 .global _start
63 _start:
64         cli
65         xorl    %eax, %eax
66         movl    %eax, %cr3    /* Invalidate TLB*/
68         /* On hyper threaded cpus, invalidating the cache here is
69          * very very bad.  Don't.
70          */
72         /* setup the data segment */
73         movw    %cs, %ax
74         movw    %ax, %ds
76         /* The gdtaddr needs to be releative to the data segment in order
77          * to properly dereference it. The .text section comes first in an
78          * rmodule so _start can be used as a proxy for the load address. */
79         movl    $(gdtaddr), %ebx
80         sub     $(_start), %ebx
82         lgdtl   (%ebx)
84         movl    %cr0, %eax
85         andl    $~CR0_CLEAR_FLAGS, %eax
86         orl     $CR0_SET_FLAGS, %eax
87         movl    %eax, %cr0
89         ljmpl   $CODE_SEG, $1f
91         .code32
92         movw    $DATA_SEG, %ax
93         movw    %ax, %ds
94         movw    %ax, %es
95         movw    %ax, %ss
96         movw    %ax, %fs
97         movw    %ax, %gs
99         /* Load the Interrupt descriptor table */
100         mov     idt_ptr, %ebx
101         lidt    (%ebx)
103         /* Obtain CPU number. */
104         movl    ap_count, %eax
106         movl    %eax, %ecx
107         inc     %ecx
108         lock cmpxchg %ecx, ap_count
109         jnz     1b
111         /* Setup stacks for each CPU. */
112         movl    stack_size, %eax
113         mul     %ecx
114         movl    stack_top, %edx
115         subl    %eax, %edx
116         mov     %edx, %esp
117         /* Save CPU number. */
118         mov     %ecx, %esi
120         /* Determine if one should check microcode versions. */
121         mov     microcode_ptr, %edi
122         test    %edi, %edi
123         jz      microcode_done /* Bypass if no microde exists. */
125         /* Get the Microcode version. */
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         /* Determine if parallel microcode loading is allowed. */
135         cmpl    $0xffffffff, microcode_lock
136         je      load_microcode
138         /* Protect microcode loading. */
139 lock_microcode:
140         lock bts $0, microcode_lock
141         jc      lock_microcode
143 load_microcode:
144         /* Load new microcode. */
145         mov     $IA32_UPDT_TRIG, %ecx
146         xor     %edx, %edx
147         mov     %edi, %eax
148         /* The microcode pointer is passed in pointing to the header. Adjust
149          * pointer to reflect the payload (header size is 48 bytes). */
150         add     $48, %eax
151         pusha
152         wrmsr
153         popa
155         /* Unconditionally unlock microcode loading. */
156         cmpl    $0xffffffff, microcode_lock
157         je      microcode_done
159         xor     %eax, %eax
160         mov     %eax, microcode_lock
162 microcode_done:
163         /*
164          * Load MSRs. Each entry in the table consists of:
165          * 0: index,
166          * 4: value[31:0]
167          * 8: value[63:32]
168          */
169         mov     msr_table_ptr, %edi
170         mov     msr_count, %ebx
171         test    %ebx, %ebx
172         jz      1f
173 load_msr:
174         mov     (%edi), %ecx
175         mov     4(%edi), %eax
176         mov     8(%edi), %edx
177         wrmsr
178         add     $12, %edi
179         dec     %ebx
180         jnz     load_msr
183         /* Enable caching. */
184         mov     %cr0, %eax
185         and     $~(CR0_CLEAR_FLAGS_CACHE_ENABLE), %eax
186         mov     %eax, %cr0
188 #if IS_ENABLED(CONFIG_SSE)
189         /* Enable sse instructions. */
190         mov     %cr4, %eax
191         orl     $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
192         mov     %eax, %cr4
193 #endif
195         /* c_handler(cpu_num) */
196         push    %esi    /* cpu_num */
197         mov     c_handler, %eax
198         call    *%eax
199 halt_jump:
200         hlt
201         jmp     halt_jump