bfc2ebdb31706f41ae6d09a98b56a9927ac3e492
[coreboot.git] / src / cpu / x86 / car / cache_as_ram.inc
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) 2007 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 /* We will use 4K bytes only */
27 /* disable HyperThreading is done by eswar*/
28 /* other's is the same as AMD except remove amd specific msr */
29
30 #define CacheSize CONFIG_DCACHE_RAM_SIZE
31 #define CacheBase (0xd0000 - CacheSize)
32
33 #include <cpu/x86/mtrr.h>
34
35         /* Save the BIST result */
36         movl    %eax, %ebp
37
38 CacheAsRam:
39         /* hope we can skip the double set for normal part */
40 #if CONFIG_USE_FALLBACK_IMAGE == 1
41
42         // Check whether the processor has HT capability
43         movl    $01, %eax
44         cpuid
45         btl     $28, %edx
46         jnc     NotHtProcessor
47         bswapl  %ebx
48         cmpb    $01, %bh
49         jbe     NotHtProcessor
50
51         // It is a HT processor; Send SIPI to the other logical processor
52         // within this processor so that the CAR related common system registers
53         // are programmed accordingly
54
55         // Use some register that is common to both logical processors
56         // as semaphore. Refer Appendix B, Vol.3
57         xorl    %eax, %eax
58         xorl    %edx, %edx
59         movl    $0x250, %ecx
60         wrmsr
61
62         // Figure out the logical AP's APIC ID; the following logic will work
63         // only for processors with 2 threads
64         // Refer to Vol 3. Table 7-1 for details about this logic
65         movl    $0xFEE00020, %esi
66         movl    (%esi), %ebx
67         andl    $0xFF000000, %ebx
68         bswapl  %ebx
69         btl     $0, %ebx
70         jnc     LogicalAP0
71         andb    $0xFE, %bl
72         jmp     Send_SIPI
73 LogicalAP0:
74         orb     $0x01, %bl
75 Send_SIPI:
76         bswapl  %ebx  // ebx - logical AP's APIC ID
77
78         // Fill up the IPI command registers in the Local APIC mapped to default address
79         // and issue SIPI to the other logical processor within this processor die.
80 Retry_SIPI:
81         movl    %ebx, %eax
82         movl    $0xFEE00310, %esi
83         movl    %eax, (%esi)
84
85         // SIPI vector - F900:0000
86         movl    $0x000006F9, %eax
87         movl    $0xFEE00300, %esi
88         movl    %eax, (%esi)
89
90         movl    $0x30, %ecx
91 SIPI_Delay:
92         pause
93         decl    %ecx
94         jnz     SIPI_Delay
95
96         movl    (%esi), %eax
97         andl    $0x00001000, %eax
98         jnz     Retry_SIPI
99
100         // Wait for the Logical AP to complete initialization
101 LogicalAP_SIPINotdone:
102         movl    $0x250, %ecx
103         rdmsr
104         orl     %eax, %eax
105         jz      LogicalAP_SIPINotdone
106
107 NotHtProcessor:
108
109 #if 1
110         /* Set the default memory type and enable fixed and variable MTRRs */
111         movl    $MTRRdefType_MSR, %ecx
112         xorl    %edx, %edx
113         /* Enable Variable and Fixed MTRRs */
114         movl    $0x00000c00, %eax
115         wrmsr
116 #endif
117
118         /* Clear all MTRRs */
119         xorl    %edx, %edx
120         movl    $fixed_mtrr_msr, %esi
121
122 clear_fixed_var_mtrr:
123         lodsl   (%esi), %eax
124         testl   %eax, %eax
125         jz      clear_fixed_var_mtrr_out
126
127         movl    %eax, %ecx
128         xorl    %eax, %eax
129         wrmsr
130
131         jmp     clear_fixed_var_mtrr
132 clear_fixed_var_mtrr_out:
133
134 /* 0x06 is the WB IO type for a given 4k segment.
135  * segs is the number of 4k segments in the area of the particular
136  *   register we want to use for CAR.
137  * reg is the register where the IO type should be stored.
138  */
139 .macro extractmask segs, reg
140 .if \segs <= 0
141         /* The xorl here is superfluous because at the point of first execution
142          * of this macro, %eax and %edx are cleared. Later invocations of this
143          * macro will have a monotonically increasing segs parameter.
144          */
145         xorl \reg, \reg
146 .elseif \segs == 1
147         movl $0x06000000, \reg /* WB IO type */
148 .elseif \segs == 2
149         movl $0x06060000, \reg /* WB IO type */
150 .elseif \segs == 3
151         movl $0x06060600, \reg /* WB IO type */
152 .elseif \segs >= 4
153         movl $0x06060606, \reg /* WB IO type */
154 .endif
155 .endm
156
157 /* size is the cache size in bytes we want to use for CAR.
158  * windowoffset is the 32k-aligned window into CAR size
159  */
160 .macro simplemask carsize, windowoffset
161         .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000) - 4)
162         extractmask gas_bug_workaround, %eax
163         .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000))
164         extractmask gas_bug_workaround, %edx
165 /* Without the gas bug workaround, the entire macro would consist only of the
166  * two lines below.
167         extractmask (((\carsize - \windowoffset) / 0x1000) - 4), %eax
168         extractmask (((\carsize - \windowoffset) / 0x1000)), %edx
169  */
170 .endm
171
172 #if CacheSize > 0x10000
173 #error Invalid CAR size, must be at most 64k.
174 #endif
175 #if CacheSize < 0x1000
176 #error Invalid CAR size, must be at least 4k. This is a processor limitation.
177 #endif
178 #if (CacheSize & (0x1000 - 1))
179 #error Invalid CAR size, is not a multiple of 4k. This is a processor limitation.
180 #endif
181
182 #if CacheSize > 0x8000
183         /* enable caching for 32K-64K using fixed mtrr */
184         movl    $0x268, %ecx  /* fix4k_c0000*/
185         simplemask CacheSize, 0x8000
186         wrmsr
187 #endif
188
189         /* enable caching for 0-32K using fixed mtrr */
190         movl    $0x269, %ecx  /* fix4k_c8000*/
191         simplemask CacheSize, 0
192         wrmsr
193
194 #else
195         /* disable cache */
196         movl    %cr0, %eax
197         orl     $(0x1 << 30), %eax
198         movl    %eax, %cr0
199
200 #endif /*  CONFIG_USE_FALLBACK_IMAGE == 1*/
201
202 #if defined(CONFIG_XIP_ROM_SIZE) && defined(CONFIG_XIP_ROM_BASE)
203 #if defined(CONFIG_TINY_BOOTBLOCK) && CONFIG_TINY_BOOTBLOCK
204 #define REAL_XIP_ROM_BASE AUTO_XIP_ROM_BASE
205 #else
206 #define REAL_XIP_ROM_BASE CONFIG_XIP_ROM_BASE
207 #endif
208         /* enable write base caching so we can do execute in place
209          * on the flash rom.
210          */
211         movl    $0x202, %ecx
212         xorl    %edx, %edx
213         movl    $REAL_XIP_ROM_BASE, %eax
214         orl     $MTRR_TYPE_WRBACK, %eax
215         wrmsr
216
217         movl    $0x203, %ecx
218         movl    $0x0000000f, %edx
219         movl    $(~(CONFIG_XIP_ROM_SIZE - 1) | 0x800), %eax
220         wrmsr
221 #endif /* CONFIG_XIP_ROM_SIZE && CONFIG_XIP_ROM_BASE */
222
223         /* enable cache */
224         movl    %cr0, %eax
225         andl    $0x9fffffff, %eax
226         movl    %eax, %cr0
227
228 #if CONFIG_USE_FALLBACK_IMAGE == 1
229
230         /* Read the range with lodsl*/
231         movl    $CacheBase, %esi
232         cld
233         movl    $(CacheSize >> 2), %ecx
234         rep     lodsl
235
236         /* Clear the range */
237         movl    $CacheBase, %edi
238         movl    $(CacheSize >> 2), %ecx
239         xorl    %eax, %eax
240         rep     stosl
241
242
243 #if 0
244         /* check the cache as ram */
245         movl    $CacheBase, %esi
246         movl    $(CacheSize>>2), %ecx
247 .xin1:
248         movl    %esi, %eax
249         movl    %eax, (%esi)
250         decl    %ecx
251         je      .xout1
252         add     $4, %esi
253         jmp     .xin1
254 .xout1:
255
256         movl    $CacheBase, %esi
257 //        movl    $(CacheSize>>2), %ecx
258         movl $4, %ecx
259 .xin1x:
260         movl    %esi, %eax
261
262         movl    $0x4000, %edx
263         movb    %ah, %al
264 .testx1:
265         outb %al, $0x80
266         decl    %edx
267         jnz .testx1
268
269         movl    (%esi), %eax
270         cmpb 0xff, %al
271         je .xin2  /* dont show */
272
273         movl    $0x4000, %edx
274 .testx2:
275         outb %al, $0x80
276         decl    %edx
277         jnz .testx2
278
279 .xin2:  decl     %ecx
280         je      .xout1x
281         add     $4, %esi
282         jmp     .xin1x
283 .xout1x:
284
285 #endif
286 #endif /*CONFIG_USE_FALLBACK_IMAGE == 1*/
287
288
289         movl    $(CacheBase + CacheSize - 4), %eax
290         movl    %eax, %esp
291
292         /* Load a different set of data segments */
293 #if CONFIG_USE_INIT
294         movw    $CACHE_RAM_DATA_SEG, %ax
295         movw    %ax, %ds
296         movw    %ax, %es
297         movw    %ax, %ss
298 #endif
299
300 lout:
301         /* Restore the BIST result */
302         movl    %ebp, %eax
303
304         /* We need to set ebp ? No need */
305         movl    %esp, %ebp
306         pushl   %eax  /* bist */
307         call    amd64_main
308         /* We will not go back */
309
310 fixed_mtrr_msr:
311         .long   0x250, 0x258, 0x259
312         .long   0x268, 0x269, 0x26A
313         .long   0x26B, 0x26C, 0x26D
314         .long   0x26E, 0x26F
315 var_mtrr_msr:
316         .long   0x200, 0x201, 0x202, 0x203
317         .long   0x204, 0x205, 0x206, 0x207
318         .long   0x208, 0x209, 0x20A, 0x20B
319         .long   0x20C, 0x20D, 0x20E, 0x20F
320         .long   0x000 /* NULL, end of table */
321
322 #if CONFIG_USE_FALLBACK_IMAGE == 1
323         .align 0x1000
324         .code16
325 .global LogicalAP_SIPI
326 LogicalAP_SIPI:
327         // cr0 register is shared among the logical processors;
328         // so clear CD & NW bits so that the BSP's cr0 register
329         // controls the cache behavior
330         // Note: The cache behavior is determined by "OR" result
331         // of the cr0 registers of the logical processors
332
333         movl    %cr0, %eax
334         andl    $0x9FFFFFFF, %eax
335         movl    %eax, %cr0
336
337         finit
338
339         // Set the semaphore to indicate the Logical AP is done
340         // with CAR specific initialization
341         movl    $0x250, %ecx
342         movl    $0x06, %eax
343         xorl    %edx, %edx
344         wrmsr
345
346         // Halt this AP
347         cli
348 Halt_LogicalAP:
349         hlt
350         jmp     Halt_LogicalAP
351         .code32
352 #endif /*CONFIG_USE_FALLBACK_IMAGE == 1*/
353 .CacheAsRam_out: