blob: 24f354d4c62feb88f75226a3395a504bef058813 [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21static inline void _WRMSR(u32 addr, u32 lo, u32 hi)
22{
23 __asm__ volatile (
24 "wrmsr"
25 :
26 :"c"(addr),"a"(lo), "d" (hi)
27 );
28}
29
30
31static inline void _RDMSR(u32 addr, u32 *lo, u32 *hi)
32{
33 __asm__ volatile (
34 "rdmsr"
35 :"=a"(*lo), "=d" (*hi)
36 :"c"(addr)
37 );
38}
39
40
41static inline void _RDTSC(u32 *lo, u32 *hi)
42{
43 __asm__ volatile (
44 "rdtsc"
45 : "=a" (*lo), "=d"(*hi)
46 );
47}
48
49
50static inline void _cpu_id(u32 addr, u32 *val)
51{
52 __asm__ volatile(
53 "cpuid"
54 : "=a" (val[0]),
55 "=b" (val[1]),
56 "=c" (val[2]),
57 "=d" (val[3])
58 : "0" (addr));
59
60}
61
62
Marc Jones65e08042008-04-25 21:34:25 +000063static u32 bsr(u32 x)
Marc Jones8ae8c882007-12-19 01:32:08 +000064{
65 u8 i;
66 u32 ret = 0;
67
68 for(i=31; i>0; i--) {
69 if(x & (1<<i)) {
70 ret = i;
71 break;
72 }
73 }
74
75 return ret;
76
77}
78
79
Marc Jones65e08042008-04-25 21:34:25 +000080static u32 bsf(u32 x)
Marc Jones8ae8c882007-12-19 01:32:08 +000081{
82 u8 i;
83 u32 ret = 32;
84
85 for(i=0; i<32; i++) {
86 if(x & (1<<i)) {
87 ret = i;
88 break;
89 }
90 }
91
92 return ret;
93}
94
95#define _MFENCE asm volatile ( "mfence")
96
97#define _SFENCE asm volatile ( "sfence" )
98
99/* prevent speculative execution of following instructions */
100#define _EXECFENCE asm volatile ("outb %al, $0xed")
101
102static inline u32 read_cr4(void)
103{
104 u32 cr4;
105 __asm__ volatile ("movl %%cr4, %0" : "=r" (cr4));
106 return cr4;
107}
108
109
110static inline void write_cr4(u32 cr4)
111{
112 __asm__ volatile ("movl %0, %%cr4" : : "r" (cr4));
113}
114
115
116u32 SetUpperFSbase(u32 addr_hi);
117
118
119static void proc_CLFLUSH(u32 addr_hi)
120{
121 SetUpperFSbase(addr_hi);
122
123 __asm__ volatile (
124 /* clflush fs:[eax] */
125 "outb %%al, $0xed\n\t" /* _EXECFENCE */
126 "clflush %%fs:(%0)\n\t"
127 "mfence\n\t"
128 ::"a" (addr_hi<<8)
129 );
130}
131
132
133static void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num)
134{
135 __asm__ volatile (
136 /*prevent speculative execution of following instructions*/
137 /* FIXME: needed ? */
138 "outb %%al, $0xed\n\t" /* _EXECFENCE */
139 "1:\n\t"
140 "movdqa (%3), %%xmm0\n\t"
141 "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
142 "addl %1, %0\n\t"
143 "addl %1, %3\n\t"
144 "loop 1b\n\t"
145 "mfence\n\t"
146
147 :: "a" (addr_lo), "d" (16), "c" (line_num * 4), "b"(buf_a)
148 );
149
150}
151
152
Myles Watson075fbe82010-04-15 05:19:29 +0000153static u32 read32_fs(u32 addr_lo)
Marc Jones8ae8c882007-12-19 01:32:08 +0000154{
155 u32 value;
156 __asm__ volatile (
157 "outb %%al, $0xed\n\t" /* _EXECFENCE */
158 "movl %%fs:(%1), %0\n\t"
159 :"=b"(value): "a" (addr_lo)
160 );
161 return value;
162}
163
Stefan Reinauerd6532112010-04-16 00:31:44 +0000164#ifdef UNUSED_CODE
Myles Watson075fbe82010-04-15 05:19:29 +0000165static u8 read8_fs(u32 addr_lo)
Marc Jones8ae8c882007-12-19 01:32:08 +0000166{
167 u8 byte;
168 __asm__ volatile (
169 "outb %%al, $0xed\n\t" /* _EXECFENCE */
170 "movb %%fs:(%1), %b0\n\t"
171 "mfence\n\t"
172 :"=b"(byte): "a" (addr_lo)
173 );
174 return byte;
175}
Stefan Reinauerd6532112010-04-16 00:31:44 +0000176#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000177
178static void FlushDQSTestPattern_L9(u32 addr_lo)
179{
180 __asm__ volatile (
181 "outb %%al, $0xed\n\t" /* _EXECFENCE */
182 "clflush %%fs:-128(%%ecx)\n\t"
183 "clflush %%fs:-64(%%ecx)\n\t"
184 "clflush %%fs:(%%ecx)\n\t"
185 "clflush %%fs:64(%%ecx)\n\t"
186
187 "clflush %%fs:-128(%%eax)\n\t"
188 "clflush %%fs:-64(%%eax)\n\t"
189 "clflush %%fs:(%%eax)\n\t"
190 "clflush %%fs:64(%%eax)\n\t"
191
192 "clflush %%fs:-128(%%ebx)\n\t"
193
194 :: "b" (addr_lo+128+8*64), "c"(addr_lo+128),
195 "a"(addr_lo+128+4*64)
196 );
197
198}
199
200
201static __attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo)
202{
203 __asm__ volatile (
204 "outb %%al, $0xed\n\t" /* _EXECFENCE */
205 "clflush %%fs:-128(%%eax)\n\t"
206 "clflush %%fs:-64(%%eax)\n\t"
207 "clflush %%fs:(%%eax)\n\t"
208 "clflush %%fs:64(%%eax)\n\t"
209
210 "clflush %%fs:-128(%%edi)\n\t"
211 "clflush %%fs:-64(%%edi)\n\t"
212 "clflush %%fs:(%%edi)\n\t"
213 "clflush %%fs:64(%%edi)\n\t"
214
215 "clflush %%fs:-128(%%ebx)\n\t"
216 "clflush %%fs:-64(%%ebx)\n\t"
217 "clflush %%fs:(%%ebx)\n\t"
218 "clflush %%fs:64(%%ebx)\n\t"
219
220 "clflush %%fs:-128(%%ecx)\n\t"
221 "clflush %%fs:-64(%%ecx)\n\t"
222 "clflush %%fs:(%%ecx)\n\t"
223 "clflush %%fs:64(%%ecx)\n\t"
224
225 "clflush %%fs:-128(%%edx)\n\t"
226 "clflush %%fs:-64(%%edx)\n\t"
227
228 :: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
229 "d" (addr_lo +128+16*64), "a"(addr_lo+128),
230 "D"(addr_lo+128+4*64)
231 );
232}
233
234
235static void ReadL18TestPattern(u32 addr_lo)
236{
237 // set fs and use fs prefix to access the mem
238 __asm__ volatile (
239 "outb %%al, $0xed\n\t" /* _EXECFENCE */
240 "movl %%fs:-128(%%esi), %%eax\n\t" //TestAddr cache line
241 "movl %%fs:-64(%%esi), %%eax\n\t" //+1
242 "movl %%fs:(%%esi), %%eax\n\t" //+2
243 "movl %%fs:64(%%esi), %%eax\n\t" //+3
244
245 "movl %%fs:-128(%%edi), %%eax\n\t" //+4
246 "movl %%fs:-64(%%edi), %%eax\n\t" //+5
247 "movl %%fs:(%%edi), %%eax\n\t" //+6
248 "movl %%fs:64(%%edi), %%eax\n\t" //+7
249
250 "movl %%fs:-128(%%ebx), %%eax\n\t" //+8
251 "movl %%fs:-64(%%ebx), %%eax\n\t" //+9
252 "movl %%fs:(%%ebx), %%eax\n\t" //+10
253 "movl %%fs:64(%%ebx), %%eax\n\t" //+11
254
255 "movl %%fs:-128(%%ecx), %%eax\n\t" //+12
256 "movl %%fs:-64(%%ecx), %%eax\n\t" //+13
257 "movl %%fs:(%%ecx), %%eax\n\t" //+14
258 "movl %%fs:64(%%ecx), %%eax\n\t" //+15
259
260 "movl %%fs:-128(%%edx), %%eax\n\t" //+16
261 "movl %%fs:-64(%%edx), %%eax\n\t" //+17
262 "mfence\n\t"
263
264 :: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
265 "d" (addr_lo +128+16*64), "S"(addr_lo+128),
266 "D"(addr_lo+128+4*64)
267 );
268
269}
270
271
272static void ReadL9TestPattern(u32 addr_lo)
273{
274
275 // set fs and use fs prefix to access the mem
276 __asm__ volatile (
277 "outb %%al, $0xed\n\t" /* _EXECFENCE */
278
279 "movl %%fs:-128(%%ecx), %%eax\n\t" //TestAddr cache line
280 "movl %%fs:-64(%%ecx), %%eax\n\t" //+1
281 "movl %%fs:(%%ecx), %%eax\n\t" //+2
282 "movl %%fs:64(%%ecx), %%eax\n\t" //+3
283
284 "movl %%fs:-128(%%edx), %%eax\n\t" //+4
285 "movl %%fs:-64(%%edx), %%eax\n\t" //+5
286 "movl %%fs:(%%edx), %%eax\n\t" //+6
287 "movl %%fs:64(%%edx), %%eax\n\t" //+7
288
289 "movl %%fs:-128(%%ebx), %%eax\n\t" //+8
290 "mfence\n\t"
291
292 :: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128),
293 "d"(addr_lo+128+4*64)
294 );
295
296}
297
298
299static void ReadMaxRdLat1CLTestPattern_D(u32 addr)
300{
301 SetUpperFSbase(addr);
302
303 __asm__ volatile (
304 "outb %%al, $0xed\n\t" /* _EXECFENCE */
305 "movl %%fs:-128(%%esi), %%eax\n\t" //TestAddr cache line
306 "movl %%fs:-64(%%esi), %%eax\n\t" //+1
307 "movl %%fs:(%%esi), %%eax\n\t" //+2
308 "mfence\n\t"
309 :: "a"(0), "S"((addr<<8)+128)
310 );
311
312}
313
314
Myles Watson075fbe82010-04-15 05:19:29 +0000315static void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr)
Marc Jones8ae8c882007-12-19 01:32:08 +0000316{
317 SetUpperFSbase(addr);
318
319 __asm__ volatile (
320 "outb %%al, $0xed\n\t" /* _EXECFENCE */
321 "1:\n\t"
322 "movdqa (%3), %%xmm0\n\t"
323 "movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
324 "addl %1, %0\n\t"
325 "addl %1, %3\n\t"
326 "loop 1b\n\t"
327 "mfence\n\t"
328
329 :: "a" (addr<<8), "d" (16), "c" (3 * 4), "b"(buf)
330 );
331}
332
333
334static void FlushMaxRdLatTestPattern_D(u32 addr)
335{
336 /* Flush a pattern of 72 bit times (per DQ) from cache.
337 * This procedure is used to ensure cache miss on the next read training.
338 */
339
340 SetUpperFSbase(addr);
341
342 __asm__ volatile (
343 "outb %%al, $0xed\n\t" /* _EXECFENCE */
344 "clflush %%fs:-128(%%esi)\n\t" //TestAddr cache line
345 "clflush %%fs:-64(%%esi)\n\t" //+1
346 "clflush %%fs:(%%esi)\n\t" //+2
347 "mfence\n\t"
348
349 :: "S"((addr<<8)+128)
350 );
351}
352
353
Myles Watson075fbe82010-04-15 05:19:29 +0000354static u32 stream_to_int(u8 const *p)
Marc Jones8ae8c882007-12-19 01:32:08 +0000355{
356 int i;
357 u32 val;
358 u32 valx;
359
360 val = 0;
361
362 for(i=3; i>=0; i--) {
363 val <<= 8;
364 valx = *(p+i);
365 val |= valx;
366 }
367
368 return val;
369}
370
371
Stefan Reinauerd6532112010-04-16 00:31:44 +0000372#ifdef UNUSED_CODE
Myles Watson075fbe82010-04-15 05:19:29 +0000373static void oemSet_NB32(u32 addr, u32 val, u8 *valid)
Marc Jones8ae8c882007-12-19 01:32:08 +0000374{
375}
376
377
Myles Watson075fbe82010-04-15 05:19:29 +0000378static u32 oemGet_NB32(u32 addr, u8 *valid)
Marc Jones8ae8c882007-12-19 01:32:08 +0000379{
380 *valid = 0;
381 return 0xffffffff;
382}
Stefan Reinauerd6532112010-04-16 00:31:44 +0000383#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000384
385
Myles Watson075fbe82010-04-15 05:19:29 +0000386static u8 oemNodePresent_D(u8 Node, u8 *ret)
Marc Jones8ae8c882007-12-19 01:32:08 +0000387{
388 *ret = 0;
389 return 0;
390}