1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <bitops.h>
#include <cpu/amd/gx2def.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/cache.h>
#if 0
void
bug645(void){
msr_t msr;
rdmsr(CPU_ID_CONFIG);
msr.whatever |= ID_CONFIG_SERIAL_SET;
wrmsr(msr);
}
void
bug573(void){
msr_t msr;
msr = rdmsr(MC_GLD_MSR_PM);
msr.eax &= 0xfff3;
wrmsr(MC_GLD_MSR_PM);
}
#endif
static void
pcideadlock(void){
msr_t msr;
msr = rdmsr(CPU_DM_CONFIG0);
msr.hi &= ~(7<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
msr.hi |= (2<<DM_CONFIG0_UPPER_WSREQ_SHIFT);
msr.lo |= DM_CONFIG0_LOWER_MISSER_SET;
wrmsr(CPU_DM_CONFIG0, msr);
msr = rdmsr(CPU_IM_CONFIG);
msr.lo |= IM_CONFIG_LOWER_QWT_SET; /* interlock instruction fetches to WS regions with data accesses.
* This prevents in instruction fetch from going out to PCI if the
* data side is about to make a request.
*/
wrmsr(CPU_IM_CONFIG, msr);
/* write serialize memory hole to PCI. Need to to unWS when something is shadowed regardless of cachablility.*/
msr.lo = 0x021212121;
msr.hi = 0x021212121;
wrmsr( CPU_RCONF_A0_BF, msr);
wrmsr( CPU_RCONF_C0_DF, msr);
wrmsr( CPU_RCONF_E0_FF, msr);
}
/****************************************************************************/
/***/
/** CPUbug784*/
/***/
/** Bugtool #784 + #792*/
/***/
/** Fix CPUID instructions for < 3.0 CPUs*/
/***/
/** Entry:*/
/** Exit:*/
/** Modified:*/
/***/
/****************************************************************************/
void bug784(void){
msr_t msr;
// static char *name = "Geode by NSC";
/* we'll do this the stupid way, for now, but that's the string they want. NO ONE KNOWS why you
* would do this -- the OS can figure this type of stuff out!
*/
msr = rdmsr(0x3006);
msr.hi = 0x646f6547;
wrmsr(0x3006, msr);
msr = rdmsr(0x3007);
msr.hi = 0x79622065;
msr.lo = 0x43534e20;
wrmsr(0x3007, msr);
msr = rdmsr(0x3002);
wrmsr(0x3008, msr);
/* More CPUID to match AMD better. #792*/
msr = rdmsr(0x3009);
msr.hi = 0x0C0C0A13D;
msr.lo = 0x00000000;
wrmsr(0x3009, msr);
}
/* cpubug 1398: enable MC if we KNOW we have DDR*/
void
eng1398(void){
msr_t msr;
msr = rdmsr(MSR_GLCP+0x17);
if ((msr.lo & 0xff) < CPU_REV_2_0) {
msr = rdmsr(GLCP_SYS_RSTPLL);
if (msr.lo & (1<<RSTPPL_LOWER_SDRMODE_SHIFT))
return;
}
/* no bios to check, we just go for it? */
msr = rdmsr(MC_GLD_MSR_PM);
msr.lo |= 3; /* enable MC clock gating.*/
wrmsr(MC_GLD_MSR_PM, msr);
}
void
eng2900(void){
printk_err(" NOT DOING eng2900: only shown to be a windows problem\n");
#if 0
;**************************************************************************
;*
;* CPUbugIAENG2900
;*
;* Clear Quest IAENG00002900, VSS 118.150
;*
;* BTB issue causes blue screen in windows.
;*
;* Entry:
;* Exit:
;* Modified:
;*
;**************************************************************************
CPUbugIAENG2900 PROC NEAR PUBLIC
pushad
; Clear bit 43, disables the sysenter/sysexit in CPUID3
mov ecx, 3003h
RDMSR
and edx, 0FFFFF7FFh
WRMSR
mov cx, TOKEN_BTB_2900_SWAPSIF_ENABLE
NOSTACK bx, GetNVRAMValueBX
cmp ax, TVALUE_ENABLE
jne bug2900exit
;Disable enable_actions in DIAGCTL while setting up GLCP
mov ecx, MSR_GLCP + 005fh
xor edx, edx
xor eax, eax
WRMSR
;Changing DBGCLKCTL register to GeodeLink
mov ecx, MSR_GLCP + 0016h
xor edx, edx
xor eax, eax
WRMSR
mov ecx, MSR_GLCP + 0016h
xor edx, edx
mov eax, 02h
WRMSR
;The code below sets up the RedCloud to stall for 4 GeodeLink clocks when CPU is snooped.
;Because setting XSTATE to 0 overrides any other XSTATE action, the code will always
;stall for 4 GeodeLink clocks after a snoop request goes away even if it occured a clock or two
;later than a different snoop; the stall signal will never 'glitch high' for
;only one or two CPU clocks with this code.
;Send mb0 port 3 requests to upper GeodeLink diag bits [63:32]
mov ecx, MSR_GLIU0 + 2005h
xor edx, edx
mov eax, 80338041h
WRMSR
;set5m watches request ready from mb0 to CPU (snoop)
mov ecx, MSR_GLCP + 0045h
mov edx, 5ad68000h
xor eax, eax
WRMSR
;SET4M will be high when state is idle (XSTATE=11)
mov ecx, MSR_GLCP + 0044h
xor edx, edx
mov eax, 0140h
WRMSR
;SET5n to watch for processor stalled state
mov ecx, MSR_GLCP + 004Dh
mov edx, 2000h
xor eax, eax
WRMSR
;Writing action number 13: XSTATE=0 to occur when CPU is snooped unless we're stalled
mov ecx, MSR_GLCP + 0075h
xor edx, edx
mov eax, 00400000h
WRMSR
;Writing action number 11: inc XSTATE every GeodeLink clock unless we're idle
mov ecx, MSR_GLCP + 0073h
xor edx, edx
mov eax, 30000h
WRMSR
;Writing action number 5: STALL_CPU_PIPE when exitting idle state or not in idle state
mov ecx, MSR_GLCP + 006Dh
xor edx, edx
mov eax, 00430000h
WRMSR
;Writing DIAGCTL Register to enable the stall action and to let set5m watch the upper GeodeLink diag bits.
mov ecx, MSR_GLCP + 005fh
xor edx, edx
mov eax, 80004000h
WRMSR
bug2900exit:
popad
ret
CPUbugIAENG2900 ENDP
#endif
}
void bug118253(void){
msr_t msr;
msr = rdmsr(GLPCI_SPARE);
msr.lo &= ~GLPCI_SPARE_LOWER_PPC_SET;
wrmsr(GLPCI_SPARE, msr);
}
void
bug118339(void) {
printk_err("This is OPTIONAL BIOS-ENABLED ... ignore for now\n");
#if 0
PROC NEAR PUBLIC
pushad
mov cx, TOKEN_VGTEAR_118339_SWAPSIF_ENABLE
NOSTACK bx, GetNVRAMValueBX
cmp ax, TVALUE_ENABLE
jne bug118339exit
;Disable enable_actions in DIAGCTL while setting up GLCP
mov ecx, MSR_GLCP + 005fh
xor edx, edx
xor eax, eax
WRMSR
; SET2M fires if VG pri is odd (3, not 2) and Ystate=0
mov ecx, MSR_GLCP + 042h
; mov edx, 2d6b8000h
mov edx, 596b8000h
mov eax, 00000a00h
WRMSR
; SET3M fires if MBUS changed and VG pri is odd
mov ecx, MSR_GLCP + 043h
mov edx, 596b8040h
xor eax, eax
WRMSR
; Put VG request data on lower diag bus
mov ecx, MSR_GLIU0 + 2005h
xor edx, edx
mov eax, 80338041h
WRMSR
; Increment Y state if SET3M if true
mov ecx, MSR_GLCP + 074h
xor edx, edx
mov eax, 0000c000h
WRMSR
; Set up MBUS action to PRI=3 read of MBIU
mov ecx, MSR_GLCP + 020h
mov edx, 0000d863h
mov eax, 20002000h
WRMSR
; Trigger MBUS action if VG=pri3 and Y=0, this blocks most PCI
mov ecx, MSR_GLCP + 071h
xor edx, edx
mov eax, 00000c00h
WRMSR
;Writing DIAGCTL
mov ecx, MSR_GLCP + 005fh
xor edx, edx
mov eax, 80004000h
WRMSR
; Code to enable FS2 even when BTB and VGTEAR SWAPSiFs are enabled
; As per Todd Roberts in PBz1094 and PBz1095
; Moved from CPUREG to CPUBUG per Tom Sylla
mov ecx, 04C000042h ; GLCP SETMCTL Register
rdmsr
or edx, 8 ; Bit 35 = MCP_IN
wrmsr
bug118339exit:
popad
ret
CPUbug118339 ENDP
#endif
}
/****************************************************************************/
/***/
/** DisableMemoryReorder*/
/***/
/** PBZ 3659:*/
/** The MC reordered transactions incorrectly and breaks coherency.*/
/** Disable reording and take a potential performance hit.*/
/** This is safe to do here and not in MC init since there is nothing*/
/** to maintain coherency with and the cache is not enabled yet.*/
/***/
/***/
/** Entry:*/
/** Exit:*/
/** Modified:*/
/***/
/****************************************************************************/
void
disablememoryreadorder(void) {
msr_t msr;
msr = rdmsr(MC_CF8F_DATA);
msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
wrmsr(MC_CF8F_DATA, msr);
}
void
cpubug(void){
msr_t msr;
int rev;
msr = rdmsr(GLCP_CHIP_REVID);
rev = msr.lo & 0xff;
if (rev < 0x20) {
printk_err("%s: rev < 0x20! bailing!\n");
return;
}
printk_debug("Doing cpubug fixes for rev 0x%x\n", rev);
switch(rev)
{
case 0x20:
pcideadlock();
eng1398();
/* cs 5530 bug; ignore
bug752();
*/
break;
case 0x21:
pcideadlock();
eng1398();
eng2900();
bug118339();
break;
case 0x22:
case 0x30:
break;
default:
printk_err("unknown rev %x, bailing\n", rev);
return;
}
bug784();
bug118253();
disablememoryreadorder();
printk_debug("Done cpubug fixes \n");
}
|