107da7b222b3e9419381db2a2c8cc783ff907758
[coreboot.git] / src / arch / i386 / init / car.S
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
5  * Copyright (C) 2005 Eswar Nallusamy, LANL
6  * Copyright (C) 2005 Tyan
7  * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
8  * Copyright (C) 2007 coresystems GmbH
9  * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
10  * Copyright (C) 2008 Carl-Daniel Hailfinger
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; version 2 of the License.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
24  */
25
26 /* Init code - Switch CPU to protected mode and enable Cache-as-Ram (CAR). */
27
28 #include <arch/intel.h>
29
30 #define ROM_CODE_SEG 0x08
31 #define ROM_DATA_SEG 0x10
32
33 #define CACHE_RAM_CODE_SEG 0x18
34 #define CACHE_RAM_DATA_SEG 0x20
35
36         /* When we come here we are in protected mode. We expand the stack
37          * and copy the data segment from ROM to the memory.
38          *
39          * After that, we call the chipset bootstrap routine that
40          * does what is left of the chipset initialization.
41          *
42          * NOTE: Aligned to 4 so that we are sure that the prefetch
43          * cache will be reloaded.
44          */
45         .section .rom.text
46         .align  4
47         .globl protected_stage0
48 protected_stage0:
49         lgdt    %cs:gdtptr
50         ljmp    $ROM_CODE_SEG, $__protected_stage0
51
52 .globl __protected_stage0
53 __protected_stage0:
54         /* Save the BIST result. */
55         movl    %eax, %ebp
56
57         intel_chip_post_macro(0x01)
58
59         movw    $ROM_DATA_SEG, %ax
60         movw    %ax, %ds
61         movw    %ax, %es
62         movw    %ax, %ss
63         movw    %ax, %fs
64         movw    %ax, %gs
65
66         /* Restore the BIST value to %eax. */
67         movl    %ebp, %eax
68
69 .align 4
70
71 /* disable HyperThreading is done by eswar
72  * the other is very similar to the AMD CAR, except remove amd specific msr
73  */
74
75 #define CacheSize CONFIG_DCACHE_RAM_SIZE
76 #define CacheBase CONFIG_DCACHE_RAM_BASE
77
78 #include <cpu/x86/mtrr.h>
79
80         /* Save the BIST result */
81         movl    %eax, %ebp
82
83 CacheAsRam:
84         /* Check whether the processor has HT capability */
85         movl    $01, %eax
86         cpuid
87         btl     $28, %edx
88         jnc     NotHtProcessor
89         bswapl  %ebx
90         cmpb    $01, %bh
91         jbe     NotHtProcessor
92
93         /* It is a HT processor; Send SIPI to the other logical processor
94          * within this processor so that the CAR related common system
95          * registers are programmed accordingly
96          */
97
98         /* Use some register that is common to both logical processors
99          * as semaphore. Refer Appendix B, Vol.3
100          */
101
102         xorl    %eax, %eax
103         xorl    %edx, %edx
104         movl    $0x250, %ecx
105         wrmsr
106
107         /* Figure out the logical AP's APIC ID; the following logic will work
108          * only for processors with 2 threads.
109          *
110          * Refer to Vol 3. Table 7-1 for details about this logic
111          */
112         movl    $0xFEE00020, %esi
113         movl    (%esi), %ebx
114         andl    $0xFF000000, %ebx
115         bswapl  %ebx
116         btl     $0, %ebx
117         jnc     LogicalAP0
118         andb    $0xFE, %bl
119         jmp     SendSIPI
120 LogicalAP0:
121         orb     $0x01, %bl
122 SendSIPI:
123         bswapl  %ebx  /* ebx - logical AP's APIC ID */
124
125         /* Fill up the IPI command registers in the Local APIC mapped to
126          * default address and issue SIPI to the other logical processor
127          * within this processor die.
128          */
129
130 RetrySIPI:
131         movl    %ebx, %eax
132         movl    $0xFEE00310, %esi
133         movl    %eax, (%esi)
134
135         /* SIPI vector - F900:0000 */
136         movl    $0x000006F9, %eax
137         movl    $0xFEE00300, %esi
138         movl    %eax, (%esi)
139
140         movl    $0x30, %ecx
141 SIPIDelay:
142         pause
143         decl    %ecx
144         jnz     SIPIDelay
145
146         movl    (%esi), %eax
147         andl    $0x00001000, %eax
148         jnz     RetrySIPI
149
150         /* Wait for the Logical AP to complete initialization */
151 LogicalAPSIPINotdone:
152         movl    $0x250, %ecx
153         rdmsr
154         orl     %eax, %eax
155         jz      LogicalAPSIPINotdone
156
157
158
159 NotHtProcessor:
160         /* Set the default memory type and enable fixed and variable MTRRs */
161         movl    $MTRRdefType_MSR, %ecx
162         xorl    %edx, %edx
163         /* Enable Variable and Fixed MTRRs */
164         movl    $0x00000c00, %eax
165         wrmsr
166
167         /* Clear all MTRRs */
168         xorl    %edx, %edx
169         movl    $fixed_mtrr_msr, %esi
170
171 clear_fixed_var_mtrr:
172         lodsl   (%esi), %eax
173         testl   %eax, %eax
174         jz      clear_fixed_var_mtrr_out
175
176         movl    %eax, %ecx
177         xorl    %eax, %eax
178         wrmsr
179
180         jmp     clear_fixed_var_mtrr
181 clear_fixed_var_mtrr_out:
182
183 /* 0x06 is the WB IO type for a given 4k segment.
184  * segs is the number of 4k segments in the area of the particular
185  *   register we want to use for CAR.
186  * reg is the register where the IO type should be stored.
187  */
188 .macro extractmask segs, reg
189 .if \segs <= 0
190         /* The xorl here is superfluous because at the point of first execution
191          * of this macro, %eax and %edx are cleared. Later invocations of this
192          * macro will have a monotonically increasing segs parameter.
193          */
194         xorl \reg, \reg
195 .elseif \segs == 1
196         movl $0x06000000, \reg /* WB IO type */
197 .elseif \segs == 2
198         movl $0x06060000, \reg /* WB IO type */
199 .elseif \segs == 3
200         movl $0x06060600, \reg /* WB IO type */
201 .elseif \segs >= 4
202         movl $0x06060606, \reg /* WB IO type */
203 .endif
204 .endm
205
206 /* size is the cache size in bytes we want to use for CAR.
207  * windowoffset is the 32k-aligned window into CAR size
208  */
209 .macro simplemask carsize, windowoffset
210 /* DO NOT CHANGE THE FORMATTING of the two lines below! Whitespace is
211  * interpreted as an argument delimiter by some versions of GNU as. */
212         extractmask (((\carsize-\windowoffset)/0x1000)-4), %eax
213         extractmask (((\carsize-\windowoffset)/0x1000)), %edx
214 .endm
215
216 #if CacheSize > 0x10000
217 #error Invalid CAR size, must be at most 64k.
218 #endif
219 #if CacheSize < 0x1000
220 #error Invalid CAR size, must be at least 4k. This is a processor limitation.
221 #endif
222 #if (CacheSize & (0x1000 - 1))
223 #error Invalid CAR size, is not a multiple of 4k. This is a processor limitation.
224 #endif
225
226 #if CacheSize > 0x8000
227         /* enable caching for 32K-64K using fixed mtrr */
228         movl    $0x268, %ecx  /* fix4k_c0000*/
229         simplemask CacheSize, 0x8000
230         wrmsr
231 #endif
232
233         /* enable caching for 0-32K using fixed mtrr */
234         movl    $0x269, %ecx  /* fix4k_c8000*/
235         simplemask CacheSize, 0
236         wrmsr
237
238 #if defined(CONFIG_XIP_ROM_SIZE) && defined(CONFIG_XIP_ROM_BASE)
239 #if defined(CONFIG_TINY_BOOTBLOCK) && CONFIG_TINY_BOOTBLOCK
240 #define REAL_XIP_ROM_BASE AUTO_XIP_ROM_BASE
241 #else
242 #define REAL_XIP_ROM_BASE CONFIG_XIP_ROM_BASE
243 #endif
244         /* enable write base caching so we can do execute in place
245          * on the flash rom.
246          */
247         movl    $0x202, %ecx
248         xorl    %edx, %edx
249         movl    $REAL_XIP_ROM_BASE, %eax
250         orl     $MTRR_TYPE_WRBACK, %eax
251         wrmsr
252
253         movl    $0x203, %ecx
254         movl    $0x0000000f, %edx
255         movl    $(~(CONFIG_XIP_ROM_SIZE - 1) | 0x800), %eax
256         wrmsr
257 #endif /* CONFIG_XIP_ROM_SIZE && CONFIG_XIP_ROM_BASE */
258
259         /* enable cache */
260         movl    %cr0, %eax
261         andl    $0x9fffffff,%eax
262         movl    %eax, %cr0
263
264         /* Read the range with lodsl*/
265         movl    $CacheBase, %esi
266         cld
267         movl    $(CacheSize>>2), %ecx
268         rep     lodsl
269
270         /* Clear the range */
271         movl    $CacheBase, %edi
272         movl    $(CacheSize>>2), %ecx
273         xorl    %eax, %eax
274         rep     stosl
275
276
277         /* TODO: make this a config variable */
278 #if CARTEST
279         /* check the cache as ram */
280         movl  $CacheBase, %esi
281         movl    $(CacheSize>>2), %ecx
282 .xin1:
283         movl  %esi, %eax
284         movl  %eax, (%esi)
285         decl  %ecx
286         je      .xout1
287         add     $4, %esi
288         jmp     .xin1
289 .xout1:
290
291         movl  $CacheBase, %esi
292 //        movl    $(CacheSize>>2), %ecx
293         movl $4, %ecx
294 .xin1x:
295         movl  %esi, %eax
296
297         movl    $0x4000, %edx
298         movb    %ah, %al
299 .testx1:
300         outb %al, $0x80
301         decl    %edx
302         jnz .testx1
303         
304         movl  (%esi), %eax
305         cmpb 0xff, %al
306         je .xin2  /* dont show */
307
308         movl    $0x4000, %edx
309 .testx2:
310         outb %al, $0x80
311         decl    %edx
312         jnz .testx2
313         
314 .xin2:  decl     %ecx
315         je      .xout1x
316         add     $4, %esi
317         jmp     .xin1x
318 .xout1x:
319
320 #endif
321
322         movl    $(CacheBase+CacheSize-4), %eax
323         movl    %eax, %esp
324
325         /* Load a different set of data segments */
326         movw    $CACHE_RAM_DATA_SEG, %ax
327         movw    %ax, %ds
328         movw    %ax, %es
329         movw    %ax, %ss
330
331 lout:
332         /* Store zero for the pointer to the global variables. */
333         pushl   $0
334
335         /* Restore the BIST result. */
336         movl    %ebp, %eax
337
338         /* We need to set ebp? No need. */
339         movl    %esp, %ebp
340
341         /* Third parameter: cpu #: 0 == BSP all other are APs.
342          * 0 until SMP support is added.
343          */
344         pushl   $0
345         /* Second parameter: init_detected */
346         /* Store zero for the unused init_detected parameter. */
347         pushl   $0
348         /* First parameter: bist */
349         pushl   %eax
350         call    main
351         /* We will not go back. */
352
353 fixed_mtrr_msr:
354         .long   0x250, 0x258, 0x259
355         .long   0x268, 0x269, 0x26A
356         .long   0x26B, 0x26C, 0x26D
357         .long   0x26E, 0x26F
358 var_mtrr_msr:
359         .long   0x200, 0x201, 0x202, 0x203
360         .long   0x204, 0x205, 0x206, 0x207
361         .long   0x208, 0x209, 0x20A, 0x20B
362         .long   0x20C, 0x20D, 0x20E, 0x20F
363         .long   0x000 /* NULL, end of table */