Remove address from GPLv2 headers
[coreboot.git] / src / cpu / x86 / sipi_vector.S
blobc7b1097b78fd94fbe7e5a91c8b9007a18f724bb6
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  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc.
19  */
21 /* The SIPI vector is responsible for initializing the APs in the sytem. It
22  * loads microcode, sets up MSRs, and enables caching before calling into
23  * C code. */
25 /* These segment selectors need to match the gdt entries in c_start.S. */
26 #define CODE_SEG 0x10
27 #define DATA_SEG 0x18
29 #define IA32_UPDT_TRIG 0x79
30 #define IA32_BIOS_SIGN_ID 0x8b
32 .section ".module_parameters", "aw", @progbits
33 ap_start_params:
34 gdtaddr:
35 .word 0 /* limit */
36 .long 0 /* table */
37 .word 0 /* unused */
38 idt_ptr:
39 .long 0
40 stack_top:
41 .long 0
42 stack_size:
43 .long 0
44 microcode_lock:
45 .long 0
46 microcode_ptr:
47 .long 0
48 msr_table_ptr:
49 .long 0
50 msr_count:
51 .long 0
52 c_handler:
53 .long 0
54 ap_count:
55 .long 0
57 .text
58 .code16
59 .global ap_start
60 .global __rmodule_entry
61 __rmodule_entry:
62 ap_start:
63         cli
64         xorl    %eax, %eax
65         movl    %eax, %cr3    /* Invalidate TLB*/
67         /* On hyper threaded cpus, invalidating the cache here is
68          * very very bad.  Don't.
69          */
71         /* setup the data segment */
72         movw    %cs, %ax
73         movw    %ax, %ds
75         /* The gdtaddr needs to be releative to the data segment in order
76          * to properly dereference it. The .text section comes first in an
77          * rmodule so ap_start can be used as a proxy for the load address. */
78         movl    $(gdtaddr), %ebx
79         sub     $(ap_start), %ebx
81         data32 lgdt (%ebx)
83         movl    %cr0, %eax
84         andl    $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
85         orl     $0x60000001, %eax /* CD, NW, PE = 1 */
86         movl    %eax, %cr0
88         ljmpl   $CODE_SEG, $1f
90         .code32
91         movw    $DATA_SEG, %ax
92         movw    %ax, %ds
93         movw    %ax, %es
94         movw    %ax, %ss
95         movw    %ax, %fs
96         movw    %ax, %gs
98         /* Load the Interrupt descriptor table */
99         mov     idt_ptr, %ebx
100         lidt    (%ebx)
102         /* Obtain cpu number. */
103         movl    ap_count, %eax
105         movl    %eax, %ecx
106         inc     %ecx
107         lock cmpxchg %ecx, ap_count
108         jnz     1b
110         /* Setup stacks for each CPU. */
111         movl    stack_size, %eax
112         mul     %ecx
113         movl    stack_top, %edx
114         subl    %eax, %edx
115         mov     %edx, %esp
116         /* Save cpu number. */
117         mov     %ecx, %esi
119         /* 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. */
124         /* Get the Microcode version. */
125         mov     $1, %eax
126         cpuid
127         mov     $IA32_BIOS_SIGN_ID, %ecx
128         rdmsr
129         /* If something already loaded skip loading again. */
130         test    %edx, %edx
131         jnz     microcode_done
133         /* Determine if parallel microcode loading is allowed. */
134         cmp     $0xffffffff, microcode_lock
135         je      load_microcode
137         /* Protect microcode loading. */
138 lock_microcode:
139         lock bts $0, microcode_lock
140         jc      lock_microcode
142 load_microcode:
143         /* Load new microcode. */
144         mov     $IA32_UPDT_TRIG, %ecx
145         xor     %edx, %edx
146         mov     %edi, %eax
147         /* The microcode pointer is passed in pointing to the header. Adjust
148          * pointer to reflect the payload (header size is 48 bytes). */
149         add     $48, %eax
150         pusha
151         wrmsr
152         popa
154         /* Unconditionally unlock microcode loading. */
155         cmp     $0xffffffff, microcode_lock
156         je      microcode_done
158         xor     %eax, %eax
159         mov     %eax, microcode_lock
161 microcode_done:
162         /*
163          * Load MSRs. Each entry in the table consists of:
164          * 0: index,
165          * 4: value[31:0]
166          * 8: value[63:32]
167          */
168         mov     msr_table_ptr, %edi
169         mov     msr_count, %ebx
170         test    %ebx, %ebx
171         jz      1f
172 load_msr:
173         mov     (%edi), %ecx
174         mov     4(%edi), %eax
175         mov     8(%edi), %edx
176         wrmsr
177         add     $12, %edi
178         dec     %ebx
179         jnz     load_msr
182         /* Enable caching. */
183         mov     %cr0, %eax
184         and     $0x9fffffff, %eax /* CD, NW = 0 */
185         mov     %eax, %cr0
187         /* c_handler(cpu_num) */
188         push    %esi    /* cpu_num */
189         mov     c_handler, %eax
190         call    *%eax
191 halt_jump:
192         hlt
193         jmp     halt_jump