tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / cpu / x86 / sipi_vector.S
blob985b9da08029486b6bfd5dc8e7ab88de11ec79e0
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 /* The SIPI vector is responsible for initializing the APs in the sytem. It
18  * loads microcode, sets up MSRs, and enables caching before calling into
19  * C code. */
21 /* These segment selectors need to match the gdt entries in c_start.S. */
22 #define CODE_SEG 0x10
23 #define DATA_SEG 0x18
25 #define IA32_UPDT_TRIG 0x79
26 #define IA32_BIOS_SIGN_ID 0x8b
28 .section ".module_parameters", "aw", @progbits
29 ap_start_params:
30 gdtaddr:
31 .word 0 /* limit */
32 .long 0 /* table */
33 .word 0 /* unused */
34 idt_ptr:
35 .long 0
36 stack_top:
37 .long 0
38 stack_size:
39 .long 0
40 microcode_lock:
41 .long 0
42 microcode_ptr:
43 .long 0
44 msr_table_ptr:
45 .long 0
46 msr_count:
47 .long 0
48 c_handler:
49 .long 0
50 ap_count:
51 .long 0
53 .text
54 .code16
55 .global _start
56 _start:
57         cli
58         xorl    %eax, %eax
59         movl    %eax, %cr3    /* Invalidate TLB*/
61         /* On hyper threaded cpus, invalidating the cache here is
62          * very very bad.  Don't.
63          */
65         /* setup the data segment */
66         movw    %cs, %ax
67         movw    %ax, %ds
69         /* The gdtaddr needs to be releative to the data segment in order
70          * to properly dereference it. The .text section comes first in an
71          * rmodule so _start can be used as a proxy for the load address. */
72         movl    $(gdtaddr), %ebx
73         sub     $(_start), %ebx
75         data32 lgdt (%ebx)
77         movl    %cr0, %eax
78         andl    $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
79         orl     $0x60000001, %eax /* CD, NW, PE = 1 */
80         movl    %eax, %cr0
82         ljmpl   $CODE_SEG, $1f
84         .code32
85         movw    $DATA_SEG, %ax
86         movw    %ax, %ds
87         movw    %ax, %es
88         movw    %ax, %ss
89         movw    %ax, %fs
90         movw    %ax, %gs
92         /* Load the Interrupt descriptor table */
93         mov     idt_ptr, %ebx
94         lidt    (%ebx)
96         /* Obtain cpu number. */
97         movl    ap_count, %eax
99         movl    %eax, %ecx
100         inc     %ecx
101         lock cmpxchg %ecx, ap_count
102         jnz     1b
104         /* Setup stacks for each CPU. */
105         movl    stack_size, %eax
106         mul     %ecx
107         movl    stack_top, %edx
108         subl    %eax, %edx
109         mov     %edx, %esp
110         /* Save cpu number. */
111         mov     %ecx, %esi
113         /* Determine if one should check microcode versions. */
114         mov     microcode_ptr, %edi
115         test    %edi, %edi
116         jz      microcode_done /* Bypass if no microde exists. */
118         /* Get the Microcode version. */
119         mov     $1, %eax
120         cpuid
121         mov     $IA32_BIOS_SIGN_ID, %ecx
122         rdmsr
123         /* If something already loaded skip loading again. */
124         test    %edx, %edx
125         jnz     microcode_done
127         /* Determine if parallel microcode loading is allowed. */
128         cmp     $0xffffffff, microcode_lock
129         je      load_microcode
131         /* Protect microcode loading. */
132 lock_microcode:
133         lock bts $0, microcode_lock
134         jc      lock_microcode
136 load_microcode:
137         /* Load new microcode. */
138         mov     $IA32_UPDT_TRIG, %ecx
139         xor     %edx, %edx
140         mov     %edi, %eax
141         /* The microcode pointer is passed in pointing to the header. Adjust
142          * pointer to reflect the payload (header size is 48 bytes). */
143         add     $48, %eax
144         pusha
145         wrmsr
146         popa
148         /* Unconditionally unlock microcode loading. */
149         cmp     $0xffffffff, microcode_lock
150         je      microcode_done
152         xor     %eax, %eax
153         mov     %eax, microcode_lock
155 microcode_done:
156         /*
157          * Load MSRs. Each entry in the table consists of:
158          * 0: index,
159          * 4: value[31:0]
160          * 8: value[63:32]
161          */
162         mov     msr_table_ptr, %edi
163         mov     msr_count, %ebx
164         test    %ebx, %ebx
165         jz      1f
166 load_msr:
167         mov     (%edi), %ecx
168         mov     4(%edi), %eax
169         mov     8(%edi), %edx
170         wrmsr
171         add     $12, %edi
172         dec     %ebx
173         jnz     load_msr
176         /* Enable caching. */
177         mov     %cr0, %eax
178         and     $0x9fffffff, %eax /* CD, NW = 0 */
179         mov     %eax, %cr0
181         /* c_handler(cpu_num) */
182         push    %esi    /* cpu_num */
183         mov     c_handler, %eax
184         call    *%eax
185 halt_jump:
186         hlt
187         jmp     halt_jump