xref: /freebsd/sys/amd64/amd64/initcpu.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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.12 1998/02/04 03:47:14 eivind Exp $
30  */
31 
32 #include "opt_cpu.h"
33 #include "opt_failsafe.h"
34 
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 
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 I686_CPU
56 static void	init_6x86MX(void);
57 static void	init_ppro(void);
58 #endif
59 
60 #ifdef I486_CPU
61 /*
62  * IBM Blue Lightning
63  */
64 static void
65 init_bluelightning(void)
66 {
67 	u_long	eflags;
68 
69 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
70 	need_post_dma_flush = 1;
71 #endif
72 
73 	eflags = read_eflags();
74 	disable_intr();
75 
76 	load_cr0(rcr0() | CR0_CD | CR0_NW);
77 	invd();
78 
79 #ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
80 	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
81 #else
82 	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
83 #endif
84 	/* Enables 13MB and 0-640KB cache. */
85 	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
86 #ifdef CPU_BLUELIGHTNING_3X
87 	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
88 #else
89 	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
90 #endif
91 
92 	/* Enable caching in CR0. */
93 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
94 	invd();
95 	write_eflags(eflags);
96 }
97 
98 /*
99  * Cyrix 486SLC/DLC/SR/DR series
100  */
101 static void
102 init_486dlc(void)
103 {
104 	u_long	eflags;
105 	u_char	ccr0;
106 
107 	eflags = read_eflags();
108 	disable_intr();
109 	invd();
110 
111 	ccr0 = read_cyrix_reg(CCR0);
112 #ifndef CYRIX_CACHE_WORKS
113 	ccr0 |= CCR0_NC1 | CCR0_BARB;
114 	write_cyrix_reg(CCR0, ccr0);
115 	invd();
116 #else
117 	ccr0 &= ~CCR0_NC0;
118 #ifndef CYRIX_CACHE_REALLY_WORKS
119 	ccr0 |= CCR0_NC1 | CCR0_BARB;
120 #else
121 	ccr0 |= CCR0_NC1;
122 #endif
123 #ifdef CPU_DIRECT_MAPPED_CACHE
124 	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
125 #endif
126 	write_cyrix_reg(CCR0, ccr0);
127 
128 	/* Clear non-cacheable region. */
129 	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
130 	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
131 	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
132 	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
133 
134 	write_cyrix_reg(0, 0);	/* dummy write */
135 
136 	/* Enable caching in CR0. */
137 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
138 	invd();
139 #endif /* !CYRIX_CACHE_WORKS */
140 	write_eflags(eflags);
141 }
142 
143 
144 /*
145  * Cyrix 486S/DX series
146  */
147 static void
148 init_cy486dx(void)
149 {
150 	u_long	eflags;
151 	u_char	ccr2;
152 
153 	eflags = read_eflags();
154 	disable_intr();
155 	invd();
156 
157 	ccr2 = read_cyrix_reg(CCR2);
158 #ifdef CPU_SUSP_HLT
159 	ccr2 |= CCR2_SUSP_HLT;
160 #endif
161 	write_cyrix_reg(CCR2, ccr2);
162 	write_eflags(eflags);
163 }
164 
165 
166 /*
167  * Cyrix 5x86
168  */
169 static void
170 init_5x86(void)
171 {
172 	u_long	eflags;
173 	u_char	ccr2, ccr3, ccr4, pcr0;
174 
175 	eflags = read_eflags();
176 	disable_intr();
177 
178 	load_cr0(rcr0() | CR0_CD | CR0_NW);
179 	wbinvd();
180 
181 	(void)read_cyrix_reg(CCR3);		/* dummy */
182 
183 	/* Initialize CCR2. */
184 	ccr2 = read_cyrix_reg(CCR2);
185 	ccr2 |= CCR2_WB;
186 #ifdef CPU_SUSP_HLT
187 	ccr2 |= CCR2_SUSP_HLT;
188 #else
189 	ccr2 &= ~CCR2_SUSP_HLT;
190 #endif
191 	ccr2 |= CCR2_WT1;
192 	write_cyrix_reg(CCR2, ccr2);
193 
194 	/* Initialize CCR4. */
195 	ccr3 = read_cyrix_reg(CCR3);
196 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
197 
198 	ccr4 = read_cyrix_reg(CCR4);
199 	ccr4 |= CCR4_DTE;
200 	ccr4 |= CCR4_MEM;
201 #ifdef CPU_FASTER_5X86_FPU
202 	ccr4 |= CCR4_FASTFPE;
203 #else
204 	ccr4 &= ~CCR4_FASTFPE;
205 #endif
206 	ccr4 &= ~CCR4_IOMASK;
207 	/********************************************************************
208 	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
209 	 * should be 0 for errata fix.
210 	 ********************************************************************/
211 #ifdef CPU_IORT
212 	ccr4 |= CPU_IORT & CCR4_IOMASK;
213 #endif
214 	write_cyrix_reg(CCR4, ccr4);
215 
216 	/* Initialize PCR0. */
217 	/****************************************************************
218 	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
219 	 * BTB_EN might make your system unstable.
220 	 ****************************************************************/
221 	pcr0 = read_cyrix_reg(PCR0);
222 #ifdef CPU_RSTK_EN
223 	pcr0 |= PCR0_RSTK;
224 #else
225 	pcr0 &= ~PCR0_RSTK;
226 #endif
227 #ifdef CPU_BTB_EN
228 	pcr0 |= PCR0_BTB;
229 #else
230 	pcr0 &= ~PCR0_BTB;
231 #endif
232 #ifdef CPU_LOOP_EN
233 	pcr0 |= PCR0_LOOP;
234 #else
235 	pcr0 &= ~PCR0_LOOP;
236 #endif
237 
238 	/****************************************************************
239 	 * WARNING: if you use a memory mapped I/O device, don't use
240 	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
241 	 * I/O access.
242 	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
243 	 ****************************************************************/
244 #ifdef CPU_DISABLE_5X86_LSSER
245 	pcr0 &= ~PCR0_LSSER;
246 #else
247 	pcr0 |= PCR0_LSSER;
248 #endif
249 	write_cyrix_reg(PCR0, pcr0);
250 
251 	/* Restore CCR3. */
252 	write_cyrix_reg(CCR3, ccr3);
253 
254 	(void)read_cyrix_reg(0x80);		/* dummy */
255 
256 	/* Unlock NW bit in CR0. */
257 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
258 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
259 	/* Lock NW bit in CR0. */
260 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
261 
262 	write_eflags(eflags);
263 }
264 
265 #ifdef CPU_I486_ON_386
266 /*
267  * There are i486 based upgrade products for i386 machines.
268  * In this case, BIOS doesn't enables CPU cache.
269  */
270 void
271 init_i486_on_386(void)
272 {
273 	u_long	eflags;
274 
275 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
276 	need_post_dma_flush = 1;
277 #endif
278 
279 	eflags = read_eflags();
280 	disable_intr();
281 
282 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
283 
284 	write_eflags(eflags);
285 }
286 #endif
287 
288 /*
289  * Cyrix 6x86
290  *
291  * XXX - What should I do here?  Please let me know.
292  */
293 static void
294 init_6x86(void)
295 {
296 	u_long	eflags;
297 	u_char	ccr3, ccr4;
298 
299 	eflags = read_eflags();
300 	disable_intr();
301 
302 	load_cr0(rcr0() | CR0_CD | CR0_NW);
303 	wbinvd();
304 
305 	/* Initialize CCR0. */
306 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
307 
308 	/* Initialize CCR1. */
309 #ifdef CPU_CYRIX_NO_LOCK
310 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
311 #else
312 #ifdef FAILSAFE
313 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
314 #endif
315 #endif
316 
317 	/* Initialize CCR2. */
318 #ifdef CPU_SUSP_HLT
319 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
320 #else
321 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
322 #endif
323 
324 	ccr3 = read_cyrix_reg(CCR3);
325 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
326 
327 	/* Initialize CCR4. */
328 	ccr4 = read_cyrix_reg(CCR4);
329 	ccr4 |= CCR4_DTE;
330 	ccr4 &= ~CCR4_IOMASK;
331 #ifdef CPU_IORT
332 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
333 #else
334 	write_cyrix_reg(CCR4, ccr4 | 7);
335 #endif
336 
337 	/* Initialize CCR5. */
338 #ifdef CPU_WT_ALLOC
339 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
340 #endif
341 
342 	/* Restore CCR3. */
343 	write_cyrix_reg(CCR3, ccr3);
344 
345 	/* Unlock NW bit in CR0. */
346 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
347 
348 	/*
349 	 * Earlier revision of the 6x86 CPU could crash the system if
350 	 * L1 cache is in write-back mode.
351 	 */
352 	if ((cyrix_did & 0xff00) > 0x1600)
353 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
354 	else {
355 		/* Revision 2.6 and lower. */
356 #ifdef CYRIX_CACHE_REALLY_WORKS
357 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
358 #else
359 		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
360 #endif
361 	}
362 
363 	/* Lock NW bit in CR0. */
364 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
365 
366 	write_eflags(eflags);
367 }
368 #endif /* I486_CPU */
369 
370 #ifdef I686_CPU
371 /*
372  * Cyrix 6x86MX (code-named M2)
373  *
374  * XXX - What should I do here?  Please let me know.
375  */
376 static void
377 init_6x86MX(void)
378 {
379 	u_long	eflags;
380 	u_char	ccr3, ccr4;
381 
382 	eflags = read_eflags();
383 	disable_intr();
384 
385 	load_cr0(rcr0() | CR0_CD | CR0_NW);
386 	wbinvd();
387 
388 	/* Initialize CCR0. */
389 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
390 
391 	/* Initialize CCR1. */
392 #ifdef CPU_CYRIX_NO_LOCK
393 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
394 #else
395 #ifdef FAILSAFE
396 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
397 #endif
398 #endif
399 
400 	/* Initialize CCR2. */
401 #ifdef CPU_SUSP_HLT
402 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
403 #else
404 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
405 #endif
406 
407 	ccr3 = read_cyrix_reg(CCR3);
408 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
409 
410 	/* Initialize CCR4. */
411 	ccr4 = read_cyrix_reg(CCR4);
412 	ccr4 &= ~CCR4_IOMASK;
413 #ifdef CPU_IORT
414 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
415 #else
416 	write_cyrix_reg(CCR4, ccr4 | 7);
417 #endif
418 
419 	/* Initialize CCR5. */
420 #ifdef CPU_WT_ALLOC
421 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
422 #endif
423 
424 	/* Restore CCR3. */
425 	write_cyrix_reg(CCR3, ccr3);
426 
427 	/* Unlock NW bit in CR0. */
428 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
429 
430 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
431 
432 	/* Lock NW bit in CR0. */
433 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
434 
435 	write_eflags(eflags);
436 }
437 
438 static void
439 init_ppro(void)
440 {
441 #ifndef SMP
442 	quad_t	apicbase;
443 
444 	/*
445 	 * Local APIC should be diabled in UP kernel.
446 	 */
447 	apicbase = rdmsr(0x1b);
448 	apicbase &= ~0x800LL;
449 	wrmsr(0x1b, apicbase);
450 #endif
451 }
452 #endif /* I686_CPU */
453 
454 void
455 initializecpu(void)
456 {
457 
458 	switch (cpu) {
459 #ifdef I486_CPU
460 	case CPU_BLUE:
461 		init_bluelightning();
462 		break;
463 	case CPU_486DLC:
464 		init_486dlc();
465 		break;
466 	case CPU_CY486DX:
467 		init_cy486dx();
468 		break;
469 	case CPU_M1SC:
470 		init_5x86();
471 		break;
472 #ifdef CPU_I486_ON_386
473 	case CPU_486:
474 		init_i486_on_386();
475 		break;
476 #endif
477 	case CPU_M1:
478 		init_6x86();
479 		break;
480 #endif /* I486_CPU */
481 #ifdef I686_CPU
482 	case CPU_M2:
483 		init_6x86MX();
484 		break;
485 	case CPU_686:
486 		if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
487 			(cpu_id & 0xff0) == 0x610)
488 			init_ppro();
489 		break;
490 #endif
491 	default:
492 		break;
493 	}
494 
495 #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
496 	/*
497 	 * OS should flush L1 cahce by itself because no PC-98 supports
498 	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
499 	 * when need_pre_dma_flush = 1, use invd instruction after DMA
500 	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
501 	 * product support hardware cache control, you can add
502 	 * UPGRADE_CPU_HW_CACHE option in your kernel configuration file.
503 	 * This option elminate unneeded cache flush instruction.
504 	 */
505 	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
506 		switch (cpu) {
507 #ifdef I486_CPU
508 		case CPU_486DLC:
509 			need_post_dma_flush = 1;
510 			break;
511 		case CPU_M1SC:
512 			need_pre_dma_flush = 1;
513 			break;
514 #endif
515 		default:
516 			break;
517 		}
518 	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
519 		switch (cpu_id & 0xFF0) {
520 		case 0x470:		/* Enhanced Am486DX2 WB */
521 		case 0x490:		/* Enhanced Am486DX4 WB */
522 		case 0x4F0:		/* Am5x86 WB */
523 			need_pre_dma_flush = 1;
524 			break;
525 		}
526 	} else if (strcmp(cpu_vendor, "IBM") == 0) {
527 		need_post_dma_flush = 1;
528 	} else {
529 #ifdef CPU_I486_ON_386
530 		need_pre_dma_flush = 1;
531 #endif
532 	}
533 #endif /* PC98 && !UPGRADE_CPU_HW_CACHE */
534 }
535 
536 #include "opt_ddb.h"
537 #ifdef DDB
538 #include <ddb/ddb.h>
539 
540 DB_SHOW_COMMAND(cyrixreg, cyrixreg)
541 {
542 	u_long	eflags;
543 	u_int	cr0;
544 	u_char	ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, pcr0;
545 
546 	cr0 = rcr0();
547 	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
548 		eflags = read_eflags();
549 		disable_intr();
550 
551 
552 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
553 			ccr0 = read_cyrix_reg(CCR0);
554 		}
555 		ccr1 = read_cyrix_reg(CCR1);
556 		ccr2 = read_cyrix_reg(CCR2);
557 		ccr3 = read_cyrix_reg(CCR3);
558 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
559 			write_cyrix_reg(CCR3, CCR3_MAPEN0);
560 			ccr4 = read_cyrix_reg(CCR4);
561 			if ((cpu == CPU_M1) || (cpu == CPU_M2))
562 				ccr5 = read_cyrix_reg(CCR5);
563 			else
564 				pcr0 = read_cyrix_reg(PCR0);
565 			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
566 		}
567 		write_eflags(eflags);
568 
569 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
570 			printf("CCR0=%x, ", (u_int)ccr0);
571 
572 		printf("CCR1=%x, CCR2=%x, CCR3=%x",
573 			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
574 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
575 			printf(", CCR4=%x, ", (u_int)ccr4);
576 			if (cpu == CPU_M1SC)
577 				printf("PCR0=%x\n", pcr0);
578 			else
579 				printf("CCR5=%x\n", ccr5);
580 		}
581 	}
582 	printf("CR0=%x\n", cr0);
583 }
584 #endif /* DDB */
585