initcpu.c revision 151348
1/*-
2 * Copyright (c) KATO Takenori, 1997, 1998.
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
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/i386/i386/initcpu.c 151348 2005-10-14 22:52:01Z jkim $");
32
33#include "opt_cpu.h"
34
35#include <sys/param.h>
36#include <sys/kernel.h>
37#include <sys/systm.h>
38#include <sys/sysctl.h>
39
40#include <machine/cputypes.h>
41#include <machine/md_var.h>
42#include <machine/specialreg.h>
43
44#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
45#define CPU_ENABLE_SSE
46#endif
47
48void initializecpu(void);
49#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
50void	enable_K5_wt_alloc(void);
51void	enable_K6_wt_alloc(void);
52void	enable_K6_2_wt_alloc(void);
53#endif
54
55#ifdef I486_CPU
56static void init_5x86(void);
57static void init_bluelightning(void);
58static void init_486dlc(void);
59static void init_cy486dx(void);
60#ifdef CPU_I486_ON_386
61static void init_i486_on_386(void);
62#endif
63static void init_6x86(void);
64#endif /* I486_CPU */
65
66#ifdef I686_CPU
67static void	init_6x86MX(void);
68static void	init_ppro(void);
69static void	init_mendocino(void);
70#endif
71
72static int	hw_instruction_sse;
73SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
74    &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
75
76/* Must *NOT* be BSS or locore will bzero these after setting them */
77int	cpu = 0;		/* Are we 386, 386sx, 486, etc? */
78u_int	cpu_feature = 0;	/* Feature flags */
79u_int	cpu_feature2 = 0;	/* Feature flags */
80u_int	amd_feature = 0;	/* AMD feature flags */
81u_int	amd_feature2 = 0;	/* AMD feature flags */
82u_int	cpu_high = 0;		/* Highest arg to CPUID */
83u_int	cpu_id = 0;		/* Stepping ID */
84u_int	cpu_procinfo = 0;	/* HyperThreading Info / Brand Index / CLFUSH */
85u_int	cpu_procinfo2 = 0;	/* Multicore info */
86char	cpu_vendor[20] = "";	/* CPU Origin code */
87
88#ifdef CPU_ENABLE_SSE
89u_int	cpu_fxsr;		/* SSE enabled */
90#endif
91
92#ifdef I486_CPU
93/*
94 * IBM Blue Lightning
95 */
96static void
97init_bluelightning(void)
98{
99	u_long	eflags;
100
101#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
102	need_post_dma_flush = 1;
103#endif
104
105	eflags = read_eflags();
106	disable_intr();
107
108	load_cr0(rcr0() | CR0_CD | CR0_NW);
109	invd();
110
111#ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
112	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
113#else
114	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
115#endif
116	/* Enables 13MB and 0-640KB cache. */
117	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
118#ifdef CPU_BLUELIGHTNING_3X
119	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
120#else
121	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
122#endif
123
124	/* Enable caching in CR0. */
125	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
126	invd();
127	write_eflags(eflags);
128}
129
130/*
131 * Cyrix 486SLC/DLC/SR/DR series
132 */
133static void
134init_486dlc(void)
135{
136	u_long	eflags;
137	u_char	ccr0;
138
139	eflags = read_eflags();
140	disable_intr();
141	invd();
142
143	ccr0 = read_cyrix_reg(CCR0);
144#ifndef CYRIX_CACHE_WORKS
145	ccr0 |= CCR0_NC1 | CCR0_BARB;
146	write_cyrix_reg(CCR0, ccr0);
147	invd();
148#else
149	ccr0 &= ~CCR0_NC0;
150#ifndef CYRIX_CACHE_REALLY_WORKS
151	ccr0 |= CCR0_NC1 | CCR0_BARB;
152#else
153	ccr0 |= CCR0_NC1;
154#endif
155#ifdef CPU_DIRECT_MAPPED_CACHE
156	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
157#endif
158	write_cyrix_reg(CCR0, ccr0);
159
160	/* Clear non-cacheable region. */
161	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
162	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
163	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
164	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
165
166	write_cyrix_reg(0, 0);	/* dummy write */
167
168	/* Enable caching in CR0. */
169	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
170	invd();
171#endif /* !CYRIX_CACHE_WORKS */
172	write_eflags(eflags);
173}
174
175
176/*
177 * Cyrix 486S/DX series
178 */
179static void
180init_cy486dx(void)
181{
182	u_long	eflags;
183	u_char	ccr2;
184
185	eflags = read_eflags();
186	disable_intr();
187	invd();
188
189	ccr2 = read_cyrix_reg(CCR2);
190#ifdef CPU_SUSP_HLT
191	ccr2 |= CCR2_SUSP_HLT;
192#endif
193
194#ifdef PC98
195	/* Enables WB cache interface pin and Lock NW bit in CR0. */
196	ccr2 |= CCR2_WB | CCR2_LOCK_NW;
197	/* Unlock NW bit in CR0. */
198	write_cyrix_reg(CCR2, ccr2 & ~CCR2_LOCK_NW);
199	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
200#endif
201
202	write_cyrix_reg(CCR2, ccr2);
203	write_eflags(eflags);
204}
205
206
207/*
208 * Cyrix 5x86
209 */
210static void
211init_5x86(void)
212{
213	u_long	eflags;
214	u_char	ccr2, ccr3, ccr4, pcr0;
215
216	eflags = read_eflags();
217	disable_intr();
218
219	load_cr0(rcr0() | CR0_CD | CR0_NW);
220	wbinvd();
221
222	(void)read_cyrix_reg(CCR3);		/* dummy */
223
224	/* Initialize CCR2. */
225	ccr2 = read_cyrix_reg(CCR2);
226	ccr2 |= CCR2_WB;
227#ifdef CPU_SUSP_HLT
228	ccr2 |= CCR2_SUSP_HLT;
229#else
230	ccr2 &= ~CCR2_SUSP_HLT;
231#endif
232	ccr2 |= CCR2_WT1;
233	write_cyrix_reg(CCR2, ccr2);
234
235	/* Initialize CCR4. */
236	ccr3 = read_cyrix_reg(CCR3);
237	write_cyrix_reg(CCR3, CCR3_MAPEN0);
238
239	ccr4 = read_cyrix_reg(CCR4);
240	ccr4 |= CCR4_DTE;
241	ccr4 |= CCR4_MEM;
242#ifdef CPU_FASTER_5X86_FPU
243	ccr4 |= CCR4_FASTFPE;
244#else
245	ccr4 &= ~CCR4_FASTFPE;
246#endif
247	ccr4 &= ~CCR4_IOMASK;
248	/********************************************************************
249	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
250	 * should be 0 for errata fix.
251	 ********************************************************************/
252#ifdef CPU_IORT
253	ccr4 |= CPU_IORT & CCR4_IOMASK;
254#endif
255	write_cyrix_reg(CCR4, ccr4);
256
257	/* Initialize PCR0. */
258	/****************************************************************
259	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
260	 * BTB_EN might make your system unstable.
261	 ****************************************************************/
262	pcr0 = read_cyrix_reg(PCR0);
263#ifdef CPU_RSTK_EN
264	pcr0 |= PCR0_RSTK;
265#else
266	pcr0 &= ~PCR0_RSTK;
267#endif
268#ifdef CPU_BTB_EN
269	pcr0 |= PCR0_BTB;
270#else
271	pcr0 &= ~PCR0_BTB;
272#endif
273#ifdef CPU_LOOP_EN
274	pcr0 |= PCR0_LOOP;
275#else
276	pcr0 &= ~PCR0_LOOP;
277#endif
278
279	/****************************************************************
280	 * WARNING: if you use a memory mapped I/O device, don't use
281	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
282	 * I/O access.
283	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
284	 ****************************************************************/
285#ifdef CPU_DISABLE_5X86_LSSER
286	pcr0 &= ~PCR0_LSSER;
287#else
288	pcr0 |= PCR0_LSSER;
289#endif
290	write_cyrix_reg(PCR0, pcr0);
291
292	/* Restore CCR3. */
293	write_cyrix_reg(CCR3, ccr3);
294
295	(void)read_cyrix_reg(0x80);		/* dummy */
296
297	/* Unlock NW bit in CR0. */
298	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
299	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
300	/* Lock NW bit in CR0. */
301	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
302
303	write_eflags(eflags);
304}
305
306#ifdef CPU_I486_ON_386
307/*
308 * There are i486 based upgrade products for i386 machines.
309 * In this case, BIOS doesn't enables CPU cache.
310 */
311static void
312init_i486_on_386(void)
313{
314	u_long	eflags;
315
316#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
317	need_post_dma_flush = 1;
318#endif
319
320	eflags = read_eflags();
321	disable_intr();
322
323	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
324
325	write_eflags(eflags);
326}
327#endif
328
329/*
330 * Cyrix 6x86
331 *
332 * XXX - What should I do here?  Please let me know.
333 */
334static void
335init_6x86(void)
336{
337	u_long	eflags;
338	u_char	ccr3, ccr4;
339
340	eflags = read_eflags();
341	disable_intr();
342
343	load_cr0(rcr0() | CR0_CD | CR0_NW);
344	wbinvd();
345
346	/* Initialize CCR0. */
347	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
348
349	/* Initialize CCR1. */
350#ifdef CPU_CYRIX_NO_LOCK
351	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
352#else
353	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
354#endif
355
356	/* Initialize CCR2. */
357#ifdef CPU_SUSP_HLT
358	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
359#else
360	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
361#endif
362
363	ccr3 = read_cyrix_reg(CCR3);
364	write_cyrix_reg(CCR3, CCR3_MAPEN0);
365
366	/* Initialize CCR4. */
367	ccr4 = read_cyrix_reg(CCR4);
368	ccr4 |= CCR4_DTE;
369	ccr4 &= ~CCR4_IOMASK;
370#ifdef CPU_IORT
371	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
372#else
373	write_cyrix_reg(CCR4, ccr4 | 7);
374#endif
375
376	/* Initialize CCR5. */
377#ifdef CPU_WT_ALLOC
378	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
379#endif
380
381	/* Restore CCR3. */
382	write_cyrix_reg(CCR3, ccr3);
383
384	/* Unlock NW bit in CR0. */
385	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
386
387	/*
388	 * Earlier revision of the 6x86 CPU could crash the system if
389	 * L1 cache is in write-back mode.
390	 */
391	if ((cyrix_did & 0xff00) > 0x1600)
392		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
393	else {
394		/* Revision 2.6 and lower. */
395#ifdef CYRIX_CACHE_REALLY_WORKS
396		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
397#else
398		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
399#endif
400	}
401
402	/* Lock NW bit in CR0. */
403	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
404
405	write_eflags(eflags);
406}
407#endif /* I486_CPU */
408
409#ifdef I686_CPU
410/*
411 * Cyrix 6x86MX (code-named M2)
412 *
413 * XXX - What should I do here?  Please let me know.
414 */
415static void
416init_6x86MX(void)
417{
418	u_long	eflags;
419	u_char	ccr3, ccr4;
420
421	eflags = read_eflags();
422	disable_intr();
423
424	load_cr0(rcr0() | CR0_CD | CR0_NW);
425	wbinvd();
426
427	/* Initialize CCR0. */
428	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
429
430	/* Initialize CCR1. */
431#ifdef CPU_CYRIX_NO_LOCK
432	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
433#else
434	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
435#endif
436
437	/* Initialize CCR2. */
438#ifdef CPU_SUSP_HLT
439	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
440#else
441	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
442#endif
443
444	ccr3 = read_cyrix_reg(CCR3);
445	write_cyrix_reg(CCR3, CCR3_MAPEN0);
446
447	/* Initialize CCR4. */
448	ccr4 = read_cyrix_reg(CCR4);
449	ccr4 &= ~CCR4_IOMASK;
450#ifdef CPU_IORT
451	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
452#else
453	write_cyrix_reg(CCR4, ccr4 | 7);
454#endif
455
456	/* Initialize CCR5. */
457#ifdef CPU_WT_ALLOC
458	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
459#endif
460
461	/* Restore CCR3. */
462	write_cyrix_reg(CCR3, ccr3);
463
464	/* Unlock NW bit in CR0. */
465	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
466
467	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
468
469	/* Lock NW bit in CR0. */
470	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
471
472	write_eflags(eflags);
473}
474
475static void
476init_ppro(void)
477{
478	u_int64_t	apicbase;
479
480	/*
481	 * Local APIC should be disabled if it is not going to be used.
482	 */
483	apicbase = rdmsr(MSR_APICBASE);
484	apicbase &= ~APICBASE_ENABLED;
485	wrmsr(MSR_APICBASE, apicbase);
486}
487
488/*
489 * Initialize BBL_CR_CTL3 (Control register 3: used to configure the
490 * L2 cache).
491 */
492static void
493init_mendocino(void)
494{
495#ifdef CPU_PPRO2CELERON
496	u_long	eflags;
497	u_int64_t	bbl_cr_ctl3;
498
499	eflags = read_eflags();
500	disable_intr();
501
502	load_cr0(rcr0() | CR0_CD | CR0_NW);
503	wbinvd();
504
505	bbl_cr_ctl3 = rdmsr(MSR_BBL_CR_CTL3);
506
507	/* If the L2 cache is configured, do nothing. */
508	if (!(bbl_cr_ctl3 & 1)) {
509		bbl_cr_ctl3 = 0x134052bLL;
510
511		/* Set L2 Cache Latency (Default: 5). */
512#ifdef	CPU_CELERON_L2_LATENCY
513#if CPU_L2_LATENCY > 15
514#error invalid CPU_L2_LATENCY.
515#endif
516		bbl_cr_ctl3 |= CPU_L2_LATENCY << 1;
517#else
518		bbl_cr_ctl3 |= 5 << 1;
519#endif
520		wrmsr(MSR_BBL_CR_CTL3, bbl_cr_ctl3);
521	}
522
523	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
524	write_eflags(eflags);
525#endif /* CPU_PPRO2CELERON */
526}
527
528#endif /* I686_CPU */
529
530/*
531 * Initialize CR4 (Control register 4) to enable SSE instructions.
532 */
533void
534enable_sse(void)
535{
536#if defined(CPU_ENABLE_SSE)
537	if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
538		load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
539		cpu_fxsr = hw_instruction_sse = 1;
540	}
541#endif
542}
543
544void
545initializecpu(void)
546{
547
548	switch (cpu) {
549#ifdef I486_CPU
550	case CPU_BLUE:
551		init_bluelightning();
552		break;
553	case CPU_486DLC:
554		init_486dlc();
555		break;
556	case CPU_CY486DX:
557		init_cy486dx();
558		break;
559	case CPU_M1SC:
560		init_5x86();
561		break;
562#ifdef CPU_I486_ON_386
563	case CPU_486:
564		init_i486_on_386();
565		break;
566#endif
567	case CPU_M1:
568		init_6x86();
569		break;
570#endif /* I486_CPU */
571#ifdef I686_CPU
572	case CPU_M2:
573		init_6x86MX();
574		break;
575	case CPU_686:
576		if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
577			switch (cpu_id & 0xff0) {
578			case 0x610:
579				init_ppro();
580				break;
581			case 0x660:
582				init_mendocino();
583				break;
584			}
585		} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
586#if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK)
587			/*
588			 * Sometimes the BIOS doesn't enable SSE instructions.
589			 * According to AMD document 20734, the mobile
590			 * Duron, the (mobile) Athlon 4 and the Athlon MP
591			 * support SSE. These correspond to cpu_id 0x66X
592			 * or 0x67X.
593			 */
594			if ((cpu_feature & CPUID_XMM) == 0 &&
595			    ((cpu_id & ~0xf) == 0x660 ||
596			     (cpu_id & ~0xf) == 0x670 ||
597			     (cpu_id & ~0xf) == 0x680)) {
598				u_int regs[4];
599				wrmsr(0xC0010015, rdmsr(0xC0010015) & ~0x08000);
600				do_cpuid(1, regs);
601				cpu_feature = regs[3];
602			}
603#endif
604		}
605		break;
606#endif
607	default:
608		break;
609	}
610	enable_sse();
611
612#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
613	/*
614	 * OS should flush L1 cache by itself because no PC-98 supports
615	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
616	 * when need_pre_dma_flush = 1, use invd instruction after DMA
617	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
618	 * product supports hardware cache control, you can add the
619	 * CPU_UPGRADE_HW_CACHE option in your kernel configuration file.
620	 * This option eliminates unneeded cache flush instruction(s).
621	 */
622	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
623		switch (cpu) {
624#ifdef I486_CPU
625		case CPU_486DLC:
626			need_post_dma_flush = 1;
627			break;
628		case CPU_M1SC:
629			need_pre_dma_flush = 1;
630			break;
631		case CPU_CY486DX:
632			need_pre_dma_flush = 1;
633#ifdef CPU_I486_ON_386
634			need_post_dma_flush = 1;
635#endif
636			break;
637#endif
638		default:
639			break;
640		}
641	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
642		switch (cpu_id & 0xFF0) {
643		case 0x470:		/* Enhanced Am486DX2 WB */
644		case 0x490:		/* Enhanced Am486DX4 WB */
645		case 0x4F0:		/* Am5x86 WB */
646			need_pre_dma_flush = 1;
647			break;
648		}
649	} else if (strcmp(cpu_vendor, "IBM") == 0) {
650		need_post_dma_flush = 1;
651	} else {
652#ifdef CPU_I486_ON_386
653		need_pre_dma_flush = 1;
654#endif
655	}
656#endif /* PC98 && !CPU_UPGRADE_HW_CACHE */
657}
658
659#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
660/*
661 * Enable write allocate feature of AMD processors.
662 * Following two functions require the Maxmem variable being set.
663 */
664void
665enable_K5_wt_alloc(void)
666{
667	u_int64_t	msr;
668	register_t	savecrit;
669
670	/*
671	 * Write allocate is supported only on models 1, 2, and 3, with
672	 * a stepping of 4 or greater.
673	 */
674	if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) {
675		savecrit = intr_disable();
676		msr = rdmsr(0x83);		/* HWCR */
677		wrmsr(0x83, msr & !(0x10));
678
679		/*
680		 * We have to tell the chip where the top of memory is,
681		 * since video cards could have frame bufferes there,
682		 * memory-mapped I/O could be there, etc.
683		 */
684		if(Maxmem > 0)
685		  msr = Maxmem / 16;
686		else
687		  msr = 0;
688		msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE;
689#ifdef PC98
690		if (!(inb(0x43b) & 4)) {
691			wrmsr(0x86, 0x0ff00f0);
692			msr |= AMD_WT_ALLOC_PRE;
693		}
694#else
695		/*
696		 * There is no way to know wheter 15-16M hole exists or not.
697		 * Therefore, we disable write allocate for this range.
698		 */
699			wrmsr(0x86, 0x0ff00f0);
700			msr |= AMD_WT_ALLOC_PRE;
701#endif
702		wrmsr(0x85, msr);
703
704		msr=rdmsr(0x83);
705		wrmsr(0x83, msr|0x10); /* enable write allocate */
706		intr_restore(savecrit);
707	}
708}
709
710void
711enable_K6_wt_alloc(void)
712{
713	quad_t	size;
714	u_int64_t	whcr;
715	u_long	eflags;
716
717	eflags = read_eflags();
718	disable_intr();
719	wbinvd();
720
721#ifdef CPU_DISABLE_CACHE
722	/*
723	 * Certain K6-2 box becomes unstable when write allocation is
724	 * enabled.
725	 */
726	/*
727	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
728	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
729	 * All other bits in TR12 have no effect on the processer's operation.
730	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
731	 * on the AMD-K6.
732	 */
733	wrmsr(0x0000000e, (u_int64_t)0x0008);
734#endif
735	/* Don't assume that memory size is aligned with 4M. */
736	if (Maxmem > 0)
737	  size = ((Maxmem >> 8) + 3) >> 2;
738	else
739	  size = 0;
740
741	/* Limit is 508M bytes. */
742	if (size > 0x7f)
743		size = 0x7f;
744	whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1);
745
746#if defined(PC98) || defined(NO_MEMORY_HOLE)
747	if (whcr & (0x7fLL << 1)) {
748#ifdef PC98
749		/*
750		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
751		 * 15-16M range.
752		 */
753		if (!(inb(0x43b) & 4))
754			whcr &= ~0x0001LL;
755		else
756#endif
757			whcr |=  0x0001LL;
758	}
759#else
760	/*
761	 * There is no way to know wheter 15-16M hole exists or not.
762	 * Therefore, we disable write allocate for this range.
763	 */
764	whcr &= ~0x0001LL;
765#endif
766	wrmsr(0x0c0000082, whcr);
767
768	write_eflags(eflags);
769}
770
771void
772enable_K6_2_wt_alloc(void)
773{
774	quad_t	size;
775	u_int64_t	whcr;
776	u_long	eflags;
777
778	eflags = read_eflags();
779	disable_intr();
780	wbinvd();
781
782#ifdef CPU_DISABLE_CACHE
783	/*
784	 * Certain K6-2 box becomes unstable when write allocation is
785	 * enabled.
786	 */
787	/*
788	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
789	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
790	 * All other bits in TR12 have no effect on the processer's operation.
791	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
792	 * on the AMD-K6.
793	 */
794	wrmsr(0x0000000e, (u_int64_t)0x0008);
795#endif
796	/* Don't assume that memory size is aligned with 4M. */
797	if (Maxmem > 0)
798	  size = ((Maxmem >> 8) + 3) >> 2;
799	else
800	  size = 0;
801
802	/* Limit is 4092M bytes. */
803	if (size > 0x3fff)
804		size = 0x3ff;
805	whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22);
806
807#if defined(PC98) || defined(NO_MEMORY_HOLE)
808	if (whcr & (0x3ffLL << 22)) {
809#ifdef PC98
810		/*
811		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
812		 * 15-16M range.
813		 */
814		if (!(inb(0x43b) & 4))
815			whcr &= ~(1LL << 16);
816		else
817#endif
818			whcr |=  1LL << 16;
819	}
820#else
821	/*
822	 * There is no way to know wheter 15-16M hole exists or not.
823	 * Therefore, we disable write allocate for this range.
824	 */
825	whcr &= ~(1LL << 16);
826#endif
827	wrmsr(0x0c0000082, whcr);
828
829	write_eflags(eflags);
830}
831#endif /* I585_CPU && CPU_WT_ALLOC */
832
833#include "opt_ddb.h"
834#ifdef DDB
835#include <ddb/ddb.h>
836
837DB_SHOW_COMMAND(cyrixreg, cyrixreg)
838{
839	u_long	eflags;
840	u_int	cr0;
841	u_char	ccr1, ccr2, ccr3;
842	u_char	ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0;
843
844	cr0 = rcr0();
845	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
846		eflags = read_eflags();
847		disable_intr();
848
849
850		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
851			ccr0 = read_cyrix_reg(CCR0);
852		}
853		ccr1 = read_cyrix_reg(CCR1);
854		ccr2 = read_cyrix_reg(CCR2);
855		ccr3 = read_cyrix_reg(CCR3);
856		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
857			write_cyrix_reg(CCR3, CCR3_MAPEN0);
858			ccr4 = read_cyrix_reg(CCR4);
859			if ((cpu == CPU_M1) || (cpu == CPU_M2))
860				ccr5 = read_cyrix_reg(CCR5);
861			else
862				pcr0 = read_cyrix_reg(PCR0);
863			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
864		}
865		write_eflags(eflags);
866
867		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
868			printf("CCR0=%x, ", (u_int)ccr0);
869
870		printf("CCR1=%x, CCR2=%x, CCR3=%x",
871			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
872		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
873			printf(", CCR4=%x, ", (u_int)ccr4);
874			if (cpu == CPU_M1SC)
875				printf("PCR0=%x\n", pcr0);
876			else
877				printf("CCR5=%x\n", ccr5);
878		}
879	}
880	printf("CR0=%x\n", cr0);
881}
882#endif /* DDB */
883