blob: c08c3911dfd25e98249d574cf7115bdd2673a366 [file] [log] [blame]
Aaron Durbine0785c02013-10-21 12:15:29 -05001/*
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., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22/* The SIPI vector is responsible for initializing the APs in the sytem. It
23 * loads microcode, sets up MSRs, and enables caching before calling into
24 * C code. */
25
26/* These segment selectors need to match the gdt entries in c_start.S. */
27#define CODE_SEG 0x10
28#define DATA_SEG 0x18
29
30#define IA32_UPDT_TRIG 0x79
31#define IA32_BIOS_SIGN_ID 0x8b
32
33.section ".module_parameters", "aw", @progbits
34ap_start_params:
35gdtaddr:
36.word 0 /* limit */
37.long 0 /* table */
38.word 0 /* unused */
39idt_ptr:
40.long 0
41stack_top:
42.long 0
43stack_size:
44.long 0
45microcode_lock:
46.long 0
47microcode_ptr:
48.long 0
49msr_table_ptr:
50.long 0
51msr_count:
52.long 0
53c_handler:
54.long 0
55ap_count:
56.long 0
57
58.text
59.code16
60.global ap_start
Aaron Durbin3eb8eb72014-03-10 16:13:58 -050061.global __rmodule_entry
62__rmodule_entry:
Aaron Durbine0785c02013-10-21 12:15:29 -050063ap_start:
64 cli
65 xorl %eax, %eax
66 movl %eax, %cr3 /* Invalidate TLB*/
67
68 /* On hyper threaded cpus, invalidating the cache here is
69 * very very bad. Don't.
70 */
71
72 /* setup the data segment */
73 movw %cs, %ax
74 movw %ax, %ds
75
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 ap_start can be used as a proxy for the load address. */
79 movl $(gdtaddr), %ebx
80 sub $(ap_start), %ebx
81
82 data32 lgdt (%ebx)
83
84 movl %cr0, %eax
85 andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
86 orl $0x60000001, %eax /* CD, NW, PE = 1 */
87 movl %eax, %cr0
88
89 ljmpl $CODE_SEG, $1f
901:
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
98
99 /* Load the Interrupt descriptor table */
100 mov idt_ptr, %ebx
101 lidt (%ebx)
102
103 /* Obtain cpu number. */
104 movl ap_count, %eax
1051:
106 movl %eax, %ecx
107 inc %ecx
108 lock cmpxchg %ecx, ap_count
109 jnz 1b
110
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
119
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. */
124
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
133
134 /* Determine if parallel microcode loading is allowed. */
135 cmp $0xffffffff, microcode_lock
136 je load_microcode
137
138 /* Protect microcode loading. */
139lock_microcode:
140 lock bts $0, microcode_lock
141 jc lock_microcode
142
143load_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
154
155 /* Unconditionally unlock microcode loading. */
156 cmp $0xffffffff, microcode_lock
157 je microcode_done
158
159 xor %eax, %eax
160 mov %eax, microcode_lock
161
162microcode_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
173load_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
181
1821:
183 /* Enable caching. */
184 mov %cr0, %eax
185 and $0x9fffffff, %eax /* CD, NW = 0 */
186 mov %eax, %cr0
187
188 /* c_handler(cpu_num) */
189 push %esi /* cpu_num */
190 mov c_handler, %eax
191 call *%eax
192halt_jump:
193 hlt
194 jmp halt_jump