xref: /freebsd/sys/amd64/amd64/initcpu.c (revision 10deca7e)
1a8e282d6SKATO Takenori /*
24536af6aSKATO Takenori  * Copyright (c) KATO Takenori, 1997, 1998.
3a8e282d6SKATO Takenori  *
4a8e282d6SKATO Takenori  * All rights reserved.  Unpublished rights reserved under the copyright
5a8e282d6SKATO Takenori  * laws of Japan.
6a8e282d6SKATO Takenori  *
7a8e282d6SKATO Takenori  * Redistribution and use in source and binary forms, with or without
8a8e282d6SKATO Takenori  * modification, are permitted provided that the following conditions
9a8e282d6SKATO Takenori  * are met:
10a8e282d6SKATO Takenori  *
11a8e282d6SKATO Takenori  * 1. Redistributions of source code must retain the above copyright
12a8e282d6SKATO Takenori  *    notice, this list of conditions and the following disclaimer as
13a8e282d6SKATO Takenori  *    the first lines of this file unmodified.
14a8e282d6SKATO Takenori  * 2. Redistributions in binary form must reproduce the above copyright
15a8e282d6SKATO Takenori  *    notice, this list of conditions and the following disclaimer in the
16a8e282d6SKATO Takenori  *    documentation and/or other materials provided with the distribution.
17a8e282d6SKATO Takenori  *
18a8e282d6SKATO Takenori  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19a8e282d6SKATO Takenori  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20a8e282d6SKATO Takenori  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21a8e282d6SKATO Takenori  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22a8e282d6SKATO Takenori  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23a8e282d6SKATO Takenori  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24a8e282d6SKATO Takenori  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25a8e282d6SKATO Takenori  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26a8e282d6SKATO Takenori  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27a8e282d6SKATO Takenori  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28a8e282d6SKATO Takenori  *
29c3aac50fSPeter Wemm  * $FreeBSD$
30a8e282d6SKATO Takenori  */
31a8e282d6SKATO Takenori 
32a8e282d6SKATO Takenori #include "opt_cpu.h"
33a8e282d6SKATO Takenori 
34a8e282d6SKATO Takenori #include <sys/param.h>
35a8e282d6SKATO Takenori #include <sys/kernel.h>
36a8e282d6SKATO Takenori #include <sys/systm.h>
379d146ac5SPeter Wemm #include <sys/sysctl.h>
38a8e282d6SKATO Takenori 
39a8e282d6SKATO Takenori #include <machine/cputypes.h>
40a8e282d6SKATO Takenori #include <machine/md_var.h>
41a8e282d6SKATO Takenori #include <machine/specialreg.h>
42a8e282d6SKATO Takenori 
43f7749f92SPeter Wemm #if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
44f7749f92SPeter Wemm #define CPU_ENABLE_SSE
45f7749f92SPeter Wemm #endif
46f7749f92SPeter Wemm #if defined(CPU_DISABLE_SSE)
47f7749f92SPeter Wemm #undef CPU_ENABLE_SSE
48f7749f92SPeter Wemm #endif
49f7749f92SPeter Wemm 
50a8e282d6SKATO Takenori void initializecpu(void);
514536af6aSKATO Takenori #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
524536af6aSKATO Takenori void	enable_K5_wt_alloc(void);
534536af6aSKATO Takenori void	enable_K6_wt_alloc(void);
54925f3681SMike Smith void	enable_K6_2_wt_alloc(void);
554536af6aSKATO Takenori #endif
564536af6aSKATO Takenori 
57a8e282d6SKATO Takenori #ifdef I486_CPU
58a8e282d6SKATO Takenori static void init_5x86(void);
59a8e282d6SKATO Takenori static void init_bluelightning(void);
60a8e282d6SKATO Takenori static void init_486dlc(void);
619ca82267SKATO Takenori static void init_cy486dx(void);
62a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
63a8e282d6SKATO Takenori static void init_i486_on_386(void);
64a8e282d6SKATO Takenori #endif
65a8e282d6SKATO Takenori static void init_6x86(void);
66a8e282d6SKATO Takenori #endif /* I486_CPU */
67a8e282d6SKATO Takenori 
684877e978SKATO Takenori #ifdef I686_CPU
6920916c1fSKATO Takenori static void	init_6x86MX(void);
700d303cbaSKATO Takenori static void	init_ppro(void);
7165cbb03cSKATO Takenori static void	init_mendocino(void);
7220916c1fSKATO Takenori #endif
7320916c1fSKATO Takenori 
7410deca7eSJohn Baldwin static int	hw_instruction_sse;
759d146ac5SPeter Wemm SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
7610deca7eSJohn Baldwin     &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
779d146ac5SPeter Wemm 
7825ea330aSPeter Wemm /* Must *NOT* be BSS or locore will bzero these after setting them */
7925ea330aSPeter Wemm int	cpu = 0;		/* Are we 386, 386sx, 486, etc? */
8025ea330aSPeter Wemm u_int	cpu_feature = 0;	/* Feature flags */
8125ea330aSPeter Wemm u_int	cpu_high = 0;		/* Highest arg to CPUID */
8210deca7eSJohn Baldwin u_int	cpu_id = 0;		/* Stepping ID */
83caf31976SJohn Baldwin u_int	cpu_procinfo = 0;	/* HyperThreading Info / Brand Index / CLFUSH */
8425ea330aSPeter Wemm char	cpu_vendor[20] = "";	/* CPU Origin code */
855897d411SPeter Wemm 
8610deca7eSJohn Baldwin #ifdef CPU_ENABLE_SSE
8710deca7eSJohn Baldwin u_int	cpu_fxsr;		/* SSE enabled */
8810deca7eSJohn Baldwin #endif
8910deca7eSJohn Baldwin 
90a8e282d6SKATO Takenori #ifdef I486_CPU
91a8e282d6SKATO Takenori /*
92a8e282d6SKATO Takenori  * IBM Blue Lightning
93a8e282d6SKATO Takenori  */
94a8e282d6SKATO Takenori static void
95a8e282d6SKATO Takenori init_bluelightning(void)
96a8e282d6SKATO Takenori {
97a8e282d6SKATO Takenori 	u_long	eflags;
98a8e282d6SKATO Takenori 
99a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
100a8e282d6SKATO Takenori 	need_post_dma_flush = 1;
101a8e282d6SKATO Takenori #endif
102a8e282d6SKATO Takenori 
103a8e282d6SKATO Takenori 	eflags = read_eflags();
104a8e282d6SKATO Takenori 	disable_intr();
105a8e282d6SKATO Takenori 
106a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
107a8e282d6SKATO Takenori 	invd();
108a8e282d6SKATO Takenori 
109a8e282d6SKATO Takenori #ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
110a8e282d6SKATO Takenori 	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
111a8e282d6SKATO Takenori #else
112a8e282d6SKATO Takenori 	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
113a8e282d6SKATO Takenori #endif
114a8e282d6SKATO Takenori 	/* Enables 13MB and 0-640KB cache. */
115a8e282d6SKATO Takenori 	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
116a8e282d6SKATO Takenori #ifdef CPU_BLUELIGHTNING_3X
117a8e282d6SKATO Takenori 	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
118a8e282d6SKATO Takenori #else
119a8e282d6SKATO Takenori 	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
120a8e282d6SKATO Takenori #endif
121a8e282d6SKATO Takenori 
122a8e282d6SKATO Takenori 	/* Enable caching in CR0. */
123a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
124a8e282d6SKATO Takenori 	invd();
125a8e282d6SKATO Takenori 	write_eflags(eflags);
126a8e282d6SKATO Takenori }
127a8e282d6SKATO Takenori 
128a8e282d6SKATO Takenori /*
1299ca82267SKATO Takenori  * Cyrix 486SLC/DLC/SR/DR series
130a8e282d6SKATO Takenori  */
131a8e282d6SKATO Takenori static void
132a8e282d6SKATO Takenori init_486dlc(void)
133a8e282d6SKATO Takenori {
134a8e282d6SKATO Takenori 	u_long	eflags;
135a8e282d6SKATO Takenori 	u_char	ccr0;
136a8e282d6SKATO Takenori 
137a8e282d6SKATO Takenori 	eflags = read_eflags();
138a8e282d6SKATO Takenori 	disable_intr();
139a8e282d6SKATO Takenori 	invd();
140a8e282d6SKATO Takenori 
141a8e282d6SKATO Takenori 	ccr0 = read_cyrix_reg(CCR0);
142a8e282d6SKATO Takenori #ifndef CYRIX_CACHE_WORKS
143a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1 | CCR0_BARB;
144a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, ccr0);
145a8e282d6SKATO Takenori 	invd();
146a8e282d6SKATO Takenori #else
147a8e282d6SKATO Takenori 	ccr0 &= ~CCR0_NC0;
148a8e282d6SKATO Takenori #ifndef CYRIX_CACHE_REALLY_WORKS
149a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1 | CCR0_BARB;
150a8e282d6SKATO Takenori #else
151a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1;
152a8e282d6SKATO Takenori #endif
1534962d938SKATO Takenori #ifdef CPU_DIRECT_MAPPED_CACHE
1544962d938SKATO Takenori 	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
1554962d938SKATO Takenori #endif
156a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, ccr0);
157a8e282d6SKATO Takenori 
158a8e282d6SKATO Takenori 	/* Clear non-cacheable region. */
159a8e282d6SKATO Takenori 	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
160a8e282d6SKATO Takenori 	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
161a8e282d6SKATO Takenori 	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
162a8e282d6SKATO Takenori 	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
163a8e282d6SKATO Takenori 
164a8e282d6SKATO Takenori 	write_cyrix_reg(0, 0);	/* dummy write */
165a8e282d6SKATO Takenori 
166a8e282d6SKATO Takenori 	/* Enable caching in CR0. */
167a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
168a8e282d6SKATO Takenori 	invd();
169a8e282d6SKATO Takenori #endif /* !CYRIX_CACHE_WORKS */
170a8e282d6SKATO Takenori 	write_eflags(eflags);
171a8e282d6SKATO Takenori }
172a8e282d6SKATO Takenori 
173a8e282d6SKATO Takenori 
174a8e282d6SKATO Takenori /*
1759ca82267SKATO Takenori  * Cyrix 486S/DX series
1769ca82267SKATO Takenori  */
1779ca82267SKATO Takenori static void
1789ca82267SKATO Takenori init_cy486dx(void)
1799ca82267SKATO Takenori {
1809ca82267SKATO Takenori 	u_long	eflags;
1819ca82267SKATO Takenori 	u_char	ccr2;
1829ca82267SKATO Takenori 
1839ca82267SKATO Takenori 	eflags = read_eflags();
1849ca82267SKATO Takenori 	disable_intr();
1859ca82267SKATO Takenori 	invd();
1869ca82267SKATO Takenori 
1879ca82267SKATO Takenori 	ccr2 = read_cyrix_reg(CCR2);
1881ba2a543SKATO Takenori #ifdef CPU_SUSP_HLT
1891ba2a543SKATO Takenori 	ccr2 |= CCR2_SUSP_HLT;
1909ca82267SKATO Takenori #endif
1911cfd836fSKATO Takenori 
1921cfd836fSKATO Takenori #ifdef PC98
1931cfd836fSKATO Takenori 	/* Enables WB cache interface pin and Lock NW bit in CR0. */
1941cfd836fSKATO Takenori 	ccr2 |= CCR2_WB | CCR2_LOCK_NW;
1951cfd836fSKATO Takenori 	/* Unlock NW bit in CR0. */
1961cfd836fSKATO Takenori 	write_cyrix_reg(CCR2, ccr2 & ~CCR2_LOCK_NW);
1971cfd836fSKATO Takenori 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
1981cfd836fSKATO Takenori #endif
1991cfd836fSKATO Takenori 
2009ca82267SKATO Takenori 	write_cyrix_reg(CCR2, ccr2);
2019ca82267SKATO Takenori 	write_eflags(eflags);
2029ca82267SKATO Takenori }
2039ca82267SKATO Takenori 
2049ca82267SKATO Takenori 
2059ca82267SKATO Takenori /*
206a8e282d6SKATO Takenori  * Cyrix 5x86
207a8e282d6SKATO Takenori  */
208a8e282d6SKATO Takenori static void
209a8e282d6SKATO Takenori init_5x86(void)
210a8e282d6SKATO Takenori {
211a8e282d6SKATO Takenori 	u_long	eflags;
212a8e282d6SKATO Takenori 	u_char	ccr2, ccr3, ccr4, pcr0;
213a8e282d6SKATO Takenori 
214a8e282d6SKATO Takenori 	eflags = read_eflags();
215a8e282d6SKATO Takenori 	disable_intr();
216a8e282d6SKATO Takenori 
217a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
218a8e282d6SKATO Takenori 	wbinvd();
219a8e282d6SKATO Takenori 
220a8e282d6SKATO Takenori 	(void)read_cyrix_reg(CCR3);		/* dummy */
221a8e282d6SKATO Takenori 
222a8e282d6SKATO Takenori 	/* Initialize CCR2. */
223a8e282d6SKATO Takenori 	ccr2 = read_cyrix_reg(CCR2);
224a8e282d6SKATO Takenori 	ccr2 |= CCR2_WB;
225a8e282d6SKATO Takenori #ifdef CPU_SUSP_HLT
226a8e282d6SKATO Takenori 	ccr2 |= CCR2_SUSP_HLT;
227a8e282d6SKATO Takenori #else
228a8e282d6SKATO Takenori 	ccr2 &= ~CCR2_SUSP_HLT;
229a8e282d6SKATO Takenori #endif
230a8e282d6SKATO Takenori 	ccr2 |= CCR2_WT1;
231a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, ccr2);
232a8e282d6SKATO Takenori 
233a8e282d6SKATO Takenori 	/* Initialize CCR4. */
234a8e282d6SKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
235a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
236a8e282d6SKATO Takenori 
237a8e282d6SKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
238a8e282d6SKATO Takenori 	ccr4 |= CCR4_DTE;
239a8e282d6SKATO Takenori 	ccr4 |= CCR4_MEM;
240a8e282d6SKATO Takenori #ifdef CPU_FASTER_5X86_FPU
241a8e282d6SKATO Takenori 	ccr4 |= CCR4_FASTFPE;
242a8e282d6SKATO Takenori #else
243a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_FASTFPE;
244a8e282d6SKATO Takenori #endif
245a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
246a8e282d6SKATO Takenori 	/********************************************************************
247a8e282d6SKATO Takenori 	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
248a8e282d6SKATO Takenori 	 * should be 0 for errata fix.
249a8e282d6SKATO Takenori 	 ********************************************************************/
250a8e282d6SKATO Takenori #ifdef CPU_IORT
251a8e282d6SKATO Takenori 	ccr4 |= CPU_IORT & CCR4_IOMASK;
252a8e282d6SKATO Takenori #endif
253a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4);
254a8e282d6SKATO Takenori 
255a8e282d6SKATO Takenori 	/* Initialize PCR0. */
256a8e282d6SKATO Takenori 	/****************************************************************
257a8e282d6SKATO Takenori 	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
258a8e282d6SKATO Takenori 	 * BTB_EN might make your system unstable.
259a8e282d6SKATO Takenori 	 ****************************************************************/
260a8e282d6SKATO Takenori 	pcr0 = read_cyrix_reg(PCR0);
261a8e282d6SKATO Takenori #ifdef CPU_RSTK_EN
262a8e282d6SKATO Takenori 	pcr0 |= PCR0_RSTK;
263a8e282d6SKATO Takenori #else
264a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_RSTK;
265a8e282d6SKATO Takenori #endif
266a8e282d6SKATO Takenori #ifdef CPU_BTB_EN
267a8e282d6SKATO Takenori 	pcr0 |= PCR0_BTB;
268a8e282d6SKATO Takenori #else
269a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_BTB;
270a8e282d6SKATO Takenori #endif
271a8e282d6SKATO Takenori #ifdef CPU_LOOP_EN
272a8e282d6SKATO Takenori 	pcr0 |= PCR0_LOOP;
273a8e282d6SKATO Takenori #else
274a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_LOOP;
275a8e282d6SKATO Takenori #endif
276a8e282d6SKATO Takenori 
277a8e282d6SKATO Takenori 	/****************************************************************
278a8e282d6SKATO Takenori 	 * WARNING: if you use a memory mapped I/O device, don't use
279a8e282d6SKATO Takenori 	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
280a8e282d6SKATO Takenori 	 * I/O access.
281a8e282d6SKATO Takenori 	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
282a8e282d6SKATO Takenori 	 ****************************************************************/
283a8e282d6SKATO Takenori #ifdef CPU_DISABLE_5X86_LSSER
284a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_LSSER;
285a8e282d6SKATO Takenori #else
286a8e282d6SKATO Takenori 	pcr0 |= PCR0_LSSER;
287a8e282d6SKATO Takenori #endif
288a8e282d6SKATO Takenori 	write_cyrix_reg(PCR0, pcr0);
289a8e282d6SKATO Takenori 
290a8e282d6SKATO Takenori 	/* Restore CCR3. */
291a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
292a8e282d6SKATO Takenori 
293a8e282d6SKATO Takenori 	(void)read_cyrix_reg(0x80);		/* dummy */
294a8e282d6SKATO Takenori 
295a8e282d6SKATO Takenori 	/* Unlock NW bit in CR0. */
296a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
297a8e282d6SKATO Takenori 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
298a8e282d6SKATO Takenori 	/* Lock NW bit in CR0. */
299a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
300a8e282d6SKATO Takenori 
301a8e282d6SKATO Takenori 	write_eflags(eflags);
302a8e282d6SKATO Takenori }
303a8e282d6SKATO Takenori 
304a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
305a8e282d6SKATO Takenori /*
306a8e282d6SKATO Takenori  * There are i486 based upgrade products for i386 machines.
307a8e282d6SKATO Takenori  * In this case, BIOS doesn't enables CPU cache.
308a8e282d6SKATO Takenori  */
3091eaae5cbSPoul-Henning Kamp static void
310a8e282d6SKATO Takenori init_i486_on_386(void)
311a8e282d6SKATO Takenori {
312a8e282d6SKATO Takenori 	u_long	eflags;
313a8e282d6SKATO Takenori 
314a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
315a8e282d6SKATO Takenori 	need_post_dma_flush = 1;
316a8e282d6SKATO Takenori #endif
317a8e282d6SKATO Takenori 
318a8e282d6SKATO Takenori 	eflags = read_eflags();
319a8e282d6SKATO Takenori 	disable_intr();
320a8e282d6SKATO Takenori 
321a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
322a8e282d6SKATO Takenori 
3235fa4a058SKATO Takenori 	write_eflags(eflags);
324a8e282d6SKATO Takenori }
325a8e282d6SKATO Takenori #endif
326a8e282d6SKATO Takenori 
327a8e282d6SKATO Takenori /*
328a8e282d6SKATO Takenori  * Cyrix 6x86
329a8e282d6SKATO Takenori  *
330a8e282d6SKATO Takenori  * XXX - What should I do here?  Please let me know.
331a8e282d6SKATO Takenori  */
332a8e282d6SKATO Takenori static void
333a8e282d6SKATO Takenori init_6x86(void)
334a8e282d6SKATO Takenori {
335a8e282d6SKATO Takenori 	u_long	eflags;
336a8e282d6SKATO Takenori 	u_char	ccr3, ccr4;
337a8e282d6SKATO Takenori 
338a8e282d6SKATO Takenori 	eflags = read_eflags();
339a8e282d6SKATO Takenori 	disable_intr();
340a8e282d6SKATO Takenori 
341a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
342a8e282d6SKATO Takenori 	wbinvd();
343a8e282d6SKATO Takenori 
344a8e282d6SKATO Takenori 	/* Initialize CCR0. */
345a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
346a8e282d6SKATO Takenori 
3476593be60SKATO Takenori 	/* Initialize CCR1. */
3486593be60SKATO Takenori #ifdef CPU_CYRIX_NO_LOCK
349b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
3506593be60SKATO Takenori #else
351b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
3526593be60SKATO Takenori #endif
3536593be60SKATO Takenori 
354a8e282d6SKATO Takenori 	/* Initialize CCR2. */
355a8e282d6SKATO Takenori #ifdef CPU_SUSP_HLT
356a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
357a8e282d6SKATO Takenori #else
358a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
359a8e282d6SKATO Takenori #endif
360a8e282d6SKATO Takenori 
361a8e282d6SKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
362a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
363a8e282d6SKATO Takenori 
364a8e282d6SKATO Takenori 	/* Initialize CCR4. */
365a8e282d6SKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
366a8e282d6SKATO Takenori 	ccr4 |= CCR4_DTE;
367a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
368a8e282d6SKATO Takenori #ifdef CPU_IORT
369a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
370a8e282d6SKATO Takenori #else
371a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | 7);
372a8e282d6SKATO Takenori #endif
373a8e282d6SKATO Takenori 
3746593be60SKATO Takenori 	/* Initialize CCR5. */
3756593be60SKATO Takenori #ifdef CPU_WT_ALLOC
3766593be60SKATO Takenori 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
3776593be60SKATO Takenori #endif
3786593be60SKATO Takenori 
379a8e282d6SKATO Takenori 	/* Restore CCR3. */
380a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
381a8e282d6SKATO Takenori 
382a8e282d6SKATO Takenori 	/* Unlock NW bit in CR0. */
383a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
384a8e282d6SKATO Takenori 
385a8e282d6SKATO Takenori 	/*
386a8e282d6SKATO Takenori 	 * Earlier revision of the 6x86 CPU could crash the system if
387a8e282d6SKATO Takenori 	 * L1 cache is in write-back mode.
388a8e282d6SKATO Takenori 	 */
389a8e282d6SKATO Takenori 	if ((cyrix_did & 0xff00) > 0x1600)
390a8e282d6SKATO Takenori 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
391a8e282d6SKATO Takenori 	else {
392a8e282d6SKATO Takenori 		/* Revision 2.6 and lower. */
393a8e282d6SKATO Takenori #ifdef CYRIX_CACHE_REALLY_WORKS
394a8e282d6SKATO Takenori 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
395a8e282d6SKATO Takenori #else
396a8e282d6SKATO Takenori 		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
397a8e282d6SKATO Takenori #endif
398a8e282d6SKATO Takenori 	}
399a8e282d6SKATO Takenori 
400a8e282d6SKATO Takenori 	/* Lock NW bit in CR0. */
401a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
402a8e282d6SKATO Takenori 
403a8e282d6SKATO Takenori 	write_eflags(eflags);
404a8e282d6SKATO Takenori }
405a8e282d6SKATO Takenori #endif /* I486_CPU */
406a8e282d6SKATO Takenori 
4074877e978SKATO Takenori #ifdef I686_CPU
40820916c1fSKATO Takenori /*
40920916c1fSKATO Takenori  * Cyrix 6x86MX (code-named M2)
41020916c1fSKATO Takenori  *
41120916c1fSKATO Takenori  * XXX - What should I do here?  Please let me know.
41220916c1fSKATO Takenori  */
41320916c1fSKATO Takenori static void
41420916c1fSKATO Takenori init_6x86MX(void)
41520916c1fSKATO Takenori {
41620916c1fSKATO Takenori 	u_long	eflags;
41720916c1fSKATO Takenori 	u_char	ccr3, ccr4;
41820916c1fSKATO Takenori 
41920916c1fSKATO Takenori 	eflags = read_eflags();
42020916c1fSKATO Takenori 	disable_intr();
42120916c1fSKATO Takenori 
42220916c1fSKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
42320916c1fSKATO Takenori 	wbinvd();
42420916c1fSKATO Takenori 
42520916c1fSKATO Takenori 	/* Initialize CCR0. */
42620916c1fSKATO Takenori 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
42720916c1fSKATO Takenori 
4286593be60SKATO Takenori 	/* Initialize CCR1. */
4296593be60SKATO Takenori #ifdef CPU_CYRIX_NO_LOCK
430b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
4316593be60SKATO Takenori #else
432b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
4336593be60SKATO Takenori #endif
4346593be60SKATO Takenori 
43520916c1fSKATO Takenori 	/* Initialize CCR2. */
43620916c1fSKATO Takenori #ifdef CPU_SUSP_HLT
43720916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
43820916c1fSKATO Takenori #else
43920916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
44020916c1fSKATO Takenori #endif
44120916c1fSKATO Takenori 
44220916c1fSKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
44320916c1fSKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
44420916c1fSKATO Takenori 
44520916c1fSKATO Takenori 	/* Initialize CCR4. */
44620916c1fSKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
44720916c1fSKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
44820916c1fSKATO Takenori #ifdef CPU_IORT
44920916c1fSKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
45020916c1fSKATO Takenori #else
45120916c1fSKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | 7);
45220916c1fSKATO Takenori #endif
45320916c1fSKATO Takenori 
4546593be60SKATO Takenori 	/* Initialize CCR5. */
4556593be60SKATO Takenori #ifdef CPU_WT_ALLOC
4566593be60SKATO Takenori 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
4576593be60SKATO Takenori #endif
4586593be60SKATO Takenori 
45920916c1fSKATO Takenori 	/* Restore CCR3. */
46020916c1fSKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
46120916c1fSKATO Takenori 
46220916c1fSKATO Takenori 	/* Unlock NW bit in CR0. */
46320916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
46420916c1fSKATO Takenori 
46520916c1fSKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
46620916c1fSKATO Takenori 
46720916c1fSKATO Takenori 	/* Lock NW bit in CR0. */
46820916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
46920916c1fSKATO Takenori 
47020916c1fSKATO Takenori 	write_eflags(eflags);
47120916c1fSKATO Takenori }
4720d303cbaSKATO Takenori 
4730d303cbaSKATO Takenori static void
4740d303cbaSKATO Takenori init_ppro(void)
4750d303cbaSKATO Takenori {
4760d303cbaSKATO Takenori #ifndef SMP
4774536af6aSKATO Takenori 	u_int64_t	apicbase;
4780d303cbaSKATO Takenori 
4790d303cbaSKATO Takenori 	/*
4800d303cbaSKATO Takenori 	 * Local APIC should be diabled in UP kernel.
4810d303cbaSKATO Takenori 	 */
4820d303cbaSKATO Takenori 	apicbase = rdmsr(0x1b);
4830d303cbaSKATO Takenori 	apicbase &= ~0x800LL;
4840d303cbaSKATO Takenori 	wrmsr(0x1b, apicbase);
4850d303cbaSKATO Takenori #endif
4860d303cbaSKATO Takenori }
48765cbb03cSKATO Takenori 
48865cbb03cSKATO Takenori /*
48965cbb03cSKATO Takenori  * Initialize BBL_CR_CTL3 (Control register 3: used to configure the
49065cbb03cSKATO Takenori  * L2 cache).
49165cbb03cSKATO Takenori  */
49237c84183SPoul-Henning Kamp static void
49365cbb03cSKATO Takenori init_mendocino(void)
49465cbb03cSKATO Takenori {
49565cbb03cSKATO Takenori #ifdef CPU_PPRO2CELERON
49665cbb03cSKATO Takenori 	u_long	eflags;
49765cbb03cSKATO Takenori 	u_int64_t	bbl_cr_ctl3;
49865cbb03cSKATO Takenori 
49965cbb03cSKATO Takenori 	eflags = read_eflags();
50065cbb03cSKATO Takenori 	disable_intr();
50165cbb03cSKATO Takenori 
50265cbb03cSKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
50365cbb03cSKATO Takenori 	wbinvd();
50465cbb03cSKATO Takenori 
50565cbb03cSKATO Takenori 	bbl_cr_ctl3 = rdmsr(0x11e);
50665cbb03cSKATO Takenori 
50765cbb03cSKATO Takenori 	/* If the L2 cache is configured, do nothing. */
50865cbb03cSKATO Takenori 	if (!(bbl_cr_ctl3 & 1)) {
50965cbb03cSKATO Takenori 		bbl_cr_ctl3 = 0x134052bLL;
51065cbb03cSKATO Takenori 
51165cbb03cSKATO Takenori 		/* Set L2 Cache Latency (Default: 5). */
51265cbb03cSKATO Takenori #ifdef	CPU_CELERON_L2_LATENCY
51365cbb03cSKATO Takenori #if CPU_L2_LATENCY > 15
51465cbb03cSKATO Takenori #error invalid CPU_L2_LATENCY.
51565cbb03cSKATO Takenori #endif
51665cbb03cSKATO Takenori 		bbl_cr_ctl3 |= CPU_L2_LATENCY << 1;
51765cbb03cSKATO Takenori #else
51865cbb03cSKATO Takenori 		bbl_cr_ctl3 |= 5 << 1;
51965cbb03cSKATO Takenori #endif
52065cbb03cSKATO Takenori 		wrmsr(0x11e, bbl_cr_ctl3);
52165cbb03cSKATO Takenori 	}
52265cbb03cSKATO Takenori 
52365cbb03cSKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
52465cbb03cSKATO Takenori 	write_eflags(eflags);
52565cbb03cSKATO Takenori #endif /* CPU_PPRO2CELERON */
52665cbb03cSKATO Takenori }
52765cbb03cSKATO Takenori 
5284faa812aSPeter Wemm #endif /* I686_CPU */
5294faa812aSPeter Wemm 
5309d146ac5SPeter Wemm /*
5319d146ac5SPeter Wemm  * Initialize CR4 (Control register 4) to enable SSE instructions.
5329d146ac5SPeter Wemm  */
5339d146ac5SPeter Wemm void
5349d146ac5SPeter Wemm enable_sse(void)
5359d146ac5SPeter Wemm {
5369d146ac5SPeter Wemm #if defined(CPU_ENABLE_SSE)
5379d146ac5SPeter Wemm 	if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
5389d146ac5SPeter Wemm 		load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
5399d146ac5SPeter Wemm 		cpu_fxsr = hw_instruction_sse = 1;
5409d146ac5SPeter Wemm 	}
5419d146ac5SPeter Wemm #endif
5429d146ac5SPeter Wemm }
5439d146ac5SPeter Wemm 
544a8e282d6SKATO Takenori void
545a8e282d6SKATO Takenori initializecpu(void)
546a8e282d6SKATO Takenori {
547a8e282d6SKATO Takenori 
548a8e282d6SKATO Takenori 	switch (cpu) {
549a8e282d6SKATO Takenori #ifdef I486_CPU
550a8e282d6SKATO Takenori 	case CPU_BLUE:
551a8e282d6SKATO Takenori 		init_bluelightning();
552a8e282d6SKATO Takenori 		break;
553a8e282d6SKATO Takenori 	case CPU_486DLC:
554a8e282d6SKATO Takenori 		init_486dlc();
555a8e282d6SKATO Takenori 		break;
5569ca82267SKATO Takenori 	case CPU_CY486DX:
5579ca82267SKATO Takenori 		init_cy486dx();
5589ca82267SKATO Takenori 		break;
559a8e282d6SKATO Takenori 	case CPU_M1SC:
560a8e282d6SKATO Takenori 		init_5x86();
561a8e282d6SKATO Takenori 		break;
562a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
563a8e282d6SKATO Takenori 	case CPU_486:
564a8e282d6SKATO Takenori 		init_i486_on_386();
565a8e282d6SKATO Takenori 		break;
566a8e282d6SKATO Takenori #endif
567a8e282d6SKATO Takenori 	case CPU_M1:
568a8e282d6SKATO Takenori 		init_6x86();
569a8e282d6SKATO Takenori 		break;
570a8e282d6SKATO Takenori #endif /* I486_CPU */
5714877e978SKATO Takenori #ifdef I686_CPU
57220916c1fSKATO Takenori 	case CPU_M2:
57320916c1fSKATO Takenori 		init_6x86MX();
57420916c1fSKATO Takenori 		break;
5750d303cbaSKATO Takenori 	case CPU_686:
57665cbb03cSKATO Takenori 		if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
57765cbb03cSKATO Takenori 			switch (cpu_id & 0xff0) {
57865cbb03cSKATO Takenori 			case 0x610:
5790d303cbaSKATO Takenori 				init_ppro();
5800d303cbaSKATO Takenori 				break;
58165cbb03cSKATO Takenori 			case 0x660:
58265cbb03cSKATO Takenori 				init_mendocino();
58365cbb03cSKATO Takenori 				break;
58465cbb03cSKATO Takenori 			}
5856df7ca7bSDavid Malone 		} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
5866df7ca7bSDavid Malone #if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK)
5876df7ca7bSDavid Malone 			/*
5886df7ca7bSDavid Malone 			 * Sometimes the BIOS doesn't enable SSE instructions.
5896df7ca7bSDavid Malone 			 * According to AMD document 20734, the mobile
5906df7ca7bSDavid Malone 			 * Duron, the (mobile) Athlon 4 and the Athlon MP
5916df7ca7bSDavid Malone 			 * support SSE. These correspond to cpu_id 0x66X
5926df7ca7bSDavid Malone 			 * or 0x67X.
5936df7ca7bSDavid Malone 			 */
5946df7ca7bSDavid Malone 			if ((cpu_feature & CPUID_XMM) == 0 &&
5956df7ca7bSDavid Malone 			    ((cpu_id & ~0xf) == 0x660 ||
5966df7ca7bSDavid Malone 			     (cpu_id & ~0xf) == 0x670)) {
5976df7ca7bSDavid Malone 				u_int regs[4];
5986df7ca7bSDavid Malone 				wrmsr(0xC0010015, rdmsr(0xC0010015) & ~0x08000);
5996df7ca7bSDavid Malone 				do_cpuid(1, regs);
6006df7ca7bSDavid Malone 				cpu_feature = regs[3];
6016df7ca7bSDavid Malone 			}
6026df7ca7bSDavid Malone #endif
60365cbb03cSKATO Takenori 		}
60465cbb03cSKATO Takenori 		break;
60520916c1fSKATO Takenori #endif
606a8e282d6SKATO Takenori 	default:
607a8e282d6SKATO Takenori 		break;
608a8e282d6SKATO Takenori 	}
609aa32e9a9SPeter Wemm 	enable_sse();
610a8e282d6SKATO Takenori 
611a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
612a8e282d6SKATO Takenori 	/*
6135b488b34SJeroen Ruigrok van der Werven 	 * OS should flush L1 cache by itself because no PC-98 supports
614a8e282d6SKATO Takenori 	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
615a8e282d6SKATO Takenori 	 * when need_pre_dma_flush = 1, use invd instruction after DMA
616a8e282d6SKATO Takenori 	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
6175b488b34SJeroen Ruigrok van der Werven 	 * product supports hardware cache control, you can add the
618a47ea7b9SJeroen Ruigrok van der Werven 	 * CPU_UPGRADE_HW_CACHE option in your kernel configuration file.
6195b488b34SJeroen Ruigrok van der Werven 	 * This option eliminates unneeded cache flush instruction(s).
620a8e282d6SKATO Takenori 	 */
621a8e282d6SKATO Takenori 	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
622a8e282d6SKATO Takenori 		switch (cpu) {
623a8e282d6SKATO Takenori #ifdef I486_CPU
624a8e282d6SKATO Takenori 		case CPU_486DLC:
625a8e282d6SKATO Takenori 			need_post_dma_flush = 1;
626a8e282d6SKATO Takenori 			break;
627a8e282d6SKATO Takenori 		case CPU_M1SC:
628a8e282d6SKATO Takenori 			need_pre_dma_flush = 1;
629a8e282d6SKATO Takenori 			break;
6301cfd836fSKATO Takenori 		case CPU_CY486DX:
6311cfd836fSKATO Takenori 			need_pre_dma_flush = 1;
6321cfd836fSKATO Takenori #ifdef CPU_I486_ON_386
6331cfd836fSKATO Takenori 			need_post_dma_flush = 1;
6341cfd836fSKATO Takenori #endif
6351cfd836fSKATO Takenori 			break;
636a8e282d6SKATO Takenori #endif
637a8e282d6SKATO Takenori 		default:
638a8e282d6SKATO Takenori 			break;
639a8e282d6SKATO Takenori 		}
640a8e282d6SKATO Takenori 	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
641a8e282d6SKATO Takenori 		switch (cpu_id & 0xFF0) {
642a8e282d6SKATO Takenori 		case 0x470:		/* Enhanced Am486DX2 WB */
643a8e282d6SKATO Takenori 		case 0x490:		/* Enhanced Am486DX4 WB */
644a8e282d6SKATO Takenori 		case 0x4F0:		/* Am5x86 WB */
645a8e282d6SKATO Takenori 			need_pre_dma_flush = 1;
646a8e282d6SKATO Takenori 			break;
647a8e282d6SKATO Takenori 		}
648a8e282d6SKATO Takenori 	} else if (strcmp(cpu_vendor, "IBM") == 0) {
649a8e282d6SKATO Takenori 		need_post_dma_flush = 1;
650a8e282d6SKATO Takenori 	} else {
651a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
652a8e282d6SKATO Takenori 		need_pre_dma_flush = 1;
653a8e282d6SKATO Takenori #endif
654a8e282d6SKATO Takenori 	}
655a47ea7b9SJeroen Ruigrok van der Werven #endif /* PC98 && !CPU_UPGRADE_HW_CACHE */
656a8e282d6SKATO Takenori }
657a8e282d6SKATO Takenori 
6584536af6aSKATO Takenori #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
6594536af6aSKATO Takenori /*
6604536af6aSKATO Takenori  * Enable write allocate feature of AMD processors.
6614536af6aSKATO Takenori  * Following two functions require the Maxmem variable being set.
6624536af6aSKATO Takenori  */
6634536af6aSKATO Takenori void
6644536af6aSKATO Takenori enable_K5_wt_alloc(void)
6654536af6aSKATO Takenori {
6664536af6aSKATO Takenori 	u_int64_t	msr;
667ba74981eSWarner Losh 	register_t	savecrit;
6684536af6aSKATO Takenori 
6694536af6aSKATO Takenori 	/*
6704536af6aSKATO Takenori 	 * Write allocate is supported only on models 1, 2, and 3, with
6714536af6aSKATO Takenori 	 * a stepping of 4 or greater.
6724536af6aSKATO Takenori 	 */
6734536af6aSKATO Takenori 	if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) {
674ba74981eSWarner Losh 		savecrit = intr_disable();
6754536af6aSKATO Takenori 		msr = rdmsr(0x83);		/* HWCR */
6764536af6aSKATO Takenori 		wrmsr(0x83, msr & !(0x10));
6774536af6aSKATO Takenori 
6784536af6aSKATO Takenori 		/*
6794536af6aSKATO Takenori 		 * We have to tell the chip where the top of memory is,
6804536af6aSKATO Takenori 		 * since video cards could have frame bufferes there,
6814536af6aSKATO Takenori 		 * memory-mapped I/O could be there, etc.
6824536af6aSKATO Takenori 		 */
6834536af6aSKATO Takenori 		if(Maxmem > 0)
6844536af6aSKATO Takenori 		  msr = Maxmem / 16;
6854536af6aSKATO Takenori 		else
6864536af6aSKATO Takenori 		  msr = 0;
6874536af6aSKATO Takenori 		msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE;
6884536af6aSKATO Takenori #ifdef PC98
6894536af6aSKATO Takenori 		if (!(inb(0x43b) & 4)) {
6904536af6aSKATO Takenori 			wrmsr(0x86, 0x0ff00f0);
6914536af6aSKATO Takenori 			msr |= AMD_WT_ALLOC_PRE;
6924536af6aSKATO Takenori 		}
6934536af6aSKATO Takenori #else
6944536af6aSKATO Takenori 		/*
6954536af6aSKATO Takenori 		 * There is no way to know wheter 15-16M hole exists or not.
6964536af6aSKATO Takenori 		 * Therefore, we disable write allocate for this range.
6974536af6aSKATO Takenori 		 */
6984536af6aSKATO Takenori 			wrmsr(0x86, 0x0ff00f0);
6994536af6aSKATO Takenori 			msr |= AMD_WT_ALLOC_PRE;
7004536af6aSKATO Takenori #endif
7014536af6aSKATO Takenori 		wrmsr(0x85, msr);
7024536af6aSKATO Takenori 
7034536af6aSKATO Takenori 		msr=rdmsr(0x83);
7044536af6aSKATO Takenori 		wrmsr(0x83, msr|0x10); /* enable write allocate */
705ba74981eSWarner Losh 		intr_restore(savecrit);
7064536af6aSKATO Takenori 	}
7074536af6aSKATO Takenori }
7084536af6aSKATO Takenori 
7094536af6aSKATO Takenori void
7104536af6aSKATO Takenori enable_K6_wt_alloc(void)
7114536af6aSKATO Takenori {
7124536af6aSKATO Takenori 	quad_t	size;
7134536af6aSKATO Takenori 	u_int64_t	whcr;
7144536af6aSKATO Takenori 	u_long	eflags;
7154536af6aSKATO Takenori 
7164536af6aSKATO Takenori 	eflags = read_eflags();
7174536af6aSKATO Takenori 	disable_intr();
7184536af6aSKATO Takenori 	wbinvd();
7194536af6aSKATO Takenori 
7204536af6aSKATO Takenori #ifdef CPU_DISABLE_CACHE
7214536af6aSKATO Takenori 	/*
7224536af6aSKATO Takenori 	 * Certain K6-2 box becomes unstable when write allocation is
7234536af6aSKATO Takenori 	 * enabled.
7244536af6aSKATO Takenori 	 */
7254536af6aSKATO Takenori 	/*
7264536af6aSKATO Takenori 	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
7274536af6aSKATO Takenori 	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
7284536af6aSKATO Takenori 	 * All other bits in TR12 have no effect on the processer's operation.
7294536af6aSKATO Takenori 	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
7304536af6aSKATO Takenori 	 * on the AMD-K6.
7314536af6aSKATO Takenori 	 */
7324536af6aSKATO Takenori 	wrmsr(0x0000000e, (u_int64_t)0x0008);
7334536af6aSKATO Takenori #endif
7344536af6aSKATO Takenori 	/* Don't assume that memory size is aligned with 4M. */
7354536af6aSKATO Takenori 	if (Maxmem > 0)
7364b055742SKATO Takenori 	  size = ((Maxmem >> 8) + 3) >> 2;
7374536af6aSKATO Takenori 	else
7384536af6aSKATO Takenori 	  size = 0;
7394536af6aSKATO Takenori 
7404536af6aSKATO Takenori 	/* Limit is 508M bytes. */
7414b055742SKATO Takenori 	if (size > 0x7f)
7424b055742SKATO Takenori 		size = 0x7f;
7434b055742SKATO Takenori 	whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1);
7444536af6aSKATO Takenori 
745925f3681SMike Smith #if defined(PC98) || defined(NO_MEMORY_HOLE)
7464b055742SKATO Takenori 	if (whcr & (0x7fLL << 1)) {
747925f3681SMike Smith #ifdef PC98
7484536af6aSKATO Takenori 		/*
7494536af6aSKATO Takenori 		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
7504536af6aSKATO Takenori 		 * 15-16M range.
7514536af6aSKATO Takenori 		 */
7524536af6aSKATO Takenori 		if (!(inb(0x43b) & 4))
7534536af6aSKATO Takenori 			whcr &= ~0x0001LL;
7544536af6aSKATO Takenori 		else
755925f3681SMike Smith #endif
7564536af6aSKATO Takenori 			whcr |=  0x0001LL;
7574536af6aSKATO Takenori 	}
7584536af6aSKATO Takenori #else
7594536af6aSKATO Takenori 	/*
7604536af6aSKATO Takenori 	 * There is no way to know wheter 15-16M hole exists or not.
7614536af6aSKATO Takenori 	 * Therefore, we disable write allocate for this range.
7624536af6aSKATO Takenori 	 */
763925f3681SMike Smith 	whcr &= ~0x0001LL;
764925f3681SMike Smith #endif
765925f3681SMike Smith 	wrmsr(0x0c0000082, whcr);
766925f3681SMike Smith 
767925f3681SMike Smith 	write_eflags(eflags);
768925f3681SMike Smith }
769925f3681SMike Smith 
770925f3681SMike Smith void
771925f3681SMike Smith enable_K6_2_wt_alloc(void)
772925f3681SMike Smith {
773925f3681SMike Smith 	quad_t	size;
774925f3681SMike Smith 	u_int64_t	whcr;
775925f3681SMike Smith 	u_long	eflags;
776925f3681SMike Smith 
777925f3681SMike Smith 	eflags = read_eflags();
778925f3681SMike Smith 	disable_intr();
779925f3681SMike Smith 	wbinvd();
780925f3681SMike Smith 
781925f3681SMike Smith #ifdef CPU_DISABLE_CACHE
782925f3681SMike Smith 	/*
783925f3681SMike Smith 	 * Certain K6-2 box becomes unstable when write allocation is
784925f3681SMike Smith 	 * enabled.
785925f3681SMike Smith 	 */
786925f3681SMike Smith 	/*
787925f3681SMike Smith 	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
788925f3681SMike Smith 	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
789925f3681SMike Smith 	 * All other bits in TR12 have no effect on the processer's operation.
790925f3681SMike Smith 	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
791925f3681SMike Smith 	 * on the AMD-K6.
792925f3681SMike Smith 	 */
793925f3681SMike Smith 	wrmsr(0x0000000e, (u_int64_t)0x0008);
794925f3681SMike Smith #endif
795925f3681SMike Smith 	/* Don't assume that memory size is aligned with 4M. */
796925f3681SMike Smith 	if (Maxmem > 0)
797925f3681SMike Smith 	  size = ((Maxmem >> 8) + 3) >> 2;
798925f3681SMike Smith 	else
799925f3681SMike Smith 	  size = 0;
800925f3681SMike Smith 
801925f3681SMike Smith 	/* Limit is 4092M bytes. */
8024b055742SKATO Takenori 	if (size > 0x3fff)
8034b055742SKATO Takenori 		size = 0x3ff;
804925f3681SMike Smith 	whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22);
805925f3681SMike Smith 
806925f3681SMike Smith #if defined(PC98) || defined(NO_MEMORY_HOLE)
807925f3681SMike Smith 	if (whcr & (0x3ffLL << 22)) {
808925f3681SMike Smith #ifdef PC98
809925f3681SMike Smith 		/*
810925f3681SMike Smith 		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
811925f3681SMike Smith 		 * 15-16M range.
812925f3681SMike Smith 		 */
813925f3681SMike Smith 		if (!(inb(0x43b) & 4))
814925f3681SMike Smith 			whcr &= ~(1LL << 16);
815925f3681SMike Smith 		else
816925f3681SMike Smith #endif
817925f3681SMike Smith 			whcr |=  1LL << 16;
818925f3681SMike Smith 	}
819925f3681SMike Smith #else
820925f3681SMike Smith 	/*
821925f3681SMike Smith 	 * There is no way to know wheter 15-16M hole exists or not.
822925f3681SMike Smith 	 * Therefore, we disable write allocate for this range.
823925f3681SMike Smith 	 */
824925f3681SMike Smith 	whcr &= ~(1LL << 16);
8254536af6aSKATO Takenori #endif
8264536af6aSKATO Takenori 	wrmsr(0x0c0000082, whcr);
8274536af6aSKATO Takenori 
8284536af6aSKATO Takenori 	write_eflags(eflags);
8294536af6aSKATO Takenori }
8304536af6aSKATO Takenori #endif /* I585_CPU && CPU_WT_ALLOC */
8314536af6aSKATO Takenori 
832a8e282d6SKATO Takenori #include "opt_ddb.h"
833a8e282d6SKATO Takenori #ifdef DDB
834a8e282d6SKATO Takenori #include <ddb/ddb.h>
835a8e282d6SKATO Takenori 
836a8e282d6SKATO Takenori DB_SHOW_COMMAND(cyrixreg, cyrixreg)
837a8e282d6SKATO Takenori {
838a8e282d6SKATO Takenori 	u_long	eflags;
839a8e282d6SKATO Takenori 	u_int	cr0;
8409402b520SMatthew Dillon 	u_char	ccr1, ccr2, ccr3;
8419402b520SMatthew Dillon 	u_char	ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0;
842a8e282d6SKATO Takenori 
843a8e282d6SKATO Takenori 	cr0 = rcr0();
844a8e282d6SKATO Takenori 	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
845a8e282d6SKATO Takenori 		eflags = read_eflags();
846a8e282d6SKATO Takenori 		disable_intr();
847a8e282d6SKATO Takenori 
848a8e282d6SKATO Takenori 
8499ca82267SKATO Takenori 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
850a8e282d6SKATO Takenori 			ccr0 = read_cyrix_reg(CCR0);
851a8e282d6SKATO Takenori 		}
852a8e282d6SKATO Takenori 		ccr1 = read_cyrix_reg(CCR1);
853a8e282d6SKATO Takenori 		ccr2 = read_cyrix_reg(CCR2);
854a8e282d6SKATO Takenori 		ccr3 = read_cyrix_reg(CCR3);
8556593be60SKATO Takenori 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
856a8e282d6SKATO Takenori 			write_cyrix_reg(CCR3, CCR3_MAPEN0);
857a8e282d6SKATO Takenori 			ccr4 = read_cyrix_reg(CCR4);
8586593be60SKATO Takenori 			if ((cpu == CPU_M1) || (cpu == CPU_M2))
859a8e282d6SKATO Takenori 				ccr5 = read_cyrix_reg(CCR5);
860a8e282d6SKATO Takenori 			else
861a8e282d6SKATO Takenori 				pcr0 = read_cyrix_reg(PCR0);
862a8e282d6SKATO Takenori 			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
863a8e282d6SKATO Takenori 		}
864a8e282d6SKATO Takenori 		write_eflags(eflags);
865a8e282d6SKATO Takenori 
8669ca82267SKATO Takenori 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
867a8e282d6SKATO Takenori 			printf("CCR0=%x, ", (u_int)ccr0);
868a8e282d6SKATO Takenori 
869a8e282d6SKATO Takenori 		printf("CCR1=%x, CCR2=%x, CCR3=%x",
870a8e282d6SKATO Takenori 			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
8716593be60SKATO Takenori 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
872a8e282d6SKATO Takenori 			printf(", CCR4=%x, ", (u_int)ccr4);
8736593be60SKATO Takenori 			if (cpu == CPU_M1SC)
874a8e282d6SKATO Takenori 				printf("PCR0=%x\n", pcr0);
8756593be60SKATO Takenori 			else
8766593be60SKATO Takenori 				printf("CCR5=%x\n", ccr5);
877a8e282d6SKATO Takenori 		}
878a8e282d6SKATO Takenori 	}
879a8e282d6SKATO Takenori 	printf("CR0=%x\n", cr0);
880a8e282d6SKATO Takenori }
881a8e282d6SKATO Takenori #endif /* DDB */
882