xref: /freebsd/sys/amd64/amd64/initcpu.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
1 /*
2  * Copyright (c) KATO Takenori, 1997.
3  *
4  * All rights reserved.  Unpublished rights reserved under the copyright
5  * laws of Japan.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer as
13  *    the first lines of this file unmodified.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *		$Id: initcpu.c,v 1.5 1997/05/31 08:45:24 kato Exp $
30  */
31 
32 #include "opt_cpu.h"
33 
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 
38 #include <machine/cpu.h>
39 #include <machine/cputypes.h>
40 #include <machine/md_var.h>
41 #include <machine/specialreg.h>
42 
43 void initializecpu(void);
44 #ifdef I486_CPU
45 static void init_5x86(void);
46 static void init_bluelightning(void);
47 static void init_486dlc(void);
48 static void init_cy486dx(void);
49 #ifdef CPU_I486_ON_386
50 static void init_i486_on_386(void);
51 #endif
52 static void init_6x86(void);
53 #endif /* I486_CPU */
54 
55 #ifdef I586_CPU
56 static void	init_6x86MX(void);
57 #endif
58 
59 #ifdef I486_CPU
60 /*
61  * IBM Blue Lightning
62  */
63 static void
64 init_bluelightning(void)
65 {
66 	u_long	eflags;
67 
68 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
69 	need_post_dma_flush = 1;
70 #endif
71 
72 	eflags = read_eflags();
73 	disable_intr();
74 
75 	load_cr0(rcr0() | CR0_CD | CR0_NW);
76 	invd();
77 
78 #ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
79 	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
80 #else
81 	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
82 #endif
83 	/* Enables 13MB and 0-640KB cache. */
84 	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
85 #ifdef CPU_BLUELIGHTNING_3X
86 	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
87 #else
88 	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
89 #endif
90 
91 	/* Enable caching in CR0. */
92 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
93 	invd();
94 	write_eflags(eflags);
95 }
96 
97 /*
98  * Cyrix 486SLC/DLC/SR/DR series
99  */
100 static void
101 init_486dlc(void)
102 {
103 	u_long	eflags;
104 	u_char	ccr0;
105 
106 	eflags = read_eflags();
107 	disable_intr();
108 	invd();
109 
110 	ccr0 = read_cyrix_reg(CCR0);
111 #ifndef CYRIX_CACHE_WORKS
112 	ccr0 |= CCR0_NC1 | CCR0_BARB;
113 	write_cyrix_reg(CCR0, ccr0);
114 	invd();
115 #else
116 	ccr0 &= ~CCR0_NC0;
117 #ifndef CYRIX_CACHE_REALLY_WORKS
118 	ccr0 |= CCR0_NC1 | CCR0_BARB;
119 #else
120 	ccr0 |= CCR0_NC1;
121 #endif
122 #ifdef CPU_DIRECT_MAPPED_CACHE
123 	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
124 #endif
125 	write_cyrix_reg(CCR0, ccr0);
126 
127 	/* Clear non-cacheable region. */
128 	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
129 	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
130 	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
131 	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
132 
133 	write_cyrix_reg(0, 0);	/* dummy write */
134 
135 	/* Enable caching in CR0. */
136 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
137 	invd();
138 #endif /* !CYRIX_CACHE_WORKS */
139 	write_eflags(eflags);
140 }
141 
142 
143 /*
144  * Cyrix 486S/DX series
145  */
146 static void
147 init_cy486dx(void)
148 {
149 	u_long	eflags;
150 	u_char	ccr2;
151 
152 	eflags = read_eflags();
153 	disable_intr();
154 	invd();
155 
156 	ccr2 = read_cyrix_reg(CCR2);
157 #ifdef SUSP_HLT
158 	ccr2 |= CCR2_SUSP_HTL;
159 #endif
160 	write_cyrix_reg(CCR2, ccr2);
161 	write_eflags(eflags);
162 }
163 
164 
165 /*
166  * Cyrix 5x86
167  */
168 static void
169 init_5x86(void)
170 {
171 	u_long	eflags;
172 	u_char	ccr2, ccr3, ccr4, pcr0;
173 
174 	eflags = read_eflags();
175 	disable_intr();
176 
177 	load_cr0(rcr0() | CR0_CD | CR0_NW);
178 	wbinvd();
179 
180 	(void)read_cyrix_reg(CCR3);		/* dummy */
181 
182 	/* Initialize CCR2. */
183 	ccr2 = read_cyrix_reg(CCR2);
184 	ccr2 |= CCR2_WB;
185 #ifdef CPU_SUSP_HLT
186 	ccr2 |= CCR2_SUSP_HLT;
187 #else
188 	ccr2 &= ~CCR2_SUSP_HLT;
189 #endif
190 	ccr2 |= CCR2_WT1;
191 	write_cyrix_reg(CCR2, ccr2);
192 
193 	/* Initialize CCR4. */
194 	ccr3 = read_cyrix_reg(CCR3);
195 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
196 
197 	ccr4 = read_cyrix_reg(CCR4);
198 	ccr4 |= CCR4_DTE;
199 	ccr4 |= CCR4_MEM;
200 #ifdef CPU_FASTER_5X86_FPU
201 	ccr4 |= CCR4_FASTFPE;
202 #else
203 	ccr4 &= ~CCR4_FASTFPE;
204 #endif
205 	ccr4 &= ~CCR4_IOMASK;
206 	/********************************************************************
207 	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
208 	 * should be 0 for errata fix.
209 	 ********************************************************************/
210 #ifdef CPU_IORT
211 	ccr4 |= CPU_IORT & CCR4_IOMASK;
212 #endif
213 	write_cyrix_reg(CCR4, ccr4);
214 
215 	/* Initialize PCR0. */
216 	/****************************************************************
217 	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
218 	 * BTB_EN might make your system unstable.
219 	 ****************************************************************/
220 	pcr0 = read_cyrix_reg(PCR0);
221 #ifdef CPU_RSTK_EN
222 	pcr0 |= PCR0_RSTK;
223 #else
224 	pcr0 &= ~PCR0_RSTK;
225 #endif
226 #ifdef CPU_BTB_EN
227 	pcr0 |= PCR0_BTB;
228 #else
229 	pcr0 &= ~PCR0_BTB;
230 #endif
231 #ifdef CPU_LOOP_EN
232 	pcr0 |= PCR0_LOOP;
233 #else
234 	pcr0 &= ~PCR0_LOOP;
235 #endif
236 
237 	/****************************************************************
238 	 * WARNING: if you use a memory mapped I/O device, don't use
239 	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
240 	 * I/O access.
241 	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
242 	 ****************************************************************/
243 #ifdef CPU_DISABLE_5X86_LSSER
244 	pcr0 &= ~PCR0_LSSER;
245 #else
246 	pcr0 |= PCR0_LSSER;
247 #endif
248 	write_cyrix_reg(PCR0, pcr0);
249 
250 	/* Restore CCR3. */
251 	write_cyrix_reg(CCR3, ccr3);
252 
253 	(void)read_cyrix_reg(0x80);		/* dummy */
254 
255 	/* Unlock NW bit in CR0. */
256 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
257 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
258 	/* Lock NW bit in CR0. */
259 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
260 
261 	write_eflags(eflags);
262 }
263 
264 #ifdef CPU_I486_ON_386
265 /*
266  * There are i486 based upgrade products for i386 machines.
267  * In this case, BIOS doesn't enables CPU cache.
268  */
269 void
270 init_i486_on_386(void)
271 {
272 	u_long	eflags;
273 
274 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
275 	need_post_dma_flush = 1;
276 #endif
277 
278 	eflags = read_eflags();
279 	disable_intr();
280 
281 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
282 
283 	write_eflags(eflags);
284 }
285 #endif
286 
287 /*
288  * Cyrix 6x86
289  *
290  * XXX - What should I do here?  Please let me know.
291  */
292 static void
293 init_6x86(void)
294 {
295 	u_long	eflags;
296 	u_char	ccr3, ccr4;
297 
298 	eflags = read_eflags();
299 	disable_intr();
300 
301 	load_cr0(rcr0() | CR0_CD | CR0_NW);
302 	wbinvd();
303 
304 	/* Initialize CCR0. */
305 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
306 
307 	/* Initialize CCR2. */
308 #ifdef CPU_SUSP_HLT
309 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
310 #else
311 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
312 #endif
313 
314 	ccr3 = read_cyrix_reg(CCR3);
315 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
316 
317 	/* Initialize CCR4. */
318 	ccr4 = read_cyrix_reg(CCR4);
319 	ccr4 |= CCR4_DTE;
320 	ccr4 &= ~CCR4_IOMASK;
321 #ifdef CPU_IORT
322 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
323 #else
324 	write_cyrix_reg(CCR4, ccr4 | 7);
325 #endif
326 
327 	/* Restore CCR3. */
328 	write_cyrix_reg(CCR3, ccr3);
329 
330 	/* Unlock NW bit in CR0. */
331 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
332 
333 	/*
334 	 * Earlier revision of the 6x86 CPU could crash the system if
335 	 * L1 cache is in write-back mode.
336 	 */
337 	if ((cyrix_did & 0xff00) > 0x1600)
338 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
339 	else {
340 		/* Revision 2.6 and lower. */
341 #ifdef CYRIX_CACHE_REALLY_WORKS
342 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
343 #else
344 		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
345 #endif
346 	}
347 
348 	/* Lock NW bit in CR0. */
349 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
350 
351 	write_eflags(eflags);
352 }
353 #endif /* I486_CPU */
354 
355 #ifdef I586_CPU
356 /*
357  * Cyrix 6x86MX (code-named M2)
358  *
359  * XXX - What should I do here?  Please let me know.
360  */
361 static void
362 init_6x86MX(void)
363 {
364 	u_long	eflags;
365 	u_char	ccr3, ccr4;
366 
367 	eflags = read_eflags();
368 	disable_intr();
369 
370 	load_cr0(rcr0() | CR0_CD | CR0_NW);
371 	wbinvd();
372 
373 	/* Initialize CCR0. */
374 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
375 
376 	/* Initialize CCR2. */
377 #ifdef CPU_SUSP_HLT
378 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
379 #else
380 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
381 #endif
382 
383 	ccr3 = read_cyrix_reg(CCR3);
384 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
385 
386 	/* Initialize CCR4. */
387 	ccr4 = read_cyrix_reg(CCR4);
388 	ccr4 &= ~CCR4_IOMASK;
389 #ifdef CPU_IORT
390 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
391 #else
392 	write_cyrix_reg(CCR4, ccr4 | 7);
393 #endif
394 
395 	/* Restore CCR3. */
396 	write_cyrix_reg(CCR3, ccr3);
397 
398 	/* Unlock NW bit in CR0. */
399 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
400 
401 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
402 
403 	/* Lock NW bit in CR0. */
404 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
405 
406 	write_eflags(eflags);
407 }
408 #endif /* I586_CPU */
409 
410 void
411 initializecpu(void)
412 {
413 
414 	switch (cpu) {
415 #ifdef I486_CPU
416 	case CPU_BLUE:
417 		init_bluelightning();
418 		break;
419 	case CPU_486DLC:
420 		init_486dlc();
421 		break;
422 	case CPU_CY486DX:
423 		init_cy486dx();
424 		break;
425 	case CPU_M1SC:
426 		init_5x86();
427 		break;
428 #ifdef CPU_I486_ON_386
429 	case CPU_486:
430 		init_i486_on_386();
431 		break;
432 #endif
433 	case CPU_M1:
434 		init_6x86();
435 		break;
436 #endif /* I486_CPU */
437 #ifdef I586_CPU
438 	case CPU_M2:
439 		init_6x86MX();
440 		break;
441 #endif
442 	default:
443 		break;
444 	}
445 
446 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
447 	/*
448 	 * OS should flush L1 cahce by itself because no PC-98 supports
449 	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
450 	 * when need_pre_dma_flush = 1, use invd instruction after DMA
451 	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
452 	 * product support hardware cache control, you can add
453 	 * UPGRADE_CPU_HW_CACHE option in your kernel configuration file.
454 	 * This option elminate unneeded cache flush instruction.
455 	 */
456 	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
457 		switch (cpu) {
458 #ifdef I486_CPU
459 		case CPU_486DLC:
460 			need_post_dma_flush = 1;
461 			break;
462 		case CPU_M1SC:
463 			need_pre_dma_flush = 1;
464 			break;
465 #endif
466 		default:
467 			break;
468 		}
469 	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
470 		switch (cpu_id & 0xFF0) {
471 		case 0x470:		/* Enhanced Am486DX2 WB */
472 		case 0x490:		/* Enhanced Am486DX4 WB */
473 		case 0x4F0:		/* Am5x86 WB */
474 			need_pre_dma_flush = 1;
475 			break;
476 		}
477 	} else if (strcmp(cpu_vendor, "IBM") == 0) {
478 		need_post_dma_flush = 1;
479 	} else {
480 #ifdef CPU_I486_ON_386
481 		need_pre_dma_flush = 1;
482 #endif
483 	}
484 #endif /* PC98 && !UPGRADE_CPU_HW_CACHE */
485 }
486 
487 #include "opt_ddb.h"
488 #ifdef DDB
489 #include <ddb/ddb.h>
490 
491 DB_SHOW_COMMAND(cyrixreg, cyrixreg)
492 {
493 	u_long	eflags;
494 	u_int	cr0;
495 	u_char	ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, pcr0;
496 
497 	cr0 = rcr0();
498 	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
499 		eflags = read_eflags();
500 		disable_intr();
501 
502 
503 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
504 			ccr0 = read_cyrix_reg(CCR0);
505 		}
506 		ccr1 = read_cyrix_reg(CCR1);
507 		ccr2 = read_cyrix_reg(CCR2);
508 		ccr3 = read_cyrix_reg(CCR3);
509 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) {
510 			write_cyrix_reg(CCR3, CCR3_MAPEN0);
511 			ccr4 = read_cyrix_reg(CCR4);
512 			if (cpu == CPU_M1)
513 				ccr5 = read_cyrix_reg(CCR5);
514 			else
515 				pcr0 = read_cyrix_reg(PCR0);
516 			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
517 		}
518 		write_eflags(eflags);
519 
520 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
521 			printf("CCR0=%x, ", (u_int)ccr0);
522 
523 		printf("CCR1=%x, CCR2=%x, CCR3=%x",
524 			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
525 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) {
526 			printf(", CCR4=%x, ", (u_int)ccr4);
527 			if (cpu == CPU_M1)
528 				printf("CCR5=%x\n", ccr5);
529 			else
530 				printf("PCR0=%x\n", pcr0);
531 		}
532 	}
533 	printf("CR0=%x\n", cr0);
534 }
535 #endif /* DDB */
536