xref: /freebsd/sys/amd64/amd64/initcpu.c (revision ba74981e)
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 
43a8e282d6SKATO Takenori void initializecpu(void);
444536af6aSKATO Takenori #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
454536af6aSKATO Takenori void	enable_K5_wt_alloc(void);
464536af6aSKATO Takenori void	enable_K6_wt_alloc(void);
47925f3681SMike Smith void	enable_K6_2_wt_alloc(void);
484536af6aSKATO Takenori #endif
494536af6aSKATO Takenori 
50a8e282d6SKATO Takenori #ifdef I486_CPU
51a8e282d6SKATO Takenori static void init_5x86(void);
52a8e282d6SKATO Takenori static void init_bluelightning(void);
53a8e282d6SKATO Takenori static void init_486dlc(void);
549ca82267SKATO Takenori static void init_cy486dx(void);
55a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
56a8e282d6SKATO Takenori static void init_i486_on_386(void);
57a8e282d6SKATO Takenori #endif
58a8e282d6SKATO Takenori static void init_6x86(void);
59a8e282d6SKATO Takenori #endif /* I486_CPU */
60a8e282d6SKATO Takenori 
614877e978SKATO Takenori #ifdef I686_CPU
6220916c1fSKATO Takenori static void	init_6x86MX(void);
630d303cbaSKATO Takenori static void	init_ppro(void);
6465cbb03cSKATO Takenori static void	init_mendocino(void);
6520916c1fSKATO Takenori #endif
664faa812aSPeter Wemm void	enable_sse(void);
6720916c1fSKATO Takenori 
689d146ac5SPeter Wemm int	hw_instruction_sse = 0;
699d146ac5SPeter Wemm SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
709d146ac5SPeter Wemm 	   &hw_instruction_sse, 0,
719d146ac5SPeter Wemm 	   "SIMD/MMX2 instructions available in CPU");
729d146ac5SPeter Wemm 
7325ea330aSPeter Wemm /* Must *NOT* be BSS or locore will bzero these after setting them */
7425ea330aSPeter Wemm int	cpu = 0;		/* Are we 386, 386sx, 486, etc? */
7525ea330aSPeter Wemm u_int	cpu_id = 0;		/* Stepping ID */
7625ea330aSPeter Wemm u_int	cpu_feature = 0;	/* Feature flags */
7725ea330aSPeter Wemm u_int	cpu_high = 0;		/* Highest arg to CPUID */
785897d411SPeter Wemm #ifdef CPU_ENABLE_SSE
7925ea330aSPeter Wemm u_int	cpu_fxsr = 0;		/* SSE enabled */
805897d411SPeter Wemm #endif
8125ea330aSPeter Wemm char	cpu_vendor[20] = "";	/* CPU Origin code */
825897d411SPeter Wemm 
83a8e282d6SKATO Takenori #ifdef I486_CPU
84a8e282d6SKATO Takenori /*
85a8e282d6SKATO Takenori  * IBM Blue Lightning
86a8e282d6SKATO Takenori  */
87a8e282d6SKATO Takenori static void
88a8e282d6SKATO Takenori init_bluelightning(void)
89a8e282d6SKATO Takenori {
90a8e282d6SKATO Takenori 	u_long	eflags;
91a8e282d6SKATO Takenori 
92a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
93a8e282d6SKATO Takenori 	need_post_dma_flush = 1;
94a8e282d6SKATO Takenori #endif
95a8e282d6SKATO Takenori 
96a8e282d6SKATO Takenori 	eflags = read_eflags();
97a8e282d6SKATO Takenori 	disable_intr();
98a8e282d6SKATO Takenori 
99a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
100a8e282d6SKATO Takenori 	invd();
101a8e282d6SKATO Takenori 
102a8e282d6SKATO Takenori #ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE
103a8e282d6SKATO Takenori 	wrmsr(0x1000, 0x9c92LL);	/* FP operand can be cacheable on Cyrix FPU */
104a8e282d6SKATO Takenori #else
105a8e282d6SKATO Takenori 	wrmsr(0x1000, 0x1c92LL);	/* Intel FPU */
106a8e282d6SKATO Takenori #endif
107a8e282d6SKATO Takenori 	/* Enables 13MB and 0-640KB cache. */
108a8e282d6SKATO Takenori 	wrmsr(0x1001, (0xd0LL << 32) | 0x3ff);
109a8e282d6SKATO Takenori #ifdef CPU_BLUELIGHTNING_3X
110a8e282d6SKATO Takenori 	wrmsr(0x1002, 0x04000000LL);	/* Enables triple-clock mode. */
111a8e282d6SKATO Takenori #else
112a8e282d6SKATO Takenori 	wrmsr(0x1002, 0x03000000LL);	/* Enables double-clock mode. */
113a8e282d6SKATO Takenori #endif
114a8e282d6SKATO Takenori 
115a8e282d6SKATO Takenori 	/* Enable caching in CR0. */
116a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
117a8e282d6SKATO Takenori 	invd();
118a8e282d6SKATO Takenori 	write_eflags(eflags);
119a8e282d6SKATO Takenori }
120a8e282d6SKATO Takenori 
121a8e282d6SKATO Takenori /*
1229ca82267SKATO Takenori  * Cyrix 486SLC/DLC/SR/DR series
123a8e282d6SKATO Takenori  */
124a8e282d6SKATO Takenori static void
125a8e282d6SKATO Takenori init_486dlc(void)
126a8e282d6SKATO Takenori {
127a8e282d6SKATO Takenori 	u_long	eflags;
128a8e282d6SKATO Takenori 	u_char	ccr0;
129a8e282d6SKATO Takenori 
130a8e282d6SKATO Takenori 	eflags = read_eflags();
131a8e282d6SKATO Takenori 	disable_intr();
132a8e282d6SKATO Takenori 	invd();
133a8e282d6SKATO Takenori 
134a8e282d6SKATO Takenori 	ccr0 = read_cyrix_reg(CCR0);
135a8e282d6SKATO Takenori #ifndef CYRIX_CACHE_WORKS
136a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1 | CCR0_BARB;
137a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, ccr0);
138a8e282d6SKATO Takenori 	invd();
139a8e282d6SKATO Takenori #else
140a8e282d6SKATO Takenori 	ccr0 &= ~CCR0_NC0;
141a8e282d6SKATO Takenori #ifndef CYRIX_CACHE_REALLY_WORKS
142a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1 | CCR0_BARB;
143a8e282d6SKATO Takenori #else
144a8e282d6SKATO Takenori 	ccr0 |= CCR0_NC1;
145a8e282d6SKATO Takenori #endif
1464962d938SKATO Takenori #ifdef CPU_DIRECT_MAPPED_CACHE
1474962d938SKATO Takenori 	ccr0 |= CCR0_CO;			/* Direct mapped mode. */
1484962d938SKATO Takenori #endif
149a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, ccr0);
150a8e282d6SKATO Takenori 
151a8e282d6SKATO Takenori 	/* Clear non-cacheable region. */
152a8e282d6SKATO Takenori 	write_cyrix_reg(NCR1+2, NCR_SIZE_0K);
153a8e282d6SKATO Takenori 	write_cyrix_reg(NCR2+2, NCR_SIZE_0K);
154a8e282d6SKATO Takenori 	write_cyrix_reg(NCR3+2, NCR_SIZE_0K);
155a8e282d6SKATO Takenori 	write_cyrix_reg(NCR4+2, NCR_SIZE_0K);
156a8e282d6SKATO Takenori 
157a8e282d6SKATO Takenori 	write_cyrix_reg(0, 0);	/* dummy write */
158a8e282d6SKATO Takenori 
159a8e282d6SKATO Takenori 	/* Enable caching in CR0. */
160a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
161a8e282d6SKATO Takenori 	invd();
162a8e282d6SKATO Takenori #endif /* !CYRIX_CACHE_WORKS */
163a8e282d6SKATO Takenori 	write_eflags(eflags);
164a8e282d6SKATO Takenori }
165a8e282d6SKATO Takenori 
166a8e282d6SKATO Takenori 
167a8e282d6SKATO Takenori /*
1689ca82267SKATO Takenori  * Cyrix 486S/DX series
1699ca82267SKATO Takenori  */
1709ca82267SKATO Takenori static void
1719ca82267SKATO Takenori init_cy486dx(void)
1729ca82267SKATO Takenori {
1739ca82267SKATO Takenori 	u_long	eflags;
1749ca82267SKATO Takenori 	u_char	ccr2;
1759ca82267SKATO Takenori 
1769ca82267SKATO Takenori 	eflags = read_eflags();
1779ca82267SKATO Takenori 	disable_intr();
1789ca82267SKATO Takenori 	invd();
1799ca82267SKATO Takenori 
1809ca82267SKATO Takenori 	ccr2 = read_cyrix_reg(CCR2);
1811ba2a543SKATO Takenori #ifdef CPU_SUSP_HLT
1821ba2a543SKATO Takenori 	ccr2 |= CCR2_SUSP_HLT;
1839ca82267SKATO Takenori #endif
1841cfd836fSKATO Takenori 
1851cfd836fSKATO Takenori #ifdef PC98
1861cfd836fSKATO Takenori 	/* Enables WB cache interface pin and Lock NW bit in CR0. */
1871cfd836fSKATO Takenori 	ccr2 |= CCR2_WB | CCR2_LOCK_NW;
1881cfd836fSKATO Takenori 	/* Unlock NW bit in CR0. */
1891cfd836fSKATO Takenori 	write_cyrix_reg(CCR2, ccr2 & ~CCR2_LOCK_NW);
1901cfd836fSKATO Takenori 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
1911cfd836fSKATO Takenori #endif
1921cfd836fSKATO Takenori 
1939ca82267SKATO Takenori 	write_cyrix_reg(CCR2, ccr2);
1949ca82267SKATO Takenori 	write_eflags(eflags);
1959ca82267SKATO Takenori }
1969ca82267SKATO Takenori 
1979ca82267SKATO Takenori 
1989ca82267SKATO Takenori /*
199a8e282d6SKATO Takenori  * Cyrix 5x86
200a8e282d6SKATO Takenori  */
201a8e282d6SKATO Takenori static void
202a8e282d6SKATO Takenori init_5x86(void)
203a8e282d6SKATO Takenori {
204a8e282d6SKATO Takenori 	u_long	eflags;
205a8e282d6SKATO Takenori 	u_char	ccr2, ccr3, ccr4, pcr0;
206a8e282d6SKATO Takenori 
207a8e282d6SKATO Takenori 	eflags = read_eflags();
208a8e282d6SKATO Takenori 	disable_intr();
209a8e282d6SKATO Takenori 
210a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
211a8e282d6SKATO Takenori 	wbinvd();
212a8e282d6SKATO Takenori 
213a8e282d6SKATO Takenori 	(void)read_cyrix_reg(CCR3);		/* dummy */
214a8e282d6SKATO Takenori 
215a8e282d6SKATO Takenori 	/* Initialize CCR2. */
216a8e282d6SKATO Takenori 	ccr2 = read_cyrix_reg(CCR2);
217a8e282d6SKATO Takenori 	ccr2 |= CCR2_WB;
218a8e282d6SKATO Takenori #ifdef CPU_SUSP_HLT
219a8e282d6SKATO Takenori 	ccr2 |= CCR2_SUSP_HLT;
220a8e282d6SKATO Takenori #else
221a8e282d6SKATO Takenori 	ccr2 &= ~CCR2_SUSP_HLT;
222a8e282d6SKATO Takenori #endif
223a8e282d6SKATO Takenori 	ccr2 |= CCR2_WT1;
224a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, ccr2);
225a8e282d6SKATO Takenori 
226a8e282d6SKATO Takenori 	/* Initialize CCR4. */
227a8e282d6SKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
228a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
229a8e282d6SKATO Takenori 
230a8e282d6SKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
231a8e282d6SKATO Takenori 	ccr4 |= CCR4_DTE;
232a8e282d6SKATO Takenori 	ccr4 |= CCR4_MEM;
233a8e282d6SKATO Takenori #ifdef CPU_FASTER_5X86_FPU
234a8e282d6SKATO Takenori 	ccr4 |= CCR4_FASTFPE;
235a8e282d6SKATO Takenori #else
236a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_FASTFPE;
237a8e282d6SKATO Takenori #endif
238a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
239a8e282d6SKATO Takenori 	/********************************************************************
240a8e282d6SKATO Takenori 	 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time
241a8e282d6SKATO Takenori 	 * should be 0 for errata fix.
242a8e282d6SKATO Takenori 	 ********************************************************************/
243a8e282d6SKATO Takenori #ifdef CPU_IORT
244a8e282d6SKATO Takenori 	ccr4 |= CPU_IORT & CCR4_IOMASK;
245a8e282d6SKATO Takenori #endif
246a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4);
247a8e282d6SKATO Takenori 
248a8e282d6SKATO Takenori 	/* Initialize PCR0. */
249a8e282d6SKATO Takenori 	/****************************************************************
250a8e282d6SKATO Takenori 	 * WARNING: RSTK_EN and LOOP_EN could make your system unstable.
251a8e282d6SKATO Takenori 	 * BTB_EN might make your system unstable.
252a8e282d6SKATO Takenori 	 ****************************************************************/
253a8e282d6SKATO Takenori 	pcr0 = read_cyrix_reg(PCR0);
254a8e282d6SKATO Takenori #ifdef CPU_RSTK_EN
255a8e282d6SKATO Takenori 	pcr0 |= PCR0_RSTK;
256a8e282d6SKATO Takenori #else
257a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_RSTK;
258a8e282d6SKATO Takenori #endif
259a8e282d6SKATO Takenori #ifdef CPU_BTB_EN
260a8e282d6SKATO Takenori 	pcr0 |= PCR0_BTB;
261a8e282d6SKATO Takenori #else
262a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_BTB;
263a8e282d6SKATO Takenori #endif
264a8e282d6SKATO Takenori #ifdef CPU_LOOP_EN
265a8e282d6SKATO Takenori 	pcr0 |= PCR0_LOOP;
266a8e282d6SKATO Takenori #else
267a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_LOOP;
268a8e282d6SKATO Takenori #endif
269a8e282d6SKATO Takenori 
270a8e282d6SKATO Takenori 	/****************************************************************
271a8e282d6SKATO Takenori 	 * WARNING: if you use a memory mapped I/O device, don't use
272a8e282d6SKATO Takenori 	 * DISABLE_5X86_LSSER option, which may reorder memory mapped
273a8e282d6SKATO Takenori 	 * I/O access.
274a8e282d6SKATO Takenori 	 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER.
275a8e282d6SKATO Takenori 	 ****************************************************************/
276a8e282d6SKATO Takenori #ifdef CPU_DISABLE_5X86_LSSER
277a8e282d6SKATO Takenori 	pcr0 &= ~PCR0_LSSER;
278a8e282d6SKATO Takenori #else
279a8e282d6SKATO Takenori 	pcr0 |= PCR0_LSSER;
280a8e282d6SKATO Takenori #endif
281a8e282d6SKATO Takenori 	write_cyrix_reg(PCR0, pcr0);
282a8e282d6SKATO Takenori 
283a8e282d6SKATO Takenori 	/* Restore CCR3. */
284a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
285a8e282d6SKATO Takenori 
286a8e282d6SKATO Takenori 	(void)read_cyrix_reg(0x80);		/* dummy */
287a8e282d6SKATO Takenori 
288a8e282d6SKATO Takenori 	/* Unlock NW bit in CR0. */
289a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
290a8e282d6SKATO Takenori 	load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0, NW = 1 */
291a8e282d6SKATO Takenori 	/* Lock NW bit in CR0. */
292a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
293a8e282d6SKATO Takenori 
294a8e282d6SKATO Takenori 	write_eflags(eflags);
295a8e282d6SKATO Takenori }
296a8e282d6SKATO Takenori 
297a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
298a8e282d6SKATO Takenori /*
299a8e282d6SKATO Takenori  * There are i486 based upgrade products for i386 machines.
300a8e282d6SKATO Takenori  * In this case, BIOS doesn't enables CPU cache.
301a8e282d6SKATO Takenori  */
302a8e282d6SKATO Takenori void
303a8e282d6SKATO Takenori init_i486_on_386(void)
304a8e282d6SKATO Takenori {
305a8e282d6SKATO Takenori 	u_long	eflags;
306a8e282d6SKATO Takenori 
307a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
308a8e282d6SKATO Takenori 	need_post_dma_flush = 1;
309a8e282d6SKATO Takenori #endif
310a8e282d6SKATO Takenori 
311a8e282d6SKATO Takenori 	eflags = read_eflags();
312a8e282d6SKATO Takenori 	disable_intr();
313a8e282d6SKATO Takenori 
314a8e282d6SKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0, NW = 0 */
315a8e282d6SKATO Takenori 
3165fa4a058SKATO Takenori 	write_eflags(eflags);
317a8e282d6SKATO Takenori }
318a8e282d6SKATO Takenori #endif
319a8e282d6SKATO Takenori 
320a8e282d6SKATO Takenori /*
321a8e282d6SKATO Takenori  * Cyrix 6x86
322a8e282d6SKATO Takenori  *
323a8e282d6SKATO Takenori  * XXX - What should I do here?  Please let me know.
324a8e282d6SKATO Takenori  */
325a8e282d6SKATO Takenori static void
326a8e282d6SKATO Takenori init_6x86(void)
327a8e282d6SKATO Takenori {
328a8e282d6SKATO Takenori 	u_long	eflags;
329a8e282d6SKATO Takenori 	u_char	ccr3, ccr4;
330a8e282d6SKATO Takenori 
331a8e282d6SKATO Takenori 	eflags = read_eflags();
332a8e282d6SKATO Takenori 	disable_intr();
333a8e282d6SKATO Takenori 
334a8e282d6SKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
335a8e282d6SKATO Takenori 	wbinvd();
336a8e282d6SKATO Takenori 
337a8e282d6SKATO Takenori 	/* Initialize CCR0. */
338a8e282d6SKATO Takenori 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
339a8e282d6SKATO Takenori 
3406593be60SKATO Takenori 	/* Initialize CCR1. */
3416593be60SKATO Takenori #ifdef CPU_CYRIX_NO_LOCK
342b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
3436593be60SKATO Takenori #else
344b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
3456593be60SKATO Takenori #endif
3466593be60SKATO Takenori 
347a8e282d6SKATO Takenori 	/* Initialize CCR2. */
348a8e282d6SKATO Takenori #ifdef CPU_SUSP_HLT
349a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
350a8e282d6SKATO Takenori #else
351a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
352a8e282d6SKATO Takenori #endif
353a8e282d6SKATO Takenori 
354a8e282d6SKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
355a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
356a8e282d6SKATO Takenori 
357a8e282d6SKATO Takenori 	/* Initialize CCR4. */
358a8e282d6SKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
359a8e282d6SKATO Takenori 	ccr4 |= CCR4_DTE;
360a8e282d6SKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
361a8e282d6SKATO Takenori #ifdef CPU_IORT
362a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
363a8e282d6SKATO Takenori #else
364a8e282d6SKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | 7);
365a8e282d6SKATO Takenori #endif
366a8e282d6SKATO Takenori 
3676593be60SKATO Takenori 	/* Initialize CCR5. */
3686593be60SKATO Takenori #ifdef CPU_WT_ALLOC
3696593be60SKATO Takenori 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
3706593be60SKATO Takenori #endif
3716593be60SKATO Takenori 
372a8e282d6SKATO Takenori 	/* Restore CCR3. */
373a8e282d6SKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
374a8e282d6SKATO Takenori 
375a8e282d6SKATO Takenori 	/* Unlock NW bit in CR0. */
376a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
377a8e282d6SKATO Takenori 
378a8e282d6SKATO Takenori 	/*
379a8e282d6SKATO Takenori 	 * Earlier revision of the 6x86 CPU could crash the system if
380a8e282d6SKATO Takenori 	 * L1 cache is in write-back mode.
381a8e282d6SKATO Takenori 	 */
382a8e282d6SKATO Takenori 	if ((cyrix_did & 0xff00) > 0x1600)
383a8e282d6SKATO Takenori 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
384a8e282d6SKATO Takenori 	else {
385a8e282d6SKATO Takenori 		/* Revision 2.6 and lower. */
386a8e282d6SKATO Takenori #ifdef CYRIX_CACHE_REALLY_WORKS
387a8e282d6SKATO Takenori 		load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
388a8e282d6SKATO Takenori #else
389a8e282d6SKATO Takenori 		load_cr0((rcr0() & ~CR0_CD) | CR0_NW);	/* CD = 0 and NW = 1 */
390a8e282d6SKATO Takenori #endif
391a8e282d6SKATO Takenori 	}
392a8e282d6SKATO Takenori 
393a8e282d6SKATO Takenori 	/* Lock NW bit in CR0. */
394a8e282d6SKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
395a8e282d6SKATO Takenori 
396a8e282d6SKATO Takenori 	write_eflags(eflags);
397a8e282d6SKATO Takenori }
398a8e282d6SKATO Takenori #endif /* I486_CPU */
399a8e282d6SKATO Takenori 
4004877e978SKATO Takenori #ifdef I686_CPU
40120916c1fSKATO Takenori /*
40220916c1fSKATO Takenori  * Cyrix 6x86MX (code-named M2)
40320916c1fSKATO Takenori  *
40420916c1fSKATO Takenori  * XXX - What should I do here?  Please let me know.
40520916c1fSKATO Takenori  */
40620916c1fSKATO Takenori static void
40720916c1fSKATO Takenori init_6x86MX(void)
40820916c1fSKATO Takenori {
40920916c1fSKATO Takenori 	u_long	eflags;
41020916c1fSKATO Takenori 	u_char	ccr3, ccr4;
41120916c1fSKATO Takenori 
41220916c1fSKATO Takenori 	eflags = read_eflags();
41320916c1fSKATO Takenori 	disable_intr();
41420916c1fSKATO Takenori 
41520916c1fSKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
41620916c1fSKATO Takenori 	wbinvd();
41720916c1fSKATO Takenori 
41820916c1fSKATO Takenori 	/* Initialize CCR0. */
41920916c1fSKATO Takenori 	write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1);
42020916c1fSKATO Takenori 
4216593be60SKATO Takenori 	/* Initialize CCR1. */
4226593be60SKATO Takenori #ifdef CPU_CYRIX_NO_LOCK
423b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK);
4246593be60SKATO Takenori #else
425b20f1ceeSJonathan Lemon 	write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK);
4266593be60SKATO Takenori #endif
4276593be60SKATO Takenori 
42820916c1fSKATO Takenori 	/* Initialize CCR2. */
42920916c1fSKATO Takenori #ifdef CPU_SUSP_HLT
43020916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT);
43120916c1fSKATO Takenori #else
43220916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT);
43320916c1fSKATO Takenori #endif
43420916c1fSKATO Takenori 
43520916c1fSKATO Takenori 	ccr3 = read_cyrix_reg(CCR3);
43620916c1fSKATO Takenori 	write_cyrix_reg(CCR3, CCR3_MAPEN0);
43720916c1fSKATO Takenori 
43820916c1fSKATO Takenori 	/* Initialize CCR4. */
43920916c1fSKATO Takenori 	ccr4 = read_cyrix_reg(CCR4);
44020916c1fSKATO Takenori 	ccr4 &= ~CCR4_IOMASK;
44120916c1fSKATO Takenori #ifdef CPU_IORT
44220916c1fSKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK));
44320916c1fSKATO Takenori #else
44420916c1fSKATO Takenori 	write_cyrix_reg(CCR4, ccr4 | 7);
44520916c1fSKATO Takenori #endif
44620916c1fSKATO Takenori 
4476593be60SKATO Takenori 	/* Initialize CCR5. */
4486593be60SKATO Takenori #ifdef CPU_WT_ALLOC
4496593be60SKATO Takenori 	write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC);
4506593be60SKATO Takenori #endif
4516593be60SKATO Takenori 
45220916c1fSKATO Takenori 	/* Restore CCR3. */
45320916c1fSKATO Takenori 	write_cyrix_reg(CCR3, ccr3);
45420916c1fSKATO Takenori 
45520916c1fSKATO Takenori 	/* Unlock NW bit in CR0. */
45620916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW);
45720916c1fSKATO Takenori 
45820916c1fSKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));	/* CD = 0 and NW = 0 */
45920916c1fSKATO Takenori 
46020916c1fSKATO Takenori 	/* Lock NW bit in CR0. */
46120916c1fSKATO Takenori 	write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW);
46220916c1fSKATO Takenori 
46320916c1fSKATO Takenori 	write_eflags(eflags);
46420916c1fSKATO Takenori }
4650d303cbaSKATO Takenori 
4660d303cbaSKATO Takenori static void
4670d303cbaSKATO Takenori init_ppro(void)
4680d303cbaSKATO Takenori {
4690d303cbaSKATO Takenori #ifndef SMP
4704536af6aSKATO Takenori 	u_int64_t	apicbase;
4710d303cbaSKATO Takenori 
4720d303cbaSKATO Takenori 	/*
4730d303cbaSKATO Takenori 	 * Local APIC should be diabled in UP kernel.
4740d303cbaSKATO Takenori 	 */
4750d303cbaSKATO Takenori 	apicbase = rdmsr(0x1b);
4760d303cbaSKATO Takenori 	apicbase &= ~0x800LL;
4770d303cbaSKATO Takenori 	wrmsr(0x1b, apicbase);
4780d303cbaSKATO Takenori #endif
4790d303cbaSKATO Takenori }
48065cbb03cSKATO Takenori 
48165cbb03cSKATO Takenori /*
48265cbb03cSKATO Takenori  * Initialize BBL_CR_CTL3 (Control register 3: used to configure the
48365cbb03cSKATO Takenori  * L2 cache).
48465cbb03cSKATO Takenori  */
48565cbb03cSKATO Takenori void
48665cbb03cSKATO Takenori init_mendocino(void)
48765cbb03cSKATO Takenori {
48865cbb03cSKATO Takenori #ifdef CPU_PPRO2CELERON
48965cbb03cSKATO Takenori 	u_long	eflags;
49065cbb03cSKATO Takenori 	u_int64_t	bbl_cr_ctl3;
49165cbb03cSKATO Takenori 
49265cbb03cSKATO Takenori 	eflags = read_eflags();
49365cbb03cSKATO Takenori 	disable_intr();
49465cbb03cSKATO Takenori 
49565cbb03cSKATO Takenori 	load_cr0(rcr0() | CR0_CD | CR0_NW);
49665cbb03cSKATO Takenori 	wbinvd();
49765cbb03cSKATO Takenori 
49865cbb03cSKATO Takenori 	bbl_cr_ctl3 = rdmsr(0x11e);
49965cbb03cSKATO Takenori 
50065cbb03cSKATO Takenori 	/* If the L2 cache is configured, do nothing. */
50165cbb03cSKATO Takenori 	if (!(bbl_cr_ctl3 & 1)) {
50265cbb03cSKATO Takenori 		bbl_cr_ctl3 = 0x134052bLL;
50365cbb03cSKATO Takenori 
50465cbb03cSKATO Takenori 		/* Set L2 Cache Latency (Default: 5). */
50565cbb03cSKATO Takenori #ifdef	CPU_CELERON_L2_LATENCY
50665cbb03cSKATO Takenori #if CPU_L2_LATENCY > 15
50765cbb03cSKATO Takenori #error invalid CPU_L2_LATENCY.
50865cbb03cSKATO Takenori #endif
50965cbb03cSKATO Takenori 		bbl_cr_ctl3 |= CPU_L2_LATENCY << 1;
51065cbb03cSKATO Takenori #else
51165cbb03cSKATO Takenori 		bbl_cr_ctl3 |= 5 << 1;
51265cbb03cSKATO Takenori #endif
51365cbb03cSKATO Takenori 		wrmsr(0x11e, bbl_cr_ctl3);
51465cbb03cSKATO Takenori 	}
51565cbb03cSKATO Takenori 
51665cbb03cSKATO Takenori 	load_cr0(rcr0() & ~(CR0_CD | CR0_NW));
51765cbb03cSKATO Takenori 	write_eflags(eflags);
51865cbb03cSKATO Takenori #endif /* CPU_PPRO2CELERON */
51965cbb03cSKATO Takenori }
52065cbb03cSKATO Takenori 
5214faa812aSPeter Wemm #endif /* I686_CPU */
5224faa812aSPeter Wemm 
5239d146ac5SPeter Wemm /*
5249d146ac5SPeter Wemm  * Initialize CR4 (Control register 4) to enable SSE instructions.
5259d146ac5SPeter Wemm  */
5269d146ac5SPeter Wemm void
5279d146ac5SPeter Wemm enable_sse(void)
5289d146ac5SPeter Wemm {
5299d146ac5SPeter Wemm #if defined(CPU_ENABLE_SSE)
5309d146ac5SPeter Wemm 	if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
5319d146ac5SPeter Wemm 		load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
5329d146ac5SPeter Wemm 		cpu_fxsr = hw_instruction_sse = 1;
5339d146ac5SPeter Wemm 	}
5349d146ac5SPeter Wemm #endif
5359d146ac5SPeter Wemm }
5369d146ac5SPeter Wemm 
537a8e282d6SKATO Takenori void
538a8e282d6SKATO Takenori initializecpu(void)
539a8e282d6SKATO Takenori {
540a8e282d6SKATO Takenori 
541a8e282d6SKATO Takenori 	switch (cpu) {
542a8e282d6SKATO Takenori #ifdef I486_CPU
543a8e282d6SKATO Takenori 	case CPU_BLUE:
544a8e282d6SKATO Takenori 		init_bluelightning();
545a8e282d6SKATO Takenori 		break;
546a8e282d6SKATO Takenori 	case CPU_486DLC:
547a8e282d6SKATO Takenori 		init_486dlc();
548a8e282d6SKATO Takenori 		break;
5499ca82267SKATO Takenori 	case CPU_CY486DX:
5509ca82267SKATO Takenori 		init_cy486dx();
5519ca82267SKATO Takenori 		break;
552a8e282d6SKATO Takenori 	case CPU_M1SC:
553a8e282d6SKATO Takenori 		init_5x86();
554a8e282d6SKATO Takenori 		break;
555a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
556a8e282d6SKATO Takenori 	case CPU_486:
557a8e282d6SKATO Takenori 		init_i486_on_386();
558a8e282d6SKATO Takenori 		break;
559a8e282d6SKATO Takenori #endif
560a8e282d6SKATO Takenori 	case CPU_M1:
561a8e282d6SKATO Takenori 		init_6x86();
562a8e282d6SKATO Takenori 		break;
563a8e282d6SKATO Takenori #endif /* I486_CPU */
5644877e978SKATO Takenori #ifdef I686_CPU
56520916c1fSKATO Takenori 	case CPU_M2:
56620916c1fSKATO Takenori 		init_6x86MX();
56720916c1fSKATO Takenori 		break;
5680d303cbaSKATO Takenori 	case CPU_686:
56965cbb03cSKATO Takenori 		if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
57065cbb03cSKATO Takenori 			switch (cpu_id & 0xff0) {
57165cbb03cSKATO Takenori 			case 0x610:
5720d303cbaSKATO Takenori 				init_ppro();
5730d303cbaSKATO Takenori 				break;
57465cbb03cSKATO Takenori 			case 0x660:
57565cbb03cSKATO Takenori 				init_mendocino();
57665cbb03cSKATO Takenori 				break;
57765cbb03cSKATO Takenori 			}
5786df7ca7bSDavid Malone 		} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
5796df7ca7bSDavid Malone #if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK)
5806df7ca7bSDavid Malone 			/*
5816df7ca7bSDavid Malone 			 * Sometimes the BIOS doesn't enable SSE instructions.
5826df7ca7bSDavid Malone 			 * According to AMD document 20734, the mobile
5836df7ca7bSDavid Malone 			 * Duron, the (mobile) Athlon 4 and the Athlon MP
5846df7ca7bSDavid Malone 			 * support SSE. These correspond to cpu_id 0x66X
5856df7ca7bSDavid Malone 			 * or 0x67X.
5866df7ca7bSDavid Malone 			 */
5876df7ca7bSDavid Malone 			if ((cpu_feature & CPUID_XMM) == 0 &&
5886df7ca7bSDavid Malone 			    ((cpu_id & ~0xf) == 0x660 ||
5896df7ca7bSDavid Malone 			     (cpu_id & ~0xf) == 0x670)) {
5906df7ca7bSDavid Malone 				u_int regs[4];
5916df7ca7bSDavid Malone 				wrmsr(0xC0010015, rdmsr(0xC0010015) & ~0x08000);
5926df7ca7bSDavid Malone 				do_cpuid(1, regs);
5936df7ca7bSDavid Malone 				cpu_feature = regs[3];
5946df7ca7bSDavid Malone 			}
5956df7ca7bSDavid Malone #endif
59665cbb03cSKATO Takenori 		}
59765cbb03cSKATO Takenori 		break;
59820916c1fSKATO Takenori #endif
599a8e282d6SKATO Takenori 	default:
600a8e282d6SKATO Takenori 		break;
601a8e282d6SKATO Takenori 	}
602aa32e9a9SPeter Wemm 	enable_sse();
603a8e282d6SKATO Takenori 
604a8e282d6SKATO Takenori #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)
605a8e282d6SKATO Takenori 	/*
6065b488b34SJeroen Ruigrok van der Werven 	 * OS should flush L1 cache by itself because no PC-98 supports
607a8e282d6SKATO Takenori 	 * non-Intel CPUs.  Use wbinvd instruction before DMA transfer
608a8e282d6SKATO Takenori 	 * when need_pre_dma_flush = 1, use invd instruction after DMA
609a8e282d6SKATO Takenori 	 * transfer when need_post_dma_flush = 1.  If your CPU upgrade
6105b488b34SJeroen Ruigrok van der Werven 	 * product supports hardware cache control, you can add the
611a47ea7b9SJeroen Ruigrok van der Werven 	 * CPU_UPGRADE_HW_CACHE option in your kernel configuration file.
6125b488b34SJeroen Ruigrok van der Werven 	 * This option eliminates unneeded cache flush instruction(s).
613a8e282d6SKATO Takenori 	 */
614a8e282d6SKATO Takenori 	if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
615a8e282d6SKATO Takenori 		switch (cpu) {
616a8e282d6SKATO Takenori #ifdef I486_CPU
617a8e282d6SKATO Takenori 		case CPU_486DLC:
618a8e282d6SKATO Takenori 			need_post_dma_flush = 1;
619a8e282d6SKATO Takenori 			break;
620a8e282d6SKATO Takenori 		case CPU_M1SC:
621a8e282d6SKATO Takenori 			need_pre_dma_flush = 1;
622a8e282d6SKATO Takenori 			break;
6231cfd836fSKATO Takenori 		case CPU_CY486DX:
6241cfd836fSKATO Takenori 			need_pre_dma_flush = 1;
6251cfd836fSKATO Takenori #ifdef CPU_I486_ON_386
6261cfd836fSKATO Takenori 			need_post_dma_flush = 1;
6271cfd836fSKATO Takenori #endif
6281cfd836fSKATO Takenori 			break;
629a8e282d6SKATO Takenori #endif
630a8e282d6SKATO Takenori 		default:
631a8e282d6SKATO Takenori 			break;
632a8e282d6SKATO Takenori 		}
633a8e282d6SKATO Takenori 	} else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
634a8e282d6SKATO Takenori 		switch (cpu_id & 0xFF0) {
635a8e282d6SKATO Takenori 		case 0x470:		/* Enhanced Am486DX2 WB */
636a8e282d6SKATO Takenori 		case 0x490:		/* Enhanced Am486DX4 WB */
637a8e282d6SKATO Takenori 		case 0x4F0:		/* Am5x86 WB */
638a8e282d6SKATO Takenori 			need_pre_dma_flush = 1;
639a8e282d6SKATO Takenori 			break;
640a8e282d6SKATO Takenori 		}
641a8e282d6SKATO Takenori 	} else if (strcmp(cpu_vendor, "IBM") == 0) {
642a8e282d6SKATO Takenori 		need_post_dma_flush = 1;
643a8e282d6SKATO Takenori 	} else {
644a8e282d6SKATO Takenori #ifdef CPU_I486_ON_386
645a8e282d6SKATO Takenori 		need_pre_dma_flush = 1;
646a8e282d6SKATO Takenori #endif
647a8e282d6SKATO Takenori 	}
648a47ea7b9SJeroen Ruigrok van der Werven #endif /* PC98 && !CPU_UPGRADE_HW_CACHE */
649a8e282d6SKATO Takenori }
650a8e282d6SKATO Takenori 
6514536af6aSKATO Takenori #if defined(I586_CPU) && defined(CPU_WT_ALLOC)
6524536af6aSKATO Takenori /*
6534536af6aSKATO Takenori  * Enable write allocate feature of AMD processors.
6544536af6aSKATO Takenori  * Following two functions require the Maxmem variable being set.
6554536af6aSKATO Takenori  */
6564536af6aSKATO Takenori void
6574536af6aSKATO Takenori enable_K5_wt_alloc(void)
6584536af6aSKATO Takenori {
6594536af6aSKATO Takenori 	u_int64_t	msr;
660ba74981eSWarner Losh 	register_t	savecrit;
6614536af6aSKATO Takenori 
6624536af6aSKATO Takenori 	/*
6634536af6aSKATO Takenori 	 * Write allocate is supported only on models 1, 2, and 3, with
6644536af6aSKATO Takenori 	 * a stepping of 4 or greater.
6654536af6aSKATO Takenori 	 */
6664536af6aSKATO Takenori 	if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) {
667ba74981eSWarner Losh 		savecrit = intr_disable();
6684536af6aSKATO Takenori 		msr = rdmsr(0x83);		/* HWCR */
6694536af6aSKATO Takenori 		wrmsr(0x83, msr & !(0x10));
6704536af6aSKATO Takenori 
6714536af6aSKATO Takenori 		/*
6724536af6aSKATO Takenori 		 * We have to tell the chip where the top of memory is,
6734536af6aSKATO Takenori 		 * since video cards could have frame bufferes there,
6744536af6aSKATO Takenori 		 * memory-mapped I/O could be there, etc.
6754536af6aSKATO Takenori 		 */
6764536af6aSKATO Takenori 		if(Maxmem > 0)
6774536af6aSKATO Takenori 		  msr = Maxmem / 16;
6784536af6aSKATO Takenori 		else
6794536af6aSKATO Takenori 		  msr = 0;
6804536af6aSKATO Takenori 		msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE;
6814536af6aSKATO Takenori #ifdef PC98
6824536af6aSKATO Takenori 		if (!(inb(0x43b) & 4)) {
6834536af6aSKATO Takenori 			wrmsr(0x86, 0x0ff00f0);
6844536af6aSKATO Takenori 			msr |= AMD_WT_ALLOC_PRE;
6854536af6aSKATO Takenori 		}
6864536af6aSKATO Takenori #else
6874536af6aSKATO Takenori 		/*
6884536af6aSKATO Takenori 		 * There is no way to know wheter 15-16M hole exists or not.
6894536af6aSKATO Takenori 		 * Therefore, we disable write allocate for this range.
6904536af6aSKATO Takenori 		 */
6914536af6aSKATO Takenori 			wrmsr(0x86, 0x0ff00f0);
6924536af6aSKATO Takenori 			msr |= AMD_WT_ALLOC_PRE;
6934536af6aSKATO Takenori #endif
6944536af6aSKATO Takenori 		wrmsr(0x85, msr);
6954536af6aSKATO Takenori 
6964536af6aSKATO Takenori 		msr=rdmsr(0x83);
6974536af6aSKATO Takenori 		wrmsr(0x83, msr|0x10); /* enable write allocate */
698ba74981eSWarner Losh 		intr_restore(savecrit);
6994536af6aSKATO Takenori 	}
7004536af6aSKATO Takenori }
7014536af6aSKATO Takenori 
7024536af6aSKATO Takenori void
7034536af6aSKATO Takenori enable_K6_wt_alloc(void)
7044536af6aSKATO Takenori {
7054536af6aSKATO Takenori 	quad_t	size;
7064536af6aSKATO Takenori 	u_int64_t	whcr;
7074536af6aSKATO Takenori 	u_long	eflags;
7084536af6aSKATO Takenori 
7094536af6aSKATO Takenori 	eflags = read_eflags();
7104536af6aSKATO Takenori 	disable_intr();
7114536af6aSKATO Takenori 	wbinvd();
7124536af6aSKATO Takenori 
7134536af6aSKATO Takenori #ifdef CPU_DISABLE_CACHE
7144536af6aSKATO Takenori 	/*
7154536af6aSKATO Takenori 	 * Certain K6-2 box becomes unstable when write allocation is
7164536af6aSKATO Takenori 	 * enabled.
7174536af6aSKATO Takenori 	 */
7184536af6aSKATO Takenori 	/*
7194536af6aSKATO Takenori 	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
7204536af6aSKATO Takenori 	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
7214536af6aSKATO Takenori 	 * All other bits in TR12 have no effect on the processer's operation.
7224536af6aSKATO Takenori 	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
7234536af6aSKATO Takenori 	 * on the AMD-K6.
7244536af6aSKATO Takenori 	 */
7254536af6aSKATO Takenori 	wrmsr(0x0000000e, (u_int64_t)0x0008);
7264536af6aSKATO Takenori #endif
7274536af6aSKATO Takenori 	/* Don't assume that memory size is aligned with 4M. */
7284536af6aSKATO Takenori 	if (Maxmem > 0)
7294b055742SKATO Takenori 	  size = ((Maxmem >> 8) + 3) >> 2;
7304536af6aSKATO Takenori 	else
7314536af6aSKATO Takenori 	  size = 0;
7324536af6aSKATO Takenori 
7334536af6aSKATO Takenori 	/* Limit is 508M bytes. */
7344b055742SKATO Takenori 	if (size > 0x7f)
7354b055742SKATO Takenori 		size = 0x7f;
7364b055742SKATO Takenori 	whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1);
7374536af6aSKATO Takenori 
738925f3681SMike Smith #if defined(PC98) || defined(NO_MEMORY_HOLE)
7394b055742SKATO Takenori 	if (whcr & (0x7fLL << 1)) {
740925f3681SMike Smith #ifdef PC98
7414536af6aSKATO Takenori 		/*
7424536af6aSKATO Takenori 		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
7434536af6aSKATO Takenori 		 * 15-16M range.
7444536af6aSKATO Takenori 		 */
7454536af6aSKATO Takenori 		if (!(inb(0x43b) & 4))
7464536af6aSKATO Takenori 			whcr &= ~0x0001LL;
7474536af6aSKATO Takenori 		else
748925f3681SMike Smith #endif
7494536af6aSKATO Takenori 			whcr |=  0x0001LL;
7504536af6aSKATO Takenori 	}
7514536af6aSKATO Takenori #else
7524536af6aSKATO Takenori 	/*
7534536af6aSKATO Takenori 	 * There is no way to know wheter 15-16M hole exists or not.
7544536af6aSKATO Takenori 	 * Therefore, we disable write allocate for this range.
7554536af6aSKATO Takenori 	 */
756925f3681SMike Smith 	whcr &= ~0x0001LL;
757925f3681SMike Smith #endif
758925f3681SMike Smith 	wrmsr(0x0c0000082, whcr);
759925f3681SMike Smith 
760925f3681SMike Smith 	write_eflags(eflags);
761925f3681SMike Smith }
762925f3681SMike Smith 
763925f3681SMike Smith void
764925f3681SMike Smith enable_K6_2_wt_alloc(void)
765925f3681SMike Smith {
766925f3681SMike Smith 	quad_t	size;
767925f3681SMike Smith 	u_int64_t	whcr;
768925f3681SMike Smith 	u_long	eflags;
769925f3681SMike Smith 
770925f3681SMike Smith 	eflags = read_eflags();
771925f3681SMike Smith 	disable_intr();
772925f3681SMike Smith 	wbinvd();
773925f3681SMike Smith 
774925f3681SMike Smith #ifdef CPU_DISABLE_CACHE
775925f3681SMike Smith 	/*
776925f3681SMike Smith 	 * Certain K6-2 box becomes unstable when write allocation is
777925f3681SMike Smith 	 * enabled.
778925f3681SMike Smith 	 */
779925f3681SMike Smith 	/*
780925f3681SMike Smith 	 * The AMD-K6 processer provides the 64-bit Test Register 12(TR12),
781925f3681SMike Smith 	 * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported.
782925f3681SMike Smith 	 * All other bits in TR12 have no effect on the processer's operation.
783925f3681SMike Smith 	 * The I/O Trap Restart function (bit 9 of TR12) is always enabled
784925f3681SMike Smith 	 * on the AMD-K6.
785925f3681SMike Smith 	 */
786925f3681SMike Smith 	wrmsr(0x0000000e, (u_int64_t)0x0008);
787925f3681SMike Smith #endif
788925f3681SMike Smith 	/* Don't assume that memory size is aligned with 4M. */
789925f3681SMike Smith 	if (Maxmem > 0)
790925f3681SMike Smith 	  size = ((Maxmem >> 8) + 3) >> 2;
791925f3681SMike Smith 	else
792925f3681SMike Smith 	  size = 0;
793925f3681SMike Smith 
794925f3681SMike Smith 	/* Limit is 4092M bytes. */
7954b055742SKATO Takenori 	if (size > 0x3fff)
7964b055742SKATO Takenori 		size = 0x3ff;
797925f3681SMike Smith 	whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22);
798925f3681SMike Smith 
799925f3681SMike Smith #if defined(PC98) || defined(NO_MEMORY_HOLE)
800925f3681SMike Smith 	if (whcr & (0x3ffLL << 22)) {
801925f3681SMike Smith #ifdef PC98
802925f3681SMike Smith 		/*
803925f3681SMike Smith 		 * If bit 2 of port 0x43b is 0, disable wrte allocate for the
804925f3681SMike Smith 		 * 15-16M range.
805925f3681SMike Smith 		 */
806925f3681SMike Smith 		if (!(inb(0x43b) & 4))
807925f3681SMike Smith 			whcr &= ~(1LL << 16);
808925f3681SMike Smith 		else
809925f3681SMike Smith #endif
810925f3681SMike Smith 			whcr |=  1LL << 16;
811925f3681SMike Smith 	}
812925f3681SMike Smith #else
813925f3681SMike Smith 	/*
814925f3681SMike Smith 	 * There is no way to know wheter 15-16M hole exists or not.
815925f3681SMike Smith 	 * Therefore, we disable write allocate for this range.
816925f3681SMike Smith 	 */
817925f3681SMike Smith 	whcr &= ~(1LL << 16);
8184536af6aSKATO Takenori #endif
8194536af6aSKATO Takenori 	wrmsr(0x0c0000082, whcr);
8204536af6aSKATO Takenori 
8214536af6aSKATO Takenori 	write_eflags(eflags);
8224536af6aSKATO Takenori }
8234536af6aSKATO Takenori #endif /* I585_CPU && CPU_WT_ALLOC */
8244536af6aSKATO Takenori 
825a8e282d6SKATO Takenori #include "opt_ddb.h"
826a8e282d6SKATO Takenori #ifdef DDB
827a8e282d6SKATO Takenori #include <ddb/ddb.h>
828a8e282d6SKATO Takenori 
829a8e282d6SKATO Takenori DB_SHOW_COMMAND(cyrixreg, cyrixreg)
830a8e282d6SKATO Takenori {
831a8e282d6SKATO Takenori 	u_long	eflags;
832a8e282d6SKATO Takenori 	u_int	cr0;
8339402b520SMatthew Dillon 	u_char	ccr1, ccr2, ccr3;
8349402b520SMatthew Dillon 	u_char	ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0;
835a8e282d6SKATO Takenori 
836a8e282d6SKATO Takenori 	cr0 = rcr0();
837a8e282d6SKATO Takenori 	if (strcmp(cpu_vendor,"CyrixInstead") == 0) {
838a8e282d6SKATO Takenori 		eflags = read_eflags();
839a8e282d6SKATO Takenori 		disable_intr();
840a8e282d6SKATO Takenori 
841a8e282d6SKATO Takenori 
8429ca82267SKATO Takenori 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) {
843a8e282d6SKATO Takenori 			ccr0 = read_cyrix_reg(CCR0);
844a8e282d6SKATO Takenori 		}
845a8e282d6SKATO Takenori 		ccr1 = read_cyrix_reg(CCR1);
846a8e282d6SKATO Takenori 		ccr2 = read_cyrix_reg(CCR2);
847a8e282d6SKATO Takenori 		ccr3 = read_cyrix_reg(CCR3);
8486593be60SKATO Takenori 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
849a8e282d6SKATO Takenori 			write_cyrix_reg(CCR3, CCR3_MAPEN0);
850a8e282d6SKATO Takenori 			ccr4 = read_cyrix_reg(CCR4);
8516593be60SKATO Takenori 			if ((cpu == CPU_M1) || (cpu == CPU_M2))
852a8e282d6SKATO Takenori 				ccr5 = read_cyrix_reg(CCR5);
853a8e282d6SKATO Takenori 			else
854a8e282d6SKATO Takenori 				pcr0 = read_cyrix_reg(PCR0);
855a8e282d6SKATO Takenori 			write_cyrix_reg(CCR3, ccr3);		/* Restore CCR3. */
856a8e282d6SKATO Takenori 		}
857a8e282d6SKATO Takenori 		write_eflags(eflags);
858a8e282d6SKATO Takenori 
8599ca82267SKATO Takenori 		if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX))
860a8e282d6SKATO Takenori 			printf("CCR0=%x, ", (u_int)ccr0);
861a8e282d6SKATO Takenori 
862a8e282d6SKATO Takenori 		printf("CCR1=%x, CCR2=%x, CCR3=%x",
863a8e282d6SKATO Takenori 			(u_int)ccr1, (u_int)ccr2, (u_int)ccr3);
8646593be60SKATO Takenori 		if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) {
865a8e282d6SKATO Takenori 			printf(", CCR4=%x, ", (u_int)ccr4);
8666593be60SKATO Takenori 			if (cpu == CPU_M1SC)
867a8e282d6SKATO Takenori 				printf("PCR0=%x\n", pcr0);
8686593be60SKATO Takenori 			else
8696593be60SKATO Takenori 				printf("CCR5=%x\n", ccr5);
870a8e282d6SKATO Takenori 		}
871a8e282d6SKATO Takenori 	}
872a8e282d6SKATO Takenori 	printf("CR0=%x\n", cr0);
873a8e282d6SKATO Takenori }
874a8e282d6SKATO Takenori #endif /* DDB */
875