xref: /titanic_53/usr/src/uts/i86pc/os/cpuid.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Various routines to handle identification
31*7c478bd9Sstevel@tonic-gate  * and classification of x86 processors.
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/x86_archext.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/processor.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/chip.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/fp.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/controlregs.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/auxv_386.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/bitmap.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/controlregs.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/memnode.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * Pass 0 of cpuid feature analysis happens in locore. It contains special code
54*7c478bd9Sstevel@tonic-gate  * to recognize Cyrix processors that are not cpuid-compliant, and to deal with
55*7c478bd9Sstevel@tonic-gate  * them accordingly. For most modern processors, feature detection occurs here
56*7c478bd9Sstevel@tonic-gate  * in pass 1.
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  * Pass 1 of cpuid feature analysis happens just at the beginning of mlsetup()
59*7c478bd9Sstevel@tonic-gate  * for the boot CPU and does the basic analysis that the early kernel needs.
60*7c478bd9Sstevel@tonic-gate  * x86_feature is set based on the return value of cpuid_pass1() of the boot
61*7c478bd9Sstevel@tonic-gate  * CPU.
62*7c478bd9Sstevel@tonic-gate  *
63*7c478bd9Sstevel@tonic-gate  * Pass 1 includes:
64*7c478bd9Sstevel@tonic-gate  *
65*7c478bd9Sstevel@tonic-gate  *	o Determining vendor/model/family/stepping and setting x86_type and
66*7c478bd9Sstevel@tonic-gate  *	  x86_vendor accordingly.
67*7c478bd9Sstevel@tonic-gate  *	o Processing the feature flags returned by the cpuid instruction while
68*7c478bd9Sstevel@tonic-gate  *	  applying any workarounds or tricks for the specific processor.
69*7c478bd9Sstevel@tonic-gate  *	o Mapping the feature flags into Solaris feature bits (X86_*).
70*7c478bd9Sstevel@tonic-gate  *	o Processing extended feature flags if supported by the processor,
71*7c478bd9Sstevel@tonic-gate  *	  again while applying specific processor knowledge.
72*7c478bd9Sstevel@tonic-gate  *	o Determining the CMT characteristics of the system.
73*7c478bd9Sstevel@tonic-gate  *
74*7c478bd9Sstevel@tonic-gate  * Pass 1 is done on non-boot CPUs during their initialization and the results
75*7c478bd9Sstevel@tonic-gate  * are used only as a meager attempt at ensuring that all processors within the
76*7c478bd9Sstevel@tonic-gate  * system support the same features.
77*7c478bd9Sstevel@tonic-gate  *
78*7c478bd9Sstevel@tonic-gate  * Pass 2 of cpuid feature analysis happens just at the beginning
79*7c478bd9Sstevel@tonic-gate  * of startup().  It just copies in and corrects the remainder
80*7c478bd9Sstevel@tonic-gate  * of the cpuid data we depend on: standard cpuid functions that we didn't
81*7c478bd9Sstevel@tonic-gate  * need for pass1 feature analysis, and extended cpuid functions beyond the
82*7c478bd9Sstevel@tonic-gate  * simple feature processing done in pass1.
83*7c478bd9Sstevel@tonic-gate  *
84*7c478bd9Sstevel@tonic-gate  * Pass 3 of cpuid analysis is invoked after basic kernel services; in
85*7c478bd9Sstevel@tonic-gate  * particular kernel memory allocation has been made available. It creates a
86*7c478bd9Sstevel@tonic-gate  * readable brand string based on the data collected in the first two passes.
87*7c478bd9Sstevel@tonic-gate  *
88*7c478bd9Sstevel@tonic-gate  * Pass 4 of cpuid analysis is invoked after post_startup() when all
89*7c478bd9Sstevel@tonic-gate  * the support infrastructure for various hardware features has been
90*7c478bd9Sstevel@tonic-gate  * initialized. It determines which processor features will be reported
91*7c478bd9Sstevel@tonic-gate  * to userland via the aux vector.
92*7c478bd9Sstevel@tonic-gate  *
93*7c478bd9Sstevel@tonic-gate  * All passes are executed on all CPUs, but only the boot CPU determines what
94*7c478bd9Sstevel@tonic-gate  * features the kernel will use.
95*7c478bd9Sstevel@tonic-gate  *
96*7c478bd9Sstevel@tonic-gate  * Much of the worst junk in this file is for the support of processors
97*7c478bd9Sstevel@tonic-gate  * that didn't really implement the cpuid instruction properly.
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  * NOTE: The accessor functions (cpuid_get*) are aware of, and ASSERT upon,
100*7c478bd9Sstevel@tonic-gate  * the pass numbers.  Accordingly, changes to the pass code may require changes
101*7c478bd9Sstevel@tonic-gate  * to the accessor code.
102*7c478bd9Sstevel@tonic-gate  */
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate uint_t x86_feature = 0;
105*7c478bd9Sstevel@tonic-gate uint_t x86_vendor = X86_VENDOR_IntelClone;
106*7c478bd9Sstevel@tonic-gate uint_t x86_type = X86_TYPE_OTHER;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate ulong_t cr4_value;
109*7c478bd9Sstevel@tonic-gate uint_t pentiumpro_bug4046376;
110*7c478bd9Sstevel@tonic-gate uint_t pentiumpro_bug4064495;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate uint_t enable486;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * This set of strings are for processors rumored to support the cpuid
116*7c478bd9Sstevel@tonic-gate  * instruction, and is used by locore.s to figure out how to set x86_vendor
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate const char CyrixInstead[] = "CyrixInstead";
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate struct cpuidr {
121*7c478bd9Sstevel@tonic-gate 	uint32_t	cp_eax;
122*7c478bd9Sstevel@tonic-gate 	uint32_t	cp_ebx;
123*7c478bd9Sstevel@tonic-gate 	uint32_t	cp_ecx;
124*7c478bd9Sstevel@tonic-gate 	uint32_t	cp_edx;
125*7c478bd9Sstevel@tonic-gate };
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate /*
128*7c478bd9Sstevel@tonic-gate  * These constants determine how many of the elements of the
129*7c478bd9Sstevel@tonic-gate  * cpuid we cache in the cpuid_info data structure; the
130*7c478bd9Sstevel@tonic-gate  * remaining elements are accessible via the cpuid instruction.
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate #define	NMAX_CPI_STD	6		/* eax = 0 .. 5 */
134*7c478bd9Sstevel@tonic-gate #define	NMAX_CPI_EXTD	9		/* eax = 0x80000000 .. 0x80000008 */
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate struct cpuid_info {
137*7c478bd9Sstevel@tonic-gate 	uint_t cpi_pass;		/* last pass completed */
138*7c478bd9Sstevel@tonic-gate 	/*
139*7c478bd9Sstevel@tonic-gate 	 * standard function information
140*7c478bd9Sstevel@tonic-gate 	 */
141*7c478bd9Sstevel@tonic-gate 	uint_t cpi_maxeax;		/* fn 0: %eax */
142*7c478bd9Sstevel@tonic-gate 	char cpi_vendorstr[13];		/* fn 0: %ebx:%ecx:%edx */
143*7c478bd9Sstevel@tonic-gate 	uint_t cpi_vendor;		/* enum of cpi_vendorstr */
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	uint_t cpi_family;		/* fn 1: extended family */
146*7c478bd9Sstevel@tonic-gate 	uint_t cpi_model;		/* fn 1: extended model */
147*7c478bd9Sstevel@tonic-gate 	uint_t cpi_step;		/* fn 1: stepping */
148*7c478bd9Sstevel@tonic-gate 	chipid_t cpi_chipid;		/* fn 1: %ebx: chip # on ht cpus */
149*7c478bd9Sstevel@tonic-gate 	uint_t cpi_brandid;		/* fn 1: %ebx: brand ID */
150*7c478bd9Sstevel@tonic-gate 	int cpi_clogid;			/* fn 1: %ebx: thread # */
151*7c478bd9Sstevel@tonic-gate 	uint_t cpi_ncpu_per_chip;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	uint8_t cpi_cacheinfo[16];	/* fn 2: intel-style cache desc */
154*7c478bd9Sstevel@tonic-gate 	uint_t cpi_ncache;		/* fn 2: number of elements */
155*7c478bd9Sstevel@tonic-gate 	struct cpuidr cpi_std[NMAX_CPI_STD];	/* 0 .. 5 */
156*7c478bd9Sstevel@tonic-gate 	/*
157*7c478bd9Sstevel@tonic-gate 	 * extended function information
158*7c478bd9Sstevel@tonic-gate 	 */
159*7c478bd9Sstevel@tonic-gate 	uint_t cpi_xmaxeax;		/* fn 0x80000000: %eax */
160*7c478bd9Sstevel@tonic-gate 	char cpi_brandstr[49];		/* fn 0x8000000[234] */
161*7c478bd9Sstevel@tonic-gate 	uint8_t cpi_pabits;		/* fn 0x80000006: %eax */
162*7c478bd9Sstevel@tonic-gate 	uint8_t cpi_vabits;		/* fn 0x80000006: %eax */
163*7c478bd9Sstevel@tonic-gate 	struct cpuidr cpi_extd[NMAX_CPI_EXTD];	/* 0x80000000 .. 0x80000008 */
164*7c478bd9Sstevel@tonic-gate 	/*
165*7c478bd9Sstevel@tonic-gate 	 * supported feature information
166*7c478bd9Sstevel@tonic-gate 	 */
167*7c478bd9Sstevel@tonic-gate 	uint32_t cpi_support[4];
168*7c478bd9Sstevel@tonic-gate #define	STD_EDX_FEATURES	0
169*7c478bd9Sstevel@tonic-gate #define	AMD_EDX_FEATURES	1
170*7c478bd9Sstevel@tonic-gate #define	TM_EDX_FEATURES		2
171*7c478bd9Sstevel@tonic-gate #define	STD_ECX_FEATURES	3
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate };
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate static struct cpuid_info cpuid_info0;
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate  * These bit fields are defined by the Intel Application Note AP-485
180*7c478bd9Sstevel@tonic-gate  * "Intel Processor Identification and the CPUID Instruction"
181*7c478bd9Sstevel@tonic-gate  */
182*7c478bd9Sstevel@tonic-gate #define	CPI_FAMILY_XTD(cpi)	BITX((cpi)->cpi_std[1].cp_eax, 27, 20)
183*7c478bd9Sstevel@tonic-gate #define	CPI_MODEL_XTD(cpi)	BITX((cpi)->cpi_std[1].cp_eax, 19, 16)
184*7c478bd9Sstevel@tonic-gate #define	CPI_TYPE(cpi)		BITX((cpi)->cpi_std[1].cp_eax, 13, 12)
185*7c478bd9Sstevel@tonic-gate #define	CPI_FAMILY(cpi)		BITX((cpi)->cpi_std[1].cp_eax, 11, 8)
186*7c478bd9Sstevel@tonic-gate #define	CPI_STEP(cpi)		BITX((cpi)->cpi_std[1].cp_eax, 3, 0)
187*7c478bd9Sstevel@tonic-gate #define	CPI_MODEL(cpi)		BITX((cpi)->cpi_std[1].cp_eax, 7, 4)
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate #define	CPI_FEATURES_EDX(cpi)		((cpi)->cpi_std[1].cp_edx)
190*7c478bd9Sstevel@tonic-gate #define	CPI_FEATURES_ECX(cpi)		((cpi)->cpi_std[1].cp_ecx)
191*7c478bd9Sstevel@tonic-gate #define	CPI_FEATURES_XTD_EDX(cpi)	((cpi)->cpi_extd[1].cp_edx)
192*7c478bd9Sstevel@tonic-gate #define	CPI_FEATURES_XTD_ECX(cpi)	((cpi)->cpi_extd[1].cp_ecx)
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate #define	CPI_BRANDID(cpi)	BITX((cpi)->cpi_std[1].cp_ebx, 7, 0)
195*7c478bd9Sstevel@tonic-gate #define	CPI_CHUNKS(cpi)		BITX((cpi)->cpi_std[1].cp_ebx, 15, 7)
196*7c478bd9Sstevel@tonic-gate #define	CPI_CPU_COUNT(cpi)	BITX((cpi)->cpi_std[1].cp_ebx, 23, 16)
197*7c478bd9Sstevel@tonic-gate #define	CPI_APIC_ID(cpi)	BITX((cpi)->cpi_std[1].cp_ebx, 31, 24)
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate #define	CPI_MAXEAX_MAX		0x100		/* sanity control */
200*7c478bd9Sstevel@tonic-gate #define	CPI_XMAXEAX_MAX		0x80000100
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate /*
203*7c478bd9Sstevel@tonic-gate  *  Some undocumented ways of patching the results of the cpuid
204*7c478bd9Sstevel@tonic-gate  *  instruction to permit running Solaris 10 on future cpus that
205*7c478bd9Sstevel@tonic-gate  *  we don't currently support.  Could be set to non-zero values
206*7c478bd9Sstevel@tonic-gate  *  via settings in eeprom.
207*7c478bd9Sstevel@tonic-gate  */
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate uint32_t cpuid_feature_ecx_include;
210*7c478bd9Sstevel@tonic-gate uint32_t cpuid_feature_ecx_exclude;
211*7c478bd9Sstevel@tonic-gate uint32_t cpuid_feature_edx_include;
212*7c478bd9Sstevel@tonic-gate uint32_t cpuid_feature_edx_exclude;
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate uint_t
215*7c478bd9Sstevel@tonic-gate cpuid_pass1(cpu_t *cpu)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	uint32_t mask_ecx, mask_edx;
218*7c478bd9Sstevel@tonic-gate 	uint_t feature = X86_CPUID;
219*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi;
220*7c478bd9Sstevel@tonic-gate 	struct cpuidr *cp;
221*7c478bd9Sstevel@tonic-gate 	int xcpuid;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	/*
224*7c478bd9Sstevel@tonic-gate 	 * By convention, cpu0 is the boot cpu, which is called
225*7c478bd9Sstevel@tonic-gate 	 * before memory allocation is available.  Other cpus are
226*7c478bd9Sstevel@tonic-gate 	 * initialized when memory becomes available.
227*7c478bd9Sstevel@tonic-gate 	 */
228*7c478bd9Sstevel@tonic-gate 	if (cpu->cpu_id == 0)
229*7c478bd9Sstevel@tonic-gate 		cpu->cpu_m.mcpu_cpi = cpi = &cpuid_info0;
230*7c478bd9Sstevel@tonic-gate 	else
231*7c478bd9Sstevel@tonic-gate 		cpu->cpu_m.mcpu_cpi = cpi =
232*7c478bd9Sstevel@tonic-gate 		    kmem_zalloc(sizeof (*cpi), KM_SLEEP);
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	cp = &cpi->cpi_std[0];
235*7c478bd9Sstevel@tonic-gate 	cp->cp_eax = __cpuid_insn(0, &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
236*7c478bd9Sstevel@tonic-gate 	cpi->cpi_maxeax = cp->cp_eax;
237*7c478bd9Sstevel@tonic-gate 	{
238*7c478bd9Sstevel@tonic-gate 		uint32_t *iptr = (uint32_t *)cpi->cpi_vendorstr;
239*7c478bd9Sstevel@tonic-gate 		*iptr++ = cp->cp_ebx;
240*7c478bd9Sstevel@tonic-gate 		*iptr++ = cp->cp_edx;
241*7c478bd9Sstevel@tonic-gate 		*iptr++ = cp->cp_ecx;
242*7c478bd9Sstevel@tonic-gate 		*(char *)&cpi->cpi_vendorstr[12] = '\0';
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	/*
246*7c478bd9Sstevel@tonic-gate 	 * Map the vendor string to a type code
247*7c478bd9Sstevel@tonic-gate 	 */
248*7c478bd9Sstevel@tonic-gate 	if (strcmp(cpi->cpi_vendorstr, "GenuineIntel") == 0)
249*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_Intel;
250*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "AuthenticAMD") == 0)
251*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_AMD;
252*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "GenuineTMx86") == 0)
253*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_TM;
254*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, CyrixInstead) == 0)
255*7c478bd9Sstevel@tonic-gate 		/*
256*7c478bd9Sstevel@tonic-gate 		 * CyrixInstead is a variable used by the Cyrix detection code
257*7c478bd9Sstevel@tonic-gate 		 * in locore.
258*7c478bd9Sstevel@tonic-gate 		 */
259*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_Cyrix;
260*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "UMC UMC UMC ") == 0)
261*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_UMC;
262*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "NexGenDriven") == 0)
263*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_NexGen;
264*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "CentaurHauls") == 0)
265*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_Centaur;
266*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "RiseRiseRise") == 0)
267*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_Rise;
268*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "SiS SiS SiS ") == 0)
269*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_SiS;
270*7c478bd9Sstevel@tonic-gate 	else if (strcmp(cpi->cpi_vendorstr, "Geode by NSC") == 0)
271*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_NSC;
272*7c478bd9Sstevel@tonic-gate 	else
273*7c478bd9Sstevel@tonic-gate 		cpi->cpi_vendor = X86_VENDOR_IntelClone;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	x86_vendor = cpi->cpi_vendor; /* for compatibility */
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/*
278*7c478bd9Sstevel@tonic-gate 	 * Limit the range in case of weird hardware
279*7c478bd9Sstevel@tonic-gate 	 */
280*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_maxeax > CPI_MAXEAX_MAX)
281*7c478bd9Sstevel@tonic-gate 		cpi->cpi_maxeax = CPI_MAXEAX_MAX;
282*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_maxeax < 1)
283*7c478bd9Sstevel@tonic-gate 		goto pass1_done;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	cp = &cpi->cpi_std[1];
286*7c478bd9Sstevel@tonic-gate 	cp->cp_eax = __cpuid_insn(1, &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	/*
289*7c478bd9Sstevel@tonic-gate 	 * Extract identifying constants for easy access.
290*7c478bd9Sstevel@tonic-gate 	 */
291*7c478bd9Sstevel@tonic-gate 	cpi->cpi_model = CPI_MODEL(cpi);
292*7c478bd9Sstevel@tonic-gate 	cpi->cpi_family = CPI_FAMILY(cpi);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_family == 0xf) {
295*7c478bd9Sstevel@tonic-gate 		cpi->cpi_family += CPI_FAMILY_XTD(cpi);
296*7c478bd9Sstevel@tonic-gate 		cpi->cpi_model += CPI_MODEL_XTD(cpi) << 4;
297*7c478bd9Sstevel@tonic-gate 	}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	cpi->cpi_step = CPI_STEP(cpi);
300*7c478bd9Sstevel@tonic-gate 	cpi->cpi_brandid = CPI_BRANDID(cpi);
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	/*
303*7c478bd9Sstevel@tonic-gate 	 * *default* assumptions:
304*7c478bd9Sstevel@tonic-gate 	 * - believe %edx feature word
305*7c478bd9Sstevel@tonic-gate 	 * - ignore %ecx feature word
306*7c478bd9Sstevel@tonic-gate 	 * - 32-bit virtual and physical addressing
307*7c478bd9Sstevel@tonic-gate 	 */
308*7c478bd9Sstevel@tonic-gate 	mask_edx = 0xffffffff;
309*7c478bd9Sstevel@tonic-gate 	mask_ecx = 0;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	cpi->cpi_pabits = cpi->cpi_vabits = 32;
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
314*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
315*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5)
316*7c478bd9Sstevel@tonic-gate 			x86_type = X86_TYPE_P5;
317*7c478bd9Sstevel@tonic-gate 		else if (cpi->cpi_family == 6) {
318*7c478bd9Sstevel@tonic-gate 			x86_type = X86_TYPE_P6;
319*7c478bd9Sstevel@tonic-gate 			pentiumpro_bug4046376 = 1;
320*7c478bd9Sstevel@tonic-gate 			pentiumpro_bug4064495 = 1;
321*7c478bd9Sstevel@tonic-gate 			/*
322*7c478bd9Sstevel@tonic-gate 			 * Clear the SEP bit when it was set erroneously
323*7c478bd9Sstevel@tonic-gate 			 */
324*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_model < 3 && cpi->cpi_step < 3)
325*7c478bd9Sstevel@tonic-gate 				cp->cp_edx &= ~CPUID_INTC_EDX_SEP;
326*7c478bd9Sstevel@tonic-gate 		} else if (cpi->cpi_family == 0xf) {
327*7c478bd9Sstevel@tonic-gate 			x86_type = X86_TYPE_P4;
328*7c478bd9Sstevel@tonic-gate 			/*
329*7c478bd9Sstevel@tonic-gate 			 * We don't currently depend on any of the %ecx
330*7c478bd9Sstevel@tonic-gate 			 * features until Prescott, so we'll only check
331*7c478bd9Sstevel@tonic-gate 			 * this from P4 onwards.  We might want to revisit
332*7c478bd9Sstevel@tonic-gate 			 * that idea later.
333*7c478bd9Sstevel@tonic-gate 			 */
334*7c478bd9Sstevel@tonic-gate 			mask_ecx = 0xffffffff;
335*7c478bd9Sstevel@tonic-gate 		} else if (cpi->cpi_family > 0xf)
336*7c478bd9Sstevel@tonic-gate 			mask_ecx = 0xffffffff;
337*7c478bd9Sstevel@tonic-gate 		break;
338*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_IntelClone:
339*7c478bd9Sstevel@tonic-gate 	default:
340*7c478bd9Sstevel@tonic-gate 		break;
341*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
342*7c478bd9Sstevel@tonic-gate #if defined(OPTERON_ERRATUM_108)
343*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 0xf && cpi->cpi_model == 0xe) {
344*7c478bd9Sstevel@tonic-gate 			cp->cp_eax = (0xf0f & cp->cp_eax) | 0xc0;
345*7c478bd9Sstevel@tonic-gate 			cpi->cpi_model = 0xc;
346*7c478bd9Sstevel@tonic-gate 		} else
347*7c478bd9Sstevel@tonic-gate #endif
348*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5) {
349*7c478bd9Sstevel@tonic-gate 			/*
350*7c478bd9Sstevel@tonic-gate 			 * AMD K5 and K6
351*7c478bd9Sstevel@tonic-gate 			 *
352*7c478bd9Sstevel@tonic-gate 			 * These CPUs have an incomplete implementation
353*7c478bd9Sstevel@tonic-gate 			 * of MCA/MCE which we mask away.
354*7c478bd9Sstevel@tonic-gate 			 */
355*7c478bd9Sstevel@tonic-gate 			mask_edx =
356*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_DE |
357*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_PSE |
358*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_TSC |
359*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MSR |
360*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CX8 |
361*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_PGE;
362*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_model == 0) {
363*7c478bd9Sstevel@tonic-gate 				/*
364*7c478bd9Sstevel@tonic-gate 				 * Model 0 uses the wrong (APIC) bit
365*7c478bd9Sstevel@tonic-gate 				 * to indicate PGE.  Fix it here.
366*7c478bd9Sstevel@tonic-gate 				 */
367*7c478bd9Sstevel@tonic-gate 				if (cp->cp_edx & 0x200) {
368*7c478bd9Sstevel@tonic-gate 					cp->cp_edx &= ~0x200;
369*7c478bd9Sstevel@tonic-gate 					cp->cp_edx |= CPUID_INTC_EDX_PGE;
370*7c478bd9Sstevel@tonic-gate 				}
371*7c478bd9Sstevel@tonic-gate 			} else if (cpi->cpi_model >= 6)
372*7c478bd9Sstevel@tonic-gate 				mask_edx |= CPUID_INTC_EDX_MMX;
373*7c478bd9Sstevel@tonic-gate 		}
374*7c478bd9Sstevel@tonic-gate 		break;
375*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
376*7c478bd9Sstevel@tonic-gate 		/*
377*7c478bd9Sstevel@tonic-gate 		 * workaround the NT workaround in CMS 4.1
378*7c478bd9Sstevel@tonic-gate 		 */
379*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5 && cpi->cpi_model == 4 &&
380*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_step == 2 || cpi->cpi_step == 3))
381*7c478bd9Sstevel@tonic-gate 			cp->cp_edx |= CPUID_INTC_EDX_CX8;
382*7c478bd9Sstevel@tonic-gate 		break;
383*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Centaur:
384*7c478bd9Sstevel@tonic-gate 		/*
385*7c478bd9Sstevel@tonic-gate 		 * workaround the NT workarounds again
386*7c478bd9Sstevel@tonic-gate 		 */
387*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 6)
388*7c478bd9Sstevel@tonic-gate 			cp->cp_edx |= CPUID_INTC_EDX_CX8;
389*7c478bd9Sstevel@tonic-gate 		break;
390*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
391*7c478bd9Sstevel@tonic-gate 		/*
392*7c478bd9Sstevel@tonic-gate 		 * We rely heavily on the probing in locore
393*7c478bd9Sstevel@tonic-gate 		 * to actually figure out what parts, if any,
394*7c478bd9Sstevel@tonic-gate 		 * of the Cyrix cpuid instruction to believe.
395*7c478bd9Sstevel@tonic-gate 		 */
396*7c478bd9Sstevel@tonic-gate 		switch (x86_type) {
397*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_486:
398*7c478bd9Sstevel@tonic-gate 			mask_edx = 0;
399*7c478bd9Sstevel@tonic-gate 			break;
400*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_6x86:
401*7c478bd9Sstevel@tonic-gate 			mask_edx = 0;
402*7c478bd9Sstevel@tonic-gate 			break;
403*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_6x86L:
404*7c478bd9Sstevel@tonic-gate 			mask_edx =
405*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_DE |
406*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CX8;
407*7c478bd9Sstevel@tonic-gate 			break;
408*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_6x86MX:
409*7c478bd9Sstevel@tonic-gate 			mask_edx =
410*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_DE |
411*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MSR |
412*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CX8 |
413*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_PGE |
414*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CMOV |
415*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MMX;
416*7c478bd9Sstevel@tonic-gate 			break;
417*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_GXm:
418*7c478bd9Sstevel@tonic-gate 			mask_edx =
419*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MSR |
420*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CX8 |
421*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CMOV |
422*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MMX;
423*7c478bd9Sstevel@tonic-gate 			break;
424*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_MediaGX:
425*7c478bd9Sstevel@tonic-gate 			break;
426*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_CYRIX_MII:
427*7c478bd9Sstevel@tonic-gate 		case X86_TYPE_VIA_CYRIX_III:
428*7c478bd9Sstevel@tonic-gate 			mask_edx =
429*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_DE |
430*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_TSC |
431*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MSR |
432*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CX8 |
433*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_PGE |
434*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_CMOV |
435*7c478bd9Sstevel@tonic-gate 			    CPUID_INTC_EDX_MMX;
436*7c478bd9Sstevel@tonic-gate 			break;
437*7c478bd9Sstevel@tonic-gate 		default:
438*7c478bd9Sstevel@tonic-gate 			break;
439*7c478bd9Sstevel@tonic-gate 		}
440*7c478bd9Sstevel@tonic-gate 		break;
441*7c478bd9Sstevel@tonic-gate 	}
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	/*
444*7c478bd9Sstevel@tonic-gate 	 * Now we've figured out the masks that determine
445*7c478bd9Sstevel@tonic-gate 	 * which bits we choose to believe, apply the masks
446*7c478bd9Sstevel@tonic-gate 	 * to the feature words, then map the kernel's view
447*7c478bd9Sstevel@tonic-gate 	 * of these feature words into its feature word.
448*7c478bd9Sstevel@tonic-gate 	 */
449*7c478bd9Sstevel@tonic-gate 	cp->cp_edx &= mask_edx;
450*7c478bd9Sstevel@tonic-gate 	cp->cp_ecx &= mask_ecx;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	/*
453*7c478bd9Sstevel@tonic-gate 	 * fold in fix ups
454*7c478bd9Sstevel@tonic-gate 	 */
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	cp->cp_edx |= cpuid_feature_edx_include;
457*7c478bd9Sstevel@tonic-gate 	cp->cp_edx &= ~cpuid_feature_edx_exclude;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	cp->cp_ecx |= cpuid_feature_ecx_include;
461*7c478bd9Sstevel@tonic-gate 	cp->cp_ecx &= ~cpuid_feature_ecx_exclude;
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_PSE)
464*7c478bd9Sstevel@tonic-gate 		feature |= X86_LARGEPAGE;
465*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_TSC)
466*7c478bd9Sstevel@tonic-gate 		feature |= X86_TSC;
467*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_MSR)
468*7c478bd9Sstevel@tonic-gate 		feature |= X86_MSR;
469*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_MTRR)
470*7c478bd9Sstevel@tonic-gate 		feature |= X86_MTRR;
471*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_PGE)
472*7c478bd9Sstevel@tonic-gate 		feature |= X86_PGE;
473*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_CMOV)
474*7c478bd9Sstevel@tonic-gate 		feature |= X86_CMOV;
475*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_MMX)
476*7c478bd9Sstevel@tonic-gate 		feature |= X86_MMX;
477*7c478bd9Sstevel@tonic-gate 	if ((cp->cp_edx & CPUID_INTC_EDX_MCE) != 0 &&
478*7c478bd9Sstevel@tonic-gate 	    (cp->cp_edx & CPUID_INTC_EDX_MCA) != 0)
479*7c478bd9Sstevel@tonic-gate 		feature |= X86_MCA;
480*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_PAE)
481*7c478bd9Sstevel@tonic-gate 		feature |= X86_PAE;
482*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_CX8)
483*7c478bd9Sstevel@tonic-gate 		feature |= X86_CX8;
484*7c478bd9Sstevel@tonic-gate #if defined(CPUID_INTC_ECX_CX16)
485*7c478bd9Sstevel@tonic-gate 	/*
486*7c478bd9Sstevel@tonic-gate 	 * In the July 16 2004 edition of AN 485, Intel rescinded
487*7c478bd9Sstevel@tonic-gate 	 * the definition of this bit -- it's now in the "Do not count on
488*7c478bd9Sstevel@tonic-gate 	 * their value" category.
489*7c478bd9Sstevel@tonic-gate 	 */
490*7c478bd9Sstevel@tonic-gate 	if (cp->cp_ecx & CPUID_INTC_ECX_CX16)
491*7c478bd9Sstevel@tonic-gate 		feature |= X86_CX16;
492*7c478bd9Sstevel@tonic-gate #endif
493*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_PAT)
494*7c478bd9Sstevel@tonic-gate 		feature |= X86_PAT;
495*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_SEP)
496*7c478bd9Sstevel@tonic-gate 		feature |= X86_SEP;
497*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_FXSR) {
498*7c478bd9Sstevel@tonic-gate 		/*
499*7c478bd9Sstevel@tonic-gate 		 * In our implementation, fxsave/fxrstor
500*7c478bd9Sstevel@tonic-gate 		 * are prerequisites before we'll even
501*7c478bd9Sstevel@tonic-gate 		 * try and do SSE things.
502*7c478bd9Sstevel@tonic-gate 		 */
503*7c478bd9Sstevel@tonic-gate 		if (cp->cp_edx & CPUID_INTC_EDX_SSE)
504*7c478bd9Sstevel@tonic-gate 			feature |= X86_SSE;
505*7c478bd9Sstevel@tonic-gate 		if (cp->cp_edx & CPUID_INTC_EDX_SSE2)
506*7c478bd9Sstevel@tonic-gate 			feature |= X86_SSE2;
507*7c478bd9Sstevel@tonic-gate 		if (cp->cp_ecx & CPUID_INTC_ECX_SSE3)
508*7c478bd9Sstevel@tonic-gate 			feature |= X86_SSE3;
509*7c478bd9Sstevel@tonic-gate 	}
510*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_DE)
511*7c478bd9Sstevel@tonic-gate 		cr4_value |= CR4_DE;
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	if (feature & X86_PAE)
514*7c478bd9Sstevel@tonic-gate 		cpi->cpi_pabits = 36;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	/*
517*7c478bd9Sstevel@tonic-gate 	 * Hyperthreading configuration is slightly tricky on Intel
518*7c478bd9Sstevel@tonic-gate 	 * and pure clones, and even trickier on AMD.
519*7c478bd9Sstevel@tonic-gate 	 *
520*7c478bd9Sstevel@tonic-gate 	 * (AMD chose to set the HTT bit on their CMP processors,
521*7c478bd9Sstevel@tonic-gate 	 * even though they're not actually hyperthreaded.  Thus it
522*7c478bd9Sstevel@tonic-gate 	 * takes a bit more work to figure out what's really going
523*7c478bd9Sstevel@tonic-gate 	 * on ... see the handling of the HTvalid bit below)
524*7c478bd9Sstevel@tonic-gate 	 */
525*7c478bd9Sstevel@tonic-gate 	if (cp->cp_edx & CPUID_INTC_EDX_HTT) {
526*7c478bd9Sstevel@tonic-gate 		cpi->cpi_ncpu_per_chip = CPI_CPU_COUNT(cpi);
527*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_ncpu_per_chip > 1)
528*7c478bd9Sstevel@tonic-gate 			feature |= X86_HTT;
529*7c478bd9Sstevel@tonic-gate 	}
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	/*
532*7c478bd9Sstevel@tonic-gate 	 * Work on the "extended" feature information, doing
533*7c478bd9Sstevel@tonic-gate 	 * some basic initialization for cpuid_pass2()
534*7c478bd9Sstevel@tonic-gate 	 */
535*7c478bd9Sstevel@tonic-gate 	xcpuid = 0;
536*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
537*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
538*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family >= 0xf)
539*7c478bd9Sstevel@tonic-gate 			xcpuid++;
540*7c478bd9Sstevel@tonic-gate 		break;
541*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
542*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family > 5 ||
543*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_family == 5 && cpi->cpi_model >= 1))
544*7c478bd9Sstevel@tonic-gate 			xcpuid++;
545*7c478bd9Sstevel@tonic-gate 		break;
546*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
547*7c478bd9Sstevel@tonic-gate 		/*
548*7c478bd9Sstevel@tonic-gate 		 * Only these Cyrix CPUs are -known- to support
549*7c478bd9Sstevel@tonic-gate 		 * extended cpuid operations.
550*7c478bd9Sstevel@tonic-gate 		 */
551*7c478bd9Sstevel@tonic-gate 		if (x86_type == X86_TYPE_VIA_CYRIX_III ||
552*7c478bd9Sstevel@tonic-gate 		    x86_type == X86_TYPE_CYRIX_GXm)
553*7c478bd9Sstevel@tonic-gate 			xcpuid++;
554*7c478bd9Sstevel@tonic-gate 		break;
555*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Centaur:
556*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
557*7c478bd9Sstevel@tonic-gate 	default:
558*7c478bd9Sstevel@tonic-gate 		xcpuid++;
559*7c478bd9Sstevel@tonic-gate 		break;
560*7c478bd9Sstevel@tonic-gate 	}
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 	if (xcpuid) {
563*7c478bd9Sstevel@tonic-gate 		cp = &cpi->cpi_extd[0];
564*7c478bd9Sstevel@tonic-gate 		cpi->cpi_xmaxeax = cp->cp_eax = __cpuid_insn(0x80000000,
565*7c478bd9Sstevel@tonic-gate 		    &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
566*7c478bd9Sstevel@tonic-gate 	}
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax & 0x80000000) {
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_xmaxeax > CPI_XMAXEAX_MAX)
571*7c478bd9Sstevel@tonic-gate 			cpi->cpi_xmaxeax = CPI_XMAXEAX_MAX;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 		switch (cpi->cpi_vendor) {
574*7c478bd9Sstevel@tonic-gate 		case X86_VENDOR_Intel:
575*7c478bd9Sstevel@tonic-gate 		case X86_VENDOR_AMD:
576*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_xmaxeax < 0x80000001)
577*7c478bd9Sstevel@tonic-gate 				break;
578*7c478bd9Sstevel@tonic-gate 			cp = &cpi->cpi_extd[1];
579*7c478bd9Sstevel@tonic-gate 			cp->cp_eax = __cpuid_insn(0x80000001,
580*7c478bd9Sstevel@tonic-gate 			    &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
581*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_vendor == X86_VENDOR_AMD &&
582*7c478bd9Sstevel@tonic-gate 			    cpi->cpi_family == 5 &&
583*7c478bd9Sstevel@tonic-gate 			    cpi->cpi_model == 6 &&
584*7c478bd9Sstevel@tonic-gate 			    cpi->cpi_step == 6) {
585*7c478bd9Sstevel@tonic-gate 				/*
586*7c478bd9Sstevel@tonic-gate 				 * K6 model 6 uses bit 10 to indicate SYSC
587*7c478bd9Sstevel@tonic-gate 				 * Later models use bit 11. Fix it here.
588*7c478bd9Sstevel@tonic-gate 				 */
589*7c478bd9Sstevel@tonic-gate 				if (cp->cp_edx & 0x400) {
590*7c478bd9Sstevel@tonic-gate 					cp->cp_edx &= ~0x400;
591*7c478bd9Sstevel@tonic-gate 					cp->cp_edx |= CPUID_AMD_EDX_SYSC;
592*7c478bd9Sstevel@tonic-gate 				}
593*7c478bd9Sstevel@tonic-gate 			}
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 			/*
596*7c478bd9Sstevel@tonic-gate 			 * Compute the additions to the kernel's feature word.
597*7c478bd9Sstevel@tonic-gate 			 */
598*7c478bd9Sstevel@tonic-gate 			if (cp->cp_edx & CPUID_AMD_EDX_NX)
599*7c478bd9Sstevel@tonic-gate 				feature |= X86_NX;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 			/*
602*7c478bd9Sstevel@tonic-gate 			 * Unless both the HTT bit is set, and the
603*7c478bd9Sstevel@tonic-gate 			 * HTvalid bit is set, then we're not actually
604*7c478bd9Sstevel@tonic-gate 			 * HyperThreaded at all..
605*7c478bd9Sstevel@tonic-gate 			 */
606*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_vendor == X86_VENDOR_AMD &&
607*7c478bd9Sstevel@tonic-gate 			    (feature & X86_HTT) == X86_HTT &&
608*7c478bd9Sstevel@tonic-gate 			    (cp->cp_ecx & CPUID_AMD_ECX_HTvalid) == 0)
609*7c478bd9Sstevel@tonic-gate 				feature &= ~X86_HTT;
610*7c478bd9Sstevel@tonic-gate #if defined(_LP64)
611*7c478bd9Sstevel@tonic-gate 			/*
612*7c478bd9Sstevel@tonic-gate 			 * It's really tricky to support syscall/sysret in
613*7c478bd9Sstevel@tonic-gate 			 * the i386 kernel; we rely on sysenter/sysexit
614*7c478bd9Sstevel@tonic-gate 			 * instead.  In the amd64 kernel, things are -way-
615*7c478bd9Sstevel@tonic-gate 			 * better.
616*7c478bd9Sstevel@tonic-gate 			 */
617*7c478bd9Sstevel@tonic-gate 			if (cp->cp_edx & CPUID_AMD_EDX_SYSC)
618*7c478bd9Sstevel@tonic-gate 				feature |= X86_ASYSC;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 			/*
621*7c478bd9Sstevel@tonic-gate 			 * While we're thinking about system calls, note
622*7c478bd9Sstevel@tonic-gate 			 * that AMD processors don't support sysenter
623*7c478bd9Sstevel@tonic-gate 			 * in long mode at all, so don't try to program them.
624*7c478bd9Sstevel@tonic-gate 			 */
625*7c478bd9Sstevel@tonic-gate 			if (x86_vendor == X86_VENDOR_AMD)
626*7c478bd9Sstevel@tonic-gate 				feature &= ~X86_SEP;
627*7c478bd9Sstevel@tonic-gate #endif
628*7c478bd9Sstevel@tonic-gate 			break;
629*7c478bd9Sstevel@tonic-gate 		default:
630*7c478bd9Sstevel@tonic-gate 			break;
631*7c478bd9Sstevel@tonic-gate 		}
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 		switch (cpi->cpi_vendor) {
634*7c478bd9Sstevel@tonic-gate 		case X86_VENDOR_Intel:
635*7c478bd9Sstevel@tonic-gate 		case X86_VENDOR_AMD:
636*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_xmaxeax < 0x80000008)
637*7c478bd9Sstevel@tonic-gate 				break;
638*7c478bd9Sstevel@tonic-gate 			cp = &cpi->cpi_extd[8];
639*7c478bd9Sstevel@tonic-gate 			cp->cp_eax = __cpuid_insn(0x80000008,
640*7c478bd9Sstevel@tonic-gate 			    &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
641*7c478bd9Sstevel@tonic-gate 			/*
642*7c478bd9Sstevel@tonic-gate 			 * Virtual and physical address limits from
643*7c478bd9Sstevel@tonic-gate 			 * cpuid override previously guessed values.
644*7c478bd9Sstevel@tonic-gate 			 */
645*7c478bd9Sstevel@tonic-gate 			cpi->cpi_pabits = BITX(cp->cp_eax, 7, 0);
646*7c478bd9Sstevel@tonic-gate 			cpi->cpi_vabits = BITX(cp->cp_eax, 15, 8);
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 			/*
649*7c478bd9Sstevel@tonic-gate 			 * This -might- be a CMP processor?
650*7c478bd9Sstevel@tonic-gate 			 */
651*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_vendor == X86_VENDOR_AMD) {
652*7c478bd9Sstevel@tonic-gate 				cpi->cpi_ncpu_per_chip =
653*7c478bd9Sstevel@tonic-gate 				    1 + BITX(cp->cp_ecx, 7, 0);
654*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_ncpu_per_chip > 1)
655*7c478bd9Sstevel@tonic-gate 					feature |= X86_CMP;
656*7c478bd9Sstevel@tonic-gate 			}
657*7c478bd9Sstevel@tonic-gate 			break;
658*7c478bd9Sstevel@tonic-gate 		default:
659*7c478bd9Sstevel@tonic-gate 			break;
660*7c478bd9Sstevel@tonic-gate 		}
661*7c478bd9Sstevel@tonic-gate 	}
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	if ((feature & (X86_HTT | X86_CMP)) == 0) {
664*7c478bd9Sstevel@tonic-gate 		cpi->cpi_chipid = -1;
665*7c478bd9Sstevel@tonic-gate 		cpi->cpi_clogid = 0;
666*7c478bd9Sstevel@tonic-gate 	} else if (cpi->cpi_ncpu_per_chip > 1) {
667*7c478bd9Sstevel@tonic-gate 		uint_t i, cid_shift, apic_id;
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 		for (i = 1, cid_shift = 0;
670*7c478bd9Sstevel@tonic-gate 		    i < cpi->cpi_ncpu_per_chip; i <<= 1)
671*7c478bd9Sstevel@tonic-gate 			cid_shift++;
672*7c478bd9Sstevel@tonic-gate 		apic_id = CPI_APIC_ID(cpi);
673*7c478bd9Sstevel@tonic-gate 		cpi->cpi_chipid = apic_id >> cid_shift;
674*7c478bd9Sstevel@tonic-gate 		cpi->cpi_clogid = apic_id & ((1 << cid_shift) - 1);
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate pass1_done:
678*7c478bd9Sstevel@tonic-gate 	cpi->cpi_pass = 1;
679*7c478bd9Sstevel@tonic-gate 	return (feature);
680*7c478bd9Sstevel@tonic-gate }
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate /*
683*7c478bd9Sstevel@tonic-gate  * Make copies of the cpuid table entries we depend on, in
684*7c478bd9Sstevel@tonic-gate  * part for ease of parsing now, in part so that we have only
685*7c478bd9Sstevel@tonic-gate  * one place to correct any of it, in part for ease of
686*7c478bd9Sstevel@tonic-gate  * later export to userland, and in part so we can look at
687*7c478bd9Sstevel@tonic-gate  * this stuff in a crash dump.
688*7c478bd9Sstevel@tonic-gate  */
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
691*7c478bd9Sstevel@tonic-gate void
692*7c478bd9Sstevel@tonic-gate cpuid_pass2(cpu_t *cpu)
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate 	uint_t n, nmax;
695*7c478bd9Sstevel@tonic-gate 	int i;
696*7c478bd9Sstevel@tonic-gate 	struct cpuidr *cp;
697*7c478bd9Sstevel@tonic-gate 	uint8_t *dp;
698*7c478bd9Sstevel@tonic-gate 	uint32_t *iptr;
699*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	ASSERT(cpi->cpi_pass == 1);
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_maxeax < 1)
704*7c478bd9Sstevel@tonic-gate 		goto pass2_done;
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	if ((nmax = cpi->cpi_maxeax + 1) > NMAX_CPI_STD)
707*7c478bd9Sstevel@tonic-gate 		nmax = NMAX_CPI_STD;
708*7c478bd9Sstevel@tonic-gate 	/*
709*7c478bd9Sstevel@tonic-gate 	 * (We already handled n == 0 and n == 1 in pass 1)
710*7c478bd9Sstevel@tonic-gate 	 */
711*7c478bd9Sstevel@tonic-gate 	for (n = 2, cp = &cpi->cpi_std[2]; n < nmax; n++, cp++) {
712*7c478bd9Sstevel@tonic-gate 		cp->cp_eax = __cpuid_insn(n,
713*7c478bd9Sstevel@tonic-gate 		    &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
714*7c478bd9Sstevel@tonic-gate 		switch (n) {
715*7c478bd9Sstevel@tonic-gate 		case 2:
716*7c478bd9Sstevel@tonic-gate 			/*
717*7c478bd9Sstevel@tonic-gate 			 * "the lower 8 bits of the %eax register
718*7c478bd9Sstevel@tonic-gate 			 * contain a value that identifies the number
719*7c478bd9Sstevel@tonic-gate 			 * of times the cpuid [instruction] has to be
720*7c478bd9Sstevel@tonic-gate 			 * executed to obtain a complete image of the
721*7c478bd9Sstevel@tonic-gate 			 * processor's caching systems."
722*7c478bd9Sstevel@tonic-gate 			 *
723*7c478bd9Sstevel@tonic-gate 			 * How *do* they make this stuff up?
724*7c478bd9Sstevel@tonic-gate 			 */
725*7c478bd9Sstevel@tonic-gate 			cpi->cpi_ncache = sizeof (*cp) *
726*7c478bd9Sstevel@tonic-gate 			    BITX(cp->cp_eax, 7, 0);
727*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_ncache == 0)
728*7c478bd9Sstevel@tonic-gate 				break;
729*7c478bd9Sstevel@tonic-gate 			cpi->cpi_ncache--;	/* skip count byte */
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 			/*
732*7c478bd9Sstevel@tonic-gate 			 * Well, for now, rather than attempt to implement
733*7c478bd9Sstevel@tonic-gate 			 * this slightly dubious algorithm, we just look
734*7c478bd9Sstevel@tonic-gate 			 * at the first 15 ..
735*7c478bd9Sstevel@tonic-gate 			 */
736*7c478bd9Sstevel@tonic-gate 			if (cpi->cpi_ncache > (sizeof (*cp) - 1))
737*7c478bd9Sstevel@tonic-gate 				cpi->cpi_ncache = sizeof (*cp) - 1;
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 			dp = cpi->cpi_cacheinfo;
740*7c478bd9Sstevel@tonic-gate 			if (BITX(cp->cp_eax, 31, 31) == 0) {
741*7c478bd9Sstevel@tonic-gate 				uint8_t *p = (void *)&cp->cp_eax;
742*7c478bd9Sstevel@tonic-gate 				for (i = 1; i < 3; i++)
743*7c478bd9Sstevel@tonic-gate 					if (p[i] != 0)
744*7c478bd9Sstevel@tonic-gate 						*dp++ = p[i];
745*7c478bd9Sstevel@tonic-gate 			}
746*7c478bd9Sstevel@tonic-gate 			if (BITX(cp->cp_ebx, 31, 31) == 0) {
747*7c478bd9Sstevel@tonic-gate 				uint8_t *p = (void *)&cp->cp_ebx;
748*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < 4; i++)
749*7c478bd9Sstevel@tonic-gate 					if (p[i] != 0)
750*7c478bd9Sstevel@tonic-gate 						*dp++ = p[i];
751*7c478bd9Sstevel@tonic-gate 			}
752*7c478bd9Sstevel@tonic-gate 			if (BITX(cp->cp_ecx, 31, 31) == 0) {
753*7c478bd9Sstevel@tonic-gate 				uint8_t *p = (void *)&cp->cp_ecx;
754*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < 4; i++)
755*7c478bd9Sstevel@tonic-gate 					if (p[i] != 0)
756*7c478bd9Sstevel@tonic-gate 						*dp++ = p[i];
757*7c478bd9Sstevel@tonic-gate 			}
758*7c478bd9Sstevel@tonic-gate 			if (BITX(cp->cp_edx, 31, 31) == 0) {
759*7c478bd9Sstevel@tonic-gate 				uint8_t *p = (void *)&cp->cp_edx;
760*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < 4; i++)
761*7c478bd9Sstevel@tonic-gate 					if (p[i] != 0)
762*7c478bd9Sstevel@tonic-gate 						*dp++ = p[i];
763*7c478bd9Sstevel@tonic-gate 			}
764*7c478bd9Sstevel@tonic-gate 			break;
765*7c478bd9Sstevel@tonic-gate 		case 3:	/* Processor serial number, if PSN supported */
766*7c478bd9Sstevel@tonic-gate 		case 4:	/* Deterministic cache parameters */
767*7c478bd9Sstevel@tonic-gate 		case 5:	/* Monitor/Mwait parameters */
768*7c478bd9Sstevel@tonic-gate 		default:
769*7c478bd9Sstevel@tonic-gate 			break;
770*7c478bd9Sstevel@tonic-gate 		}
771*7c478bd9Sstevel@tonic-gate 	}
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 	if ((cpi->cpi_xmaxeax & 0x80000000) == 0)
774*7c478bd9Sstevel@tonic-gate 		goto pass2_done;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	if ((nmax = cpi->cpi_xmaxeax - 0x80000000 + 1) > NMAX_CPI_EXTD)
777*7c478bd9Sstevel@tonic-gate 		nmax = NMAX_CPI_EXTD;
778*7c478bd9Sstevel@tonic-gate 	/*
779*7c478bd9Sstevel@tonic-gate 	 * Copy the extended properties, fixing them as we go.
780*7c478bd9Sstevel@tonic-gate 	 * (We already handled n == 0 and n == 1 in pass 1)
781*7c478bd9Sstevel@tonic-gate 	 */
782*7c478bd9Sstevel@tonic-gate 	iptr = (void *)cpi->cpi_brandstr;
783*7c478bd9Sstevel@tonic-gate 	for (n = 2, cp = &cpi->cpi_extd[2]; n < nmax; cp++, n++) {
784*7c478bd9Sstevel@tonic-gate 		cp->cp_eax = __cpuid_insn(n + 0x80000000,
785*7c478bd9Sstevel@tonic-gate 		    &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
786*7c478bd9Sstevel@tonic-gate 		switch (n) {
787*7c478bd9Sstevel@tonic-gate 		case 2:
788*7c478bd9Sstevel@tonic-gate 		case 3:
789*7c478bd9Sstevel@tonic-gate 		case 4:
790*7c478bd9Sstevel@tonic-gate 			/*
791*7c478bd9Sstevel@tonic-gate 			 * Extract the brand string
792*7c478bd9Sstevel@tonic-gate 			 */
793*7c478bd9Sstevel@tonic-gate 			*iptr++ = cp->cp_eax;
794*7c478bd9Sstevel@tonic-gate 			*iptr++ = cp->cp_ebx;
795*7c478bd9Sstevel@tonic-gate 			*iptr++ = cp->cp_ecx;
796*7c478bd9Sstevel@tonic-gate 			*iptr++ = cp->cp_edx;
797*7c478bd9Sstevel@tonic-gate 			break;
798*7c478bd9Sstevel@tonic-gate 		case 5:
799*7c478bd9Sstevel@tonic-gate 			switch (cpi->cpi_vendor) {
800*7c478bd9Sstevel@tonic-gate 			case X86_VENDOR_AMD:
801*7c478bd9Sstevel@tonic-gate 				/*
802*7c478bd9Sstevel@tonic-gate 				 * The Athlon and Duron were the first
803*7c478bd9Sstevel@tonic-gate 				 * parts to report the sizes of the
804*7c478bd9Sstevel@tonic-gate 				 * TLB for large pages. Before then,
805*7c478bd9Sstevel@tonic-gate 				 * we don't trust the data.
806*7c478bd9Sstevel@tonic-gate 				 */
807*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_family < 6 ||
808*7c478bd9Sstevel@tonic-gate 				    (cpi->cpi_family == 6 &&
809*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_model < 1))
810*7c478bd9Sstevel@tonic-gate 					cp->cp_eax = 0;
811*7c478bd9Sstevel@tonic-gate 				break;
812*7c478bd9Sstevel@tonic-gate 			default:
813*7c478bd9Sstevel@tonic-gate 				break;
814*7c478bd9Sstevel@tonic-gate 			}
815*7c478bd9Sstevel@tonic-gate 			break;
816*7c478bd9Sstevel@tonic-gate 		case 6:
817*7c478bd9Sstevel@tonic-gate 			switch (cpi->cpi_vendor) {
818*7c478bd9Sstevel@tonic-gate 			case X86_VENDOR_AMD:
819*7c478bd9Sstevel@tonic-gate 				/*
820*7c478bd9Sstevel@tonic-gate 				 * The Athlon and Duron were the first
821*7c478bd9Sstevel@tonic-gate 				 * AMD parts with L2 TLB's.
822*7c478bd9Sstevel@tonic-gate 				 * Before then, don't trust the data.
823*7c478bd9Sstevel@tonic-gate 				 */
824*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_family < 6 ||
825*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_family == 6 &&
826*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_model < 1)
827*7c478bd9Sstevel@tonic-gate 					cp->cp_eax = cp->cp_ebx = 0;
828*7c478bd9Sstevel@tonic-gate 				/*
829*7c478bd9Sstevel@tonic-gate 				 * AMD Duron rev A0 reports L2
830*7c478bd9Sstevel@tonic-gate 				 * cache size incorrectly as 1K
831*7c478bd9Sstevel@tonic-gate 				 * when it is really 64K
832*7c478bd9Sstevel@tonic-gate 				 */
833*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_family == 6 &&
834*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_model == 3 &&
835*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_step == 0) {
836*7c478bd9Sstevel@tonic-gate 					cp->cp_ecx &= 0xffff;
837*7c478bd9Sstevel@tonic-gate 					cp->cp_ecx |= 0x400000;
838*7c478bd9Sstevel@tonic-gate 				}
839*7c478bd9Sstevel@tonic-gate 				break;
840*7c478bd9Sstevel@tonic-gate 			case X86_VENDOR_Cyrix:	/* VIA C3 */
841*7c478bd9Sstevel@tonic-gate 				/*
842*7c478bd9Sstevel@tonic-gate 				 * VIA C3 processors are a bit messed
843*7c478bd9Sstevel@tonic-gate 				 * up w.r.t. encoding cache sizes in %ecx
844*7c478bd9Sstevel@tonic-gate 				 */
845*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_family != 6)
846*7c478bd9Sstevel@tonic-gate 					break;
847*7c478bd9Sstevel@tonic-gate 				/*
848*7c478bd9Sstevel@tonic-gate 				 * model 7 and 8 were incorrectly encoded
849*7c478bd9Sstevel@tonic-gate 				 *
850*7c478bd9Sstevel@tonic-gate 				 * xxx is model 8 really broken?
851*7c478bd9Sstevel@tonic-gate 				 */
852*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_model == 7 ||
853*7c478bd9Sstevel@tonic-gate 				    cpi->cpi_model == 8)
854*7c478bd9Sstevel@tonic-gate 					cp->cp_ecx =
855*7c478bd9Sstevel@tonic-gate 					    BITX(cp->cp_ecx, 31, 24) << 16 |
856*7c478bd9Sstevel@tonic-gate 					    BITX(cp->cp_ecx, 23, 16) << 12 |
857*7c478bd9Sstevel@tonic-gate 					    BITX(cp->cp_ecx, 15, 8) << 8 |
858*7c478bd9Sstevel@tonic-gate 					    BITX(cp->cp_ecx, 7, 0);
859*7c478bd9Sstevel@tonic-gate 				/*
860*7c478bd9Sstevel@tonic-gate 				 * model 9 stepping 1 has wrong associativity
861*7c478bd9Sstevel@tonic-gate 				 */
862*7c478bd9Sstevel@tonic-gate 				if (cpi->cpi_model == 9 && cpi->cpi_step == 1)
863*7c478bd9Sstevel@tonic-gate 					cp->cp_ecx |= 8 << 12;
864*7c478bd9Sstevel@tonic-gate 				break;
865*7c478bd9Sstevel@tonic-gate 			case X86_VENDOR_Intel:
866*7c478bd9Sstevel@tonic-gate 				/*
867*7c478bd9Sstevel@tonic-gate 				 * Extended L2 Cache features function.
868*7c478bd9Sstevel@tonic-gate 				 * First appeared on Prescott.
869*7c478bd9Sstevel@tonic-gate 				 */
870*7c478bd9Sstevel@tonic-gate 			default:
871*7c478bd9Sstevel@tonic-gate 				break;
872*7c478bd9Sstevel@tonic-gate 			}
873*7c478bd9Sstevel@tonic-gate 			break;
874*7c478bd9Sstevel@tonic-gate 		default:
875*7c478bd9Sstevel@tonic-gate 			break;
876*7c478bd9Sstevel@tonic-gate 		}
877*7c478bd9Sstevel@tonic-gate 	}
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate pass2_done:
880*7c478bd9Sstevel@tonic-gate 	cpi->cpi_pass = 2;
881*7c478bd9Sstevel@tonic-gate }
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate static const char *
884*7c478bd9Sstevel@tonic-gate intel_cpubrand(const struct cpuid_info *cpi)
885*7c478bd9Sstevel@tonic-gate {
886*7c478bd9Sstevel@tonic-gate 	int i;
887*7c478bd9Sstevel@tonic-gate 
888*7c478bd9Sstevel@tonic-gate 	if ((x86_feature & X86_CPUID) == 0 ||
889*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_maxeax < 1 || cpi->cpi_family < 5)
890*7c478bd9Sstevel@tonic-gate 		return ("i486");
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_family) {
893*7c478bd9Sstevel@tonic-gate 	case 5:
894*7c478bd9Sstevel@tonic-gate 		return ("Intel Pentium(r)");
895*7c478bd9Sstevel@tonic-gate 	case 6:
896*7c478bd9Sstevel@tonic-gate 		switch (cpi->cpi_model) {
897*7c478bd9Sstevel@tonic-gate 			uint_t celeron, xeon;
898*7c478bd9Sstevel@tonic-gate 			const struct cpuidr *cp;
899*7c478bd9Sstevel@tonic-gate 		case 0:
900*7c478bd9Sstevel@tonic-gate 		case 1:
901*7c478bd9Sstevel@tonic-gate 		case 2:
902*7c478bd9Sstevel@tonic-gate 			return ("Intel Pentium(r) Pro");
903*7c478bd9Sstevel@tonic-gate 		case 3:
904*7c478bd9Sstevel@tonic-gate 		case 4:
905*7c478bd9Sstevel@tonic-gate 			return ("Intel Pentium(r) II");
906*7c478bd9Sstevel@tonic-gate 		case 6:
907*7c478bd9Sstevel@tonic-gate 			return ("Intel Celeron(r)");
908*7c478bd9Sstevel@tonic-gate 		case 5:
909*7c478bd9Sstevel@tonic-gate 		case 7:
910*7c478bd9Sstevel@tonic-gate 			celeron = xeon = 0;
911*7c478bd9Sstevel@tonic-gate 			cp = &cpi->cpi_std[2];	/* cache info */
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 			for (i = 1; i < 3; i++) {
914*7c478bd9Sstevel@tonic-gate 				uint_t tmp;
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 				tmp = (cp->cp_eax >> (8 * i)) & 0xff;
917*7c478bd9Sstevel@tonic-gate 				if (tmp == 0x40)
918*7c478bd9Sstevel@tonic-gate 					celeron++;
919*7c478bd9Sstevel@tonic-gate 				if (tmp >= 0x44 && tmp <= 0x45)
920*7c478bd9Sstevel@tonic-gate 					xeon++;
921*7c478bd9Sstevel@tonic-gate 			}
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < 2; i++) {
924*7c478bd9Sstevel@tonic-gate 				uint_t tmp;
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 				tmp = (cp->cp_ebx >> (8 * i)) & 0xff;
927*7c478bd9Sstevel@tonic-gate 				if (tmp == 0x40)
928*7c478bd9Sstevel@tonic-gate 					celeron++;
929*7c478bd9Sstevel@tonic-gate 				else if (tmp >= 0x44 && tmp <= 0x45)
930*7c478bd9Sstevel@tonic-gate 					xeon++;
931*7c478bd9Sstevel@tonic-gate 			}
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < 4; i++) {
934*7c478bd9Sstevel@tonic-gate 				uint_t tmp;
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 				tmp = (cp->cp_ecx >> (8 * i)) & 0xff;
937*7c478bd9Sstevel@tonic-gate 				if (tmp == 0x40)
938*7c478bd9Sstevel@tonic-gate 					celeron++;
939*7c478bd9Sstevel@tonic-gate 				else if (tmp >= 0x44 && tmp <= 0x45)
940*7c478bd9Sstevel@tonic-gate 					xeon++;
941*7c478bd9Sstevel@tonic-gate 			}
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < 4; i++) {
944*7c478bd9Sstevel@tonic-gate 				uint_t tmp;
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 				tmp = (cp->cp_edx >> (8 * i)) & 0xff;
947*7c478bd9Sstevel@tonic-gate 				if (tmp == 0x40)
948*7c478bd9Sstevel@tonic-gate 					celeron++;
949*7c478bd9Sstevel@tonic-gate 				else if (tmp >= 0x44 && tmp <= 0x45)
950*7c478bd9Sstevel@tonic-gate 					xeon++;
951*7c478bd9Sstevel@tonic-gate 			}
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 			if (celeron)
954*7c478bd9Sstevel@tonic-gate 				return ("Intel Celeron(r)");
955*7c478bd9Sstevel@tonic-gate 			if (xeon)
956*7c478bd9Sstevel@tonic-gate 				return (cpi->cpi_model == 5 ?
957*7c478bd9Sstevel@tonic-gate 				    "Intel Pentium(r) II Xeon(tm)" :
958*7c478bd9Sstevel@tonic-gate 				    "Intel Pentium(r) III Xeon(tm)");
959*7c478bd9Sstevel@tonic-gate 			return (cpi->cpi_model == 5 ?
960*7c478bd9Sstevel@tonic-gate 			    "Intel Pentium(r) II or Pentium(r) II Xeon(tm)" :
961*7c478bd9Sstevel@tonic-gate 			    "Intel Pentium(r) III or Pentium(r) III Xeon(tm)");
962*7c478bd9Sstevel@tonic-gate 		default:
963*7c478bd9Sstevel@tonic-gate 			break;
964*7c478bd9Sstevel@tonic-gate 		}
965*7c478bd9Sstevel@tonic-gate 	default:
966*7c478bd9Sstevel@tonic-gate 		break;
967*7c478bd9Sstevel@tonic-gate 	}
968*7c478bd9Sstevel@tonic-gate 
969*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_family <= 0xf && cpi->cpi_model <= 0xf &&
970*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_brandid != 0) {
971*7c478bd9Sstevel@tonic-gate 		static const struct {
972*7c478bd9Sstevel@tonic-gate 			uint_t bt_bid;
973*7c478bd9Sstevel@tonic-gate 			const char *bt_str;
974*7c478bd9Sstevel@tonic-gate 		} brand_tbl[] = {
975*7c478bd9Sstevel@tonic-gate 			{ 0x1,	"Intel(r) Celeron(r)" },
976*7c478bd9Sstevel@tonic-gate 			{ 0x2,	"Intel(r) Pentium(r) III" },
977*7c478bd9Sstevel@tonic-gate 			{ 0x3,	"Intel(r) Pentium(r) III Xeon(tm)" },
978*7c478bd9Sstevel@tonic-gate 			{ 0x4,	"Intel(r) Pentium(r) III" },
979*7c478bd9Sstevel@tonic-gate 			{ 0x6,	"Mobile Intel(r) Pentium(r) III" },
980*7c478bd9Sstevel@tonic-gate 			{ 0x7,	"Mobile Intel(r) Celeron(r)" },
981*7c478bd9Sstevel@tonic-gate 			{ 0x8,	"Intel(r) Pentium(r) 4" },
982*7c478bd9Sstevel@tonic-gate 			{ 0x9,	"Intel(r) Pentium(r) 4" },
983*7c478bd9Sstevel@tonic-gate 			{ 0xa,	"Intel(r) Celeron(r)" },
984*7c478bd9Sstevel@tonic-gate 			{ 0xb,	"Intel(r) Xeon(tm)" },
985*7c478bd9Sstevel@tonic-gate 			{ 0xc,	"Intel(r) Xeon(tm) MP" },
986*7c478bd9Sstevel@tonic-gate 			{ 0xe,	"Mobile Intel(r) Pentium(r) 4" },
987*7c478bd9Sstevel@tonic-gate 			{ 0xf,	"Mobile Intel(r) Celeron(r)" }
988*7c478bd9Sstevel@tonic-gate 		};
989*7c478bd9Sstevel@tonic-gate 		uint_t btblmax = sizeof (brand_tbl) / sizeof (brand_tbl[0]);
990*7c478bd9Sstevel@tonic-gate 		uint_t sgn;
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate 		sgn = (cpi->cpi_family << 8) |
993*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_model << 4) | cpi->cpi_step;
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < btblmax; i++)
996*7c478bd9Sstevel@tonic-gate 			if (brand_tbl[i].bt_bid == cpi->cpi_brandid)
997*7c478bd9Sstevel@tonic-gate 				break;
998*7c478bd9Sstevel@tonic-gate 		if (i < btblmax) {
999*7c478bd9Sstevel@tonic-gate 			if (sgn == 0x6b1 && cpi->cpi_brandid == 3)
1000*7c478bd9Sstevel@tonic-gate 				return ("Intel(r) Celeron(r)");
1001*7c478bd9Sstevel@tonic-gate 			if (sgn < 0xf13 && cpi->cpi_brandid == 0xb)
1002*7c478bd9Sstevel@tonic-gate 				return ("Intel(r) Xeon(tm) MP");
1003*7c478bd9Sstevel@tonic-gate 			if (sgn < 0xf13 && cpi->cpi_brandid == 0xe)
1004*7c478bd9Sstevel@tonic-gate 				return ("Intel(r) Xeon(tm)");
1005*7c478bd9Sstevel@tonic-gate 			return (brand_tbl[i].bt_str);
1006*7c478bd9Sstevel@tonic-gate 		}
1007*7c478bd9Sstevel@tonic-gate 	}
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 	return (NULL);
1010*7c478bd9Sstevel@tonic-gate }
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate static const char *
1013*7c478bd9Sstevel@tonic-gate amd_cpubrand(const struct cpuid_info *cpi)
1014*7c478bd9Sstevel@tonic-gate {
1015*7c478bd9Sstevel@tonic-gate 	if ((x86_feature & X86_CPUID) == 0 ||
1016*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_maxeax < 1 || cpi->cpi_family < 5)
1017*7c478bd9Sstevel@tonic-gate 		return ("i486 compatible");
1018*7c478bd9Sstevel@tonic-gate 
1019*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_family) {
1020*7c478bd9Sstevel@tonic-gate 	case 5:
1021*7c478bd9Sstevel@tonic-gate 		switch (cpi->cpi_model) {
1022*7c478bd9Sstevel@tonic-gate 		case 0:
1023*7c478bd9Sstevel@tonic-gate 		case 1:
1024*7c478bd9Sstevel@tonic-gate 		case 2:
1025*7c478bd9Sstevel@tonic-gate 		case 3:
1026*7c478bd9Sstevel@tonic-gate 		case 4:
1027*7c478bd9Sstevel@tonic-gate 		case 5:
1028*7c478bd9Sstevel@tonic-gate 			return ("AMD-K5(r)");
1029*7c478bd9Sstevel@tonic-gate 		case 6:
1030*7c478bd9Sstevel@tonic-gate 		case 7:
1031*7c478bd9Sstevel@tonic-gate 			return ("AMD-K6(r)");
1032*7c478bd9Sstevel@tonic-gate 		case 8:
1033*7c478bd9Sstevel@tonic-gate 			return ("AMD-K6(r)-2");
1034*7c478bd9Sstevel@tonic-gate 		case 9:
1035*7c478bd9Sstevel@tonic-gate 			return ("AMD-K6(r)-III");
1036*7c478bd9Sstevel@tonic-gate 		default:
1037*7c478bd9Sstevel@tonic-gate 			return ("AMD (family 5)");
1038*7c478bd9Sstevel@tonic-gate 		}
1039*7c478bd9Sstevel@tonic-gate 	case 6:
1040*7c478bd9Sstevel@tonic-gate 		switch (cpi->cpi_model) {
1041*7c478bd9Sstevel@tonic-gate 		case 1:
1042*7c478bd9Sstevel@tonic-gate 			return ("AMD-K7(tm)");
1043*7c478bd9Sstevel@tonic-gate 		case 0:
1044*7c478bd9Sstevel@tonic-gate 		case 2:
1045*7c478bd9Sstevel@tonic-gate 		case 4:
1046*7c478bd9Sstevel@tonic-gate 			return ("AMD Athlon(tm)");
1047*7c478bd9Sstevel@tonic-gate 		case 3:
1048*7c478bd9Sstevel@tonic-gate 		case 7:
1049*7c478bd9Sstevel@tonic-gate 			return ("AMD Duron(tm)");
1050*7c478bd9Sstevel@tonic-gate 		case 6:
1051*7c478bd9Sstevel@tonic-gate 		case 8:
1052*7c478bd9Sstevel@tonic-gate 		case 10:
1053*7c478bd9Sstevel@tonic-gate 			/*
1054*7c478bd9Sstevel@tonic-gate 			 * Use the L2 cache size to distinguish
1055*7c478bd9Sstevel@tonic-gate 			 */
1056*7c478bd9Sstevel@tonic-gate 			return ((cpi->cpi_extd[6].cp_ecx >> 16) >= 256 ?
1057*7c478bd9Sstevel@tonic-gate 			    "AMD Athlon(tm)" : "AMD Duron(tm)");
1058*7c478bd9Sstevel@tonic-gate 		default:
1059*7c478bd9Sstevel@tonic-gate 			return ("AMD (family 6)");
1060*7c478bd9Sstevel@tonic-gate 		}
1061*7c478bd9Sstevel@tonic-gate 	default:
1062*7c478bd9Sstevel@tonic-gate 		break;
1063*7c478bd9Sstevel@tonic-gate 	}
1064*7c478bd9Sstevel@tonic-gate 
1065*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_family == 0xf && cpi->cpi_model == 5 &&
1066*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_brandid != 0) {
1067*7c478bd9Sstevel@tonic-gate 		switch (BITX(cpi->cpi_brandid, 7, 5)) {
1068*7c478bd9Sstevel@tonic-gate 		case 3:
1069*7c478bd9Sstevel@tonic-gate 			return ("AMD Opteron(tm) UP 1xx");
1070*7c478bd9Sstevel@tonic-gate 		case 4:
1071*7c478bd9Sstevel@tonic-gate 			return ("AMD Opteron(tm) DP 2xx");
1072*7c478bd9Sstevel@tonic-gate 		case 5:
1073*7c478bd9Sstevel@tonic-gate 			return ("AMD Opteron(tm) MP 8xx");
1074*7c478bd9Sstevel@tonic-gate 		default:
1075*7c478bd9Sstevel@tonic-gate 			return ("AMD Opteron(tm)");
1076*7c478bd9Sstevel@tonic-gate 		}
1077*7c478bd9Sstevel@tonic-gate 	}
1078*7c478bd9Sstevel@tonic-gate 
1079*7c478bd9Sstevel@tonic-gate 	return (NULL);
1080*7c478bd9Sstevel@tonic-gate }
1081*7c478bd9Sstevel@tonic-gate 
1082*7c478bd9Sstevel@tonic-gate static const char *
1083*7c478bd9Sstevel@tonic-gate cyrix_cpubrand(struct cpuid_info *cpi, uint_t type)
1084*7c478bd9Sstevel@tonic-gate {
1085*7c478bd9Sstevel@tonic-gate 	if ((x86_feature & X86_CPUID) == 0 ||
1086*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_maxeax < 1 || cpi->cpi_family < 5 ||
1087*7c478bd9Sstevel@tonic-gate 	    type == X86_TYPE_CYRIX_486)
1088*7c478bd9Sstevel@tonic-gate 		return ("i486 compatible");
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate 	switch (type) {
1091*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_6x86:
1092*7c478bd9Sstevel@tonic-gate 		return ("Cyrix 6x86");
1093*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_6x86L:
1094*7c478bd9Sstevel@tonic-gate 		return ("Cyrix 6x86L");
1095*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_6x86MX:
1096*7c478bd9Sstevel@tonic-gate 		return ("Cyrix 6x86MX");
1097*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_GXm:
1098*7c478bd9Sstevel@tonic-gate 		return ("Cyrix GXm");
1099*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_MediaGX:
1100*7c478bd9Sstevel@tonic-gate 		return ("Cyrix MediaGX");
1101*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_CYRIX_MII:
1102*7c478bd9Sstevel@tonic-gate 		return ("Cyrix M2");
1103*7c478bd9Sstevel@tonic-gate 	case X86_TYPE_VIA_CYRIX_III:
1104*7c478bd9Sstevel@tonic-gate 		return ("VIA Cyrix M3");
1105*7c478bd9Sstevel@tonic-gate 	default:
1106*7c478bd9Sstevel@tonic-gate 		/*
1107*7c478bd9Sstevel@tonic-gate 		 * Have another wild guess ..
1108*7c478bd9Sstevel@tonic-gate 		 */
1109*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 4 && cpi->cpi_model == 9)
1110*7c478bd9Sstevel@tonic-gate 			return ("Cyrix 5x86");
1111*7c478bd9Sstevel@tonic-gate 		else if (cpi->cpi_family == 5) {
1112*7c478bd9Sstevel@tonic-gate 			switch (cpi->cpi_model) {
1113*7c478bd9Sstevel@tonic-gate 			case 2:
1114*7c478bd9Sstevel@tonic-gate 				return ("Cyrix 6x86");	/* Cyrix M1 */
1115*7c478bd9Sstevel@tonic-gate 			case 4:
1116*7c478bd9Sstevel@tonic-gate 				return ("Cyrix MediaGX");
1117*7c478bd9Sstevel@tonic-gate 			default:
1118*7c478bd9Sstevel@tonic-gate 				break;
1119*7c478bd9Sstevel@tonic-gate 			}
1120*7c478bd9Sstevel@tonic-gate 		} else if (cpi->cpi_family == 6) {
1121*7c478bd9Sstevel@tonic-gate 			switch (cpi->cpi_model) {
1122*7c478bd9Sstevel@tonic-gate 			case 0:
1123*7c478bd9Sstevel@tonic-gate 				return ("Cyrix 6x86MX"); /* Cyrix M2? */
1124*7c478bd9Sstevel@tonic-gate 			case 5:
1125*7c478bd9Sstevel@tonic-gate 			case 6:
1126*7c478bd9Sstevel@tonic-gate 			case 7:
1127*7c478bd9Sstevel@tonic-gate 			case 8:
1128*7c478bd9Sstevel@tonic-gate 			case 9:
1129*7c478bd9Sstevel@tonic-gate 				return ("VIA C3");
1130*7c478bd9Sstevel@tonic-gate 			default:
1131*7c478bd9Sstevel@tonic-gate 				break;
1132*7c478bd9Sstevel@tonic-gate 			}
1133*7c478bd9Sstevel@tonic-gate 		}
1134*7c478bd9Sstevel@tonic-gate 		break;
1135*7c478bd9Sstevel@tonic-gate 	}
1136*7c478bd9Sstevel@tonic-gate 	return (NULL);
1137*7c478bd9Sstevel@tonic-gate }
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate /*
1140*7c478bd9Sstevel@tonic-gate  * This only gets called in the case that the CPU extended
1141*7c478bd9Sstevel@tonic-gate  * feature brand string (0x80000002, 0x80000003, 0x80000004)
1142*7c478bd9Sstevel@tonic-gate  * aren't available, or contain null bytes for some reason.
1143*7c478bd9Sstevel@tonic-gate  */
1144*7c478bd9Sstevel@tonic-gate static void
1145*7c478bd9Sstevel@tonic-gate fabricate_brandstr(struct cpuid_info *cpi)
1146*7c478bd9Sstevel@tonic-gate {
1147*7c478bd9Sstevel@tonic-gate 	const char *brand = NULL;
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
1150*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
1151*7c478bd9Sstevel@tonic-gate 		brand = intel_cpubrand(cpi);
1152*7c478bd9Sstevel@tonic-gate 		break;
1153*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
1154*7c478bd9Sstevel@tonic-gate 		brand = amd_cpubrand(cpi);
1155*7c478bd9Sstevel@tonic-gate 		break;
1156*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
1157*7c478bd9Sstevel@tonic-gate 		brand = cyrix_cpubrand(cpi, x86_type);
1158*7c478bd9Sstevel@tonic-gate 		break;
1159*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_NexGen:
1160*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5 && cpi->cpi_model == 0)
1161*7c478bd9Sstevel@tonic-gate 			brand = "NexGen Nx586";
1162*7c478bd9Sstevel@tonic-gate 		break;
1163*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Centaur:
1164*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5)
1165*7c478bd9Sstevel@tonic-gate 			switch (cpi->cpi_model) {
1166*7c478bd9Sstevel@tonic-gate 			case 4:
1167*7c478bd9Sstevel@tonic-gate 				brand = "Centaur C6";
1168*7c478bd9Sstevel@tonic-gate 				break;
1169*7c478bd9Sstevel@tonic-gate 			case 8:
1170*7c478bd9Sstevel@tonic-gate 				brand = "Centaur C2";
1171*7c478bd9Sstevel@tonic-gate 				break;
1172*7c478bd9Sstevel@tonic-gate 			case 9:
1173*7c478bd9Sstevel@tonic-gate 				brand = "Centaur C3";
1174*7c478bd9Sstevel@tonic-gate 				break;
1175*7c478bd9Sstevel@tonic-gate 			default:
1176*7c478bd9Sstevel@tonic-gate 				break;
1177*7c478bd9Sstevel@tonic-gate 			}
1178*7c478bd9Sstevel@tonic-gate 		break;
1179*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Rise:
1180*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5 &&
1181*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_model == 0 || cpi->cpi_model == 2))
1182*7c478bd9Sstevel@tonic-gate 			brand = "Rise mP6";
1183*7c478bd9Sstevel@tonic-gate 		break;
1184*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_SiS:
1185*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5 && cpi->cpi_model == 0)
1186*7c478bd9Sstevel@tonic-gate 			brand = "SiS 55x";
1187*7c478bd9Sstevel@tonic-gate 		break;
1188*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
1189*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family == 5 && cpi->cpi_model == 4)
1190*7c478bd9Sstevel@tonic-gate 			brand = "Transmeta Crusoe TM3x00 or TM5x00";
1191*7c478bd9Sstevel@tonic-gate 		break;
1192*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_NSC:
1193*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_UMC:
1194*7c478bd9Sstevel@tonic-gate 	default:
1195*7c478bd9Sstevel@tonic-gate 		break;
1196*7c478bd9Sstevel@tonic-gate 	}
1197*7c478bd9Sstevel@tonic-gate 	if (brand) {
1198*7c478bd9Sstevel@tonic-gate 		(void) strcpy((char *)cpi->cpi_brandstr, brand);
1199*7c478bd9Sstevel@tonic-gate 		return;
1200*7c478bd9Sstevel@tonic-gate 	}
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate 	/*
1203*7c478bd9Sstevel@tonic-gate 	 * If all else fails ...
1204*7c478bd9Sstevel@tonic-gate 	 */
1205*7c478bd9Sstevel@tonic-gate 	(void) snprintf(cpi->cpi_brandstr, sizeof (cpi->cpi_brandstr),
1206*7c478bd9Sstevel@tonic-gate 	    "%s %d.%d.%d", cpi->cpi_vendorstr, cpi->cpi_family,
1207*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_model, cpi->cpi_step);
1208*7c478bd9Sstevel@tonic-gate }
1209*7c478bd9Sstevel@tonic-gate 
1210*7c478bd9Sstevel@tonic-gate /*
1211*7c478bd9Sstevel@tonic-gate  * This routine is called just after kernel memory allocation
1212*7c478bd9Sstevel@tonic-gate  * becomes available on cpu0, and as part of mp_startup() on
1213*7c478bd9Sstevel@tonic-gate  * the other cpus.
1214*7c478bd9Sstevel@tonic-gate  *
1215*7c478bd9Sstevel@tonic-gate  * Fixup the brand string.
1216*7c478bd9Sstevel@tonic-gate  */
1217*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1218*7c478bd9Sstevel@tonic-gate void
1219*7c478bd9Sstevel@tonic-gate cpuid_pass3(cpu_t *cpu)
1220*7c478bd9Sstevel@tonic-gate {
1221*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate 	ASSERT(cpi->cpi_pass == 2);
1224*7c478bd9Sstevel@tonic-gate 
1225*7c478bd9Sstevel@tonic-gate 	if ((cpi->cpi_xmaxeax & 0x80000000) == 0) {
1226*7c478bd9Sstevel@tonic-gate 		fabricate_brandstr(cpi);
1227*7c478bd9Sstevel@tonic-gate 		goto pass3_done;
1228*7c478bd9Sstevel@tonic-gate 	}
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate 	/*
1231*7c478bd9Sstevel@tonic-gate 	 * If we successfully extracted a brand string from the cpuid
1232*7c478bd9Sstevel@tonic-gate 	 * instruction, clean it up by removing leading spaces and
1233*7c478bd9Sstevel@tonic-gate 	 * similar junk.
1234*7c478bd9Sstevel@tonic-gate 	 */
1235*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_brandstr[0]) {
1236*7c478bd9Sstevel@tonic-gate 		size_t maxlen = sizeof (cpi->cpi_brandstr);
1237*7c478bd9Sstevel@tonic-gate 		char *src, *dst;
1238*7c478bd9Sstevel@tonic-gate 
1239*7c478bd9Sstevel@tonic-gate 		dst = src = (char *)cpi->cpi_brandstr;
1240*7c478bd9Sstevel@tonic-gate 		src[maxlen - 1] = '\0';
1241*7c478bd9Sstevel@tonic-gate 		/*
1242*7c478bd9Sstevel@tonic-gate 		 * strip leading spaces
1243*7c478bd9Sstevel@tonic-gate 		 */
1244*7c478bd9Sstevel@tonic-gate 		while (*src == ' ')
1245*7c478bd9Sstevel@tonic-gate 			src++;
1246*7c478bd9Sstevel@tonic-gate 		/*
1247*7c478bd9Sstevel@tonic-gate 		 * Remove any 'Genuine' or "Authentic" prefixes
1248*7c478bd9Sstevel@tonic-gate 		 */
1249*7c478bd9Sstevel@tonic-gate 		if (strncmp(src, "Genuine ", 8) == 0)
1250*7c478bd9Sstevel@tonic-gate 			src += 8;
1251*7c478bd9Sstevel@tonic-gate 		if (strncmp(src, "Authentic ", 10) == 0)
1252*7c478bd9Sstevel@tonic-gate 			src += 10;
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate 		/*
1255*7c478bd9Sstevel@tonic-gate 		 * Now do an in-place copy.
1256*7c478bd9Sstevel@tonic-gate 		 * Map (R) to (r) and (TM) to (tm).
1257*7c478bd9Sstevel@tonic-gate 		 * The era of teletypes is long gone, and there's
1258*7c478bd9Sstevel@tonic-gate 		 * -really- no need to shout.
1259*7c478bd9Sstevel@tonic-gate 		 */
1260*7c478bd9Sstevel@tonic-gate 		while (*src != '\0') {
1261*7c478bd9Sstevel@tonic-gate 			if (src[0] == '(') {
1262*7c478bd9Sstevel@tonic-gate 				if (strncmp(src + 1, "R)", 2) == 0) {
1263*7c478bd9Sstevel@tonic-gate 					(void) strncpy(dst, "(r)", 3);
1264*7c478bd9Sstevel@tonic-gate 					src += 3;
1265*7c478bd9Sstevel@tonic-gate 					dst += 3;
1266*7c478bd9Sstevel@tonic-gate 					continue;
1267*7c478bd9Sstevel@tonic-gate 				}
1268*7c478bd9Sstevel@tonic-gate 				if (strncmp(src + 1, "TM)", 3) == 0) {
1269*7c478bd9Sstevel@tonic-gate 					(void) strncpy(dst, "(tm)", 4);
1270*7c478bd9Sstevel@tonic-gate 					src += 4;
1271*7c478bd9Sstevel@tonic-gate 					dst += 4;
1272*7c478bd9Sstevel@tonic-gate 					continue;
1273*7c478bd9Sstevel@tonic-gate 				}
1274*7c478bd9Sstevel@tonic-gate 			}
1275*7c478bd9Sstevel@tonic-gate 			*dst++ = *src++;
1276*7c478bd9Sstevel@tonic-gate 		}
1277*7c478bd9Sstevel@tonic-gate 		*dst = '\0';
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 		/*
1280*7c478bd9Sstevel@tonic-gate 		 * Finally, remove any trailing spaces
1281*7c478bd9Sstevel@tonic-gate 		 */
1282*7c478bd9Sstevel@tonic-gate 		while (--dst > cpi->cpi_brandstr)
1283*7c478bd9Sstevel@tonic-gate 			if (*dst == ' ')
1284*7c478bd9Sstevel@tonic-gate 				*dst = '\0';
1285*7c478bd9Sstevel@tonic-gate 			else
1286*7c478bd9Sstevel@tonic-gate 				break;
1287*7c478bd9Sstevel@tonic-gate 	} else
1288*7c478bd9Sstevel@tonic-gate 		fabricate_brandstr(cpi);
1289*7c478bd9Sstevel@tonic-gate 
1290*7c478bd9Sstevel@tonic-gate pass3_done:
1291*7c478bd9Sstevel@tonic-gate 	cpi->cpi_pass = 3;
1292*7c478bd9Sstevel@tonic-gate }
1293*7c478bd9Sstevel@tonic-gate 
1294*7c478bd9Sstevel@tonic-gate /*
1295*7c478bd9Sstevel@tonic-gate  * This routine is called out of bind_hwcap() much later in the life
1296*7c478bd9Sstevel@tonic-gate  * of the kernel (post_startup()).  The job of this routine is to resolve
1297*7c478bd9Sstevel@tonic-gate  * the hardware feature support and kernel support for those features into
1298*7c478bd9Sstevel@tonic-gate  * what we're actually going to tell applications via the aux vector.
1299*7c478bd9Sstevel@tonic-gate  */
1300*7c478bd9Sstevel@tonic-gate uint_t
1301*7c478bd9Sstevel@tonic-gate cpuid_pass4(cpu_t *cpu)
1302*7c478bd9Sstevel@tonic-gate {
1303*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi;
1304*7c478bd9Sstevel@tonic-gate 	uint_t hwcap_flags = 0;
1305*7c478bd9Sstevel@tonic-gate 
1306*7c478bd9Sstevel@tonic-gate 	if (cpu == NULL)
1307*7c478bd9Sstevel@tonic-gate 		cpu = CPU;
1308*7c478bd9Sstevel@tonic-gate 	cpi = cpu->cpu_m.mcpu_cpi;
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate 	ASSERT(cpi->cpi_pass == 3);
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_maxeax >= 1) {
1313*7c478bd9Sstevel@tonic-gate 		uint32_t *edx = &cpi->cpi_support[STD_EDX_FEATURES];
1314*7c478bd9Sstevel@tonic-gate 		uint32_t *ecx = &cpi->cpi_support[STD_ECX_FEATURES];
1315*7c478bd9Sstevel@tonic-gate 
1316*7c478bd9Sstevel@tonic-gate 		*edx = CPI_FEATURES_EDX(cpi);
1317*7c478bd9Sstevel@tonic-gate 		*ecx = CPI_FEATURES_ECX(cpi);
1318*7c478bd9Sstevel@tonic-gate 
1319*7c478bd9Sstevel@tonic-gate 		/*
1320*7c478bd9Sstevel@tonic-gate 		 * [these require explicit kernel support]
1321*7c478bd9Sstevel@tonic-gate 		 */
1322*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_SEP) == 0)
1323*7c478bd9Sstevel@tonic-gate 			*edx &= ~CPUID_INTC_EDX_SEP;
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_SSE) == 0)
1326*7c478bd9Sstevel@tonic-gate 			*edx &= ~(CPUID_INTC_EDX_FXSR|CPUID_INTC_EDX_SSE);
1327*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_SSE2) == 0)
1328*7c478bd9Sstevel@tonic-gate 			*edx &= ~CPUID_INTC_EDX_SSE2;
1329*7c478bd9Sstevel@tonic-gate 
1330*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_HTT) == 0)
1331*7c478bd9Sstevel@tonic-gate 			*edx &= ~CPUID_INTC_EDX_HTT;
1332*7c478bd9Sstevel@tonic-gate 
1333*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_SSE3) == 0)
1334*7c478bd9Sstevel@tonic-gate 			*ecx &= ~CPUID_INTC_ECX_SSE3;
1335*7c478bd9Sstevel@tonic-gate 
1336*7c478bd9Sstevel@tonic-gate 		/*
1337*7c478bd9Sstevel@tonic-gate 		 * [no explicit support required beyond x87 fp context]
1338*7c478bd9Sstevel@tonic-gate 		 */
1339*7c478bd9Sstevel@tonic-gate 		if (!fpu_exists)
1340*7c478bd9Sstevel@tonic-gate 			*edx &= ~(CPUID_INTC_EDX_FPU | CPUID_INTC_EDX_MMX);
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 		/*
1343*7c478bd9Sstevel@tonic-gate 		 * Now map the supported feature vector to things that we
1344*7c478bd9Sstevel@tonic-gate 		 * think userland will care about.
1345*7c478bd9Sstevel@tonic-gate 		 */
1346*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_SEP)
1347*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_SEP;
1348*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_SSE)
1349*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_FXSR | AV_386_SSE;
1350*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_SSE2)
1351*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_SSE2;
1352*7c478bd9Sstevel@tonic-gate 		if (*ecx & CPUID_INTC_ECX_SSE3)
1353*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_SSE3;
1354*7c478bd9Sstevel@tonic-gate 
1355*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_FPU)
1356*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_FPU;
1357*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_MMX)
1358*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_MMX;
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_TSC)
1361*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_TSC;
1362*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_CX8)
1363*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_CX8;
1364*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_INTC_EDX_CMOV)
1365*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_CMOV;
1366*7c478bd9Sstevel@tonic-gate 		if (*ecx & CPUID_INTC_ECX_MON)
1367*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_MON;
1368*7c478bd9Sstevel@tonic-gate #if defined(CPUID_INTC_ECX_CX16)
1369*7c478bd9Sstevel@tonic-gate 		if (*ecx & CPUID_INTC_ECX_CX16)
1370*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_CX16;
1371*7c478bd9Sstevel@tonic-gate #endif
1372*7c478bd9Sstevel@tonic-gate 	}
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate 	if (cpuid_is_ht(cpu))
1375*7c478bd9Sstevel@tonic-gate 		hwcap_flags |= AV_386_PAUSE;
1376*7c478bd9Sstevel@tonic-gate 
1377*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax < 0x80000001)
1378*7c478bd9Sstevel@tonic-gate 		goto pass4_done;
1379*7c478bd9Sstevel@tonic-gate 
1380*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
1381*7c478bd9Sstevel@tonic-gate 		uint32_t junk, *edx;
1382*7c478bd9Sstevel@tonic-gate 
1383*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:	/* sigh */
1384*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
1385*7c478bd9Sstevel@tonic-gate 		edx = &cpi->cpi_support[AMD_EDX_FEATURES];
1386*7c478bd9Sstevel@tonic-gate 
1387*7c478bd9Sstevel@tonic-gate 		*edx = CPI_FEATURES_XTD_EDX(cpi);
1388*7c478bd9Sstevel@tonic-gate 
1389*7c478bd9Sstevel@tonic-gate 		/*
1390*7c478bd9Sstevel@tonic-gate 		 * [no explicit support required beyond
1391*7c478bd9Sstevel@tonic-gate 		 * x87 fp context and exception handlers]
1392*7c478bd9Sstevel@tonic-gate 		 */
1393*7c478bd9Sstevel@tonic-gate 		if (!fpu_exists)
1394*7c478bd9Sstevel@tonic-gate 			*edx &= ~(CPUID_AMD_EDX_MMXamd |
1395*7c478bd9Sstevel@tonic-gate 			    CPUID_AMD_EDX_3DNow | CPUID_AMD_EDX_3DNowx);
1396*7c478bd9Sstevel@tonic-gate 
1397*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_ASYSC) == 0)
1398*7c478bd9Sstevel@tonic-gate 			*edx &= ~CPUID_AMD_EDX_SYSC;
1399*7c478bd9Sstevel@tonic-gate 		if ((x86_feature & X86_NX) == 0)
1400*7c478bd9Sstevel@tonic-gate 			*edx &= ~CPUID_AMD_EDX_NX;
1401*7c478bd9Sstevel@tonic-gate #if !defined(_LP64)
1402*7c478bd9Sstevel@tonic-gate 		*edx &= ~CPUID_AMD_EDX_LM;
1403*7c478bd9Sstevel@tonic-gate #endif
1404*7c478bd9Sstevel@tonic-gate 		/*
1405*7c478bd9Sstevel@tonic-gate 		 * Now map the supported feature vector to
1406*7c478bd9Sstevel@tonic-gate 		 * things that we think userland will care about.
1407*7c478bd9Sstevel@tonic-gate 		 */
1408*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_AMD_EDX_SYSC)
1409*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_AMD_SYSC;
1410*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_AMD_EDX_MMXamd)
1411*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_AMD_MMX;
1412*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_AMD_EDX_3DNow)
1413*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_AMD_3DNow;
1414*7c478bd9Sstevel@tonic-gate 		if (*edx & CPUID_AMD_EDX_3DNowx)
1415*7c478bd9Sstevel@tonic-gate 			hwcap_flags |= AV_386_AMD_3DNowx;
1416*7c478bd9Sstevel@tonic-gate 		break;
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
1419*7c478bd9Sstevel@tonic-gate 		edx = &cpi->cpi_support[TM_EDX_FEATURES];
1420*7c478bd9Sstevel@tonic-gate 		(void) __cpuid_insn(0x80860001, &junk, &junk, edx);
1421*7c478bd9Sstevel@tonic-gate 		break;
1422*7c478bd9Sstevel@tonic-gate 
1423*7c478bd9Sstevel@tonic-gate 	default:
1424*7c478bd9Sstevel@tonic-gate 		break;
1425*7c478bd9Sstevel@tonic-gate 	}
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate pass4_done:
1428*7c478bd9Sstevel@tonic-gate 	cpi->cpi_pass = 4;
1429*7c478bd9Sstevel@tonic-gate 	return (hwcap_flags);
1430*7c478bd9Sstevel@tonic-gate }
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate /*
1434*7c478bd9Sstevel@tonic-gate  * Simulate the cpuid instruction using the data we previously
1435*7c478bd9Sstevel@tonic-gate  * captured about this CPU.  We try our best to return the truth
1436*7c478bd9Sstevel@tonic-gate  * about the hardware, independently of kernel support.
1437*7c478bd9Sstevel@tonic-gate  */
1438*7c478bd9Sstevel@tonic-gate uint32_t
1439*7c478bd9Sstevel@tonic-gate cpuid_insn(cpu_t *cpu,
1440*7c478bd9Sstevel@tonic-gate     uint32_t eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
1441*7c478bd9Sstevel@tonic-gate {
1442*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi;
1443*7c478bd9Sstevel@tonic-gate 	struct cpuidr *cp;
1444*7c478bd9Sstevel@tonic-gate 
1445*7c478bd9Sstevel@tonic-gate 	if (cpu == NULL)
1446*7c478bd9Sstevel@tonic-gate 		cpu = CPU;
1447*7c478bd9Sstevel@tonic-gate 	cpi = cpu->cpu_m.mcpu_cpi;
1448*7c478bd9Sstevel@tonic-gate 
1449*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 3));
1450*7c478bd9Sstevel@tonic-gate 
1451*7c478bd9Sstevel@tonic-gate 	/*
1452*7c478bd9Sstevel@tonic-gate 	 * CPUID data is cached in two separate places: cpi_std for standard
1453*7c478bd9Sstevel@tonic-gate 	 * CPUID functions, and cpi_extd for extended CPUID functions.
1454*7c478bd9Sstevel@tonic-gate 	 */
1455*7c478bd9Sstevel@tonic-gate 	if (eax <= cpi->cpi_maxeax && eax < NMAX_CPI_STD)
1456*7c478bd9Sstevel@tonic-gate 		cp = &cpi->cpi_std[eax];
1457*7c478bd9Sstevel@tonic-gate 	else if (eax >= 0x80000000 && eax <= cpi->cpi_xmaxeax &&
1458*7c478bd9Sstevel@tonic-gate 	    eax < 0x80000000 + NMAX_CPI_EXTD)
1459*7c478bd9Sstevel@tonic-gate 		cp = &cpi->cpi_extd[eax - 0x80000000];
1460*7c478bd9Sstevel@tonic-gate 	else
1461*7c478bd9Sstevel@tonic-gate 		/*
1462*7c478bd9Sstevel@tonic-gate 		 * The caller is asking for data from an input parameter which
1463*7c478bd9Sstevel@tonic-gate 		 * the kernel has not cached.  In this case we go fetch from
1464*7c478bd9Sstevel@tonic-gate 		 * the hardware and return the data directly to the user.
1465*7c478bd9Sstevel@tonic-gate 		 */
1466*7c478bd9Sstevel@tonic-gate 		return (__cpuid_insn(eax, ebx, ecx, edx));
1467*7c478bd9Sstevel@tonic-gate 	*ebx = cp->cp_ebx;
1468*7c478bd9Sstevel@tonic-gate 	*ecx = cp->cp_ecx;
1469*7c478bd9Sstevel@tonic-gate 	*edx = cp->cp_edx;
1470*7c478bd9Sstevel@tonic-gate 	return (cp->cp_eax);
1471*7c478bd9Sstevel@tonic-gate }
1472*7c478bd9Sstevel@tonic-gate 
1473*7c478bd9Sstevel@tonic-gate int
1474*7c478bd9Sstevel@tonic-gate cpuid_checkpass(cpu_t *cpu, int pass)
1475*7c478bd9Sstevel@tonic-gate {
1476*7c478bd9Sstevel@tonic-gate 	return (cpu != NULL && cpu->cpu_m.mcpu_cpi != NULL &&
1477*7c478bd9Sstevel@tonic-gate 	    cpu->cpu_m.mcpu_cpi->cpi_pass >= pass);
1478*7c478bd9Sstevel@tonic-gate }
1479*7c478bd9Sstevel@tonic-gate 
1480*7c478bd9Sstevel@tonic-gate int
1481*7c478bd9Sstevel@tonic-gate cpuid_getbrandstr(cpu_t *cpu, char *s, size_t n)
1482*7c478bd9Sstevel@tonic-gate {
1483*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 3));
1484*7c478bd9Sstevel@tonic-gate 
1485*7c478bd9Sstevel@tonic-gate 	return (snprintf(s, n, "%s", cpu->cpu_m.mcpu_cpi->cpi_brandstr));
1486*7c478bd9Sstevel@tonic-gate }
1487*7c478bd9Sstevel@tonic-gate 
1488*7c478bd9Sstevel@tonic-gate int
1489*7c478bd9Sstevel@tonic-gate cpuid_is_ht(cpu_t *cpu)
1490*7c478bd9Sstevel@tonic-gate {
1491*7c478bd9Sstevel@tonic-gate 	if (cpu == NULL)
1492*7c478bd9Sstevel@tonic-gate 		cpu = CPU;
1493*7c478bd9Sstevel@tonic-gate 
1494*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1495*7c478bd9Sstevel@tonic-gate 
1496*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_chipid >= 0);
1497*7c478bd9Sstevel@tonic-gate }
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate /*
1500*7c478bd9Sstevel@tonic-gate  * AMD and Intel both implement the 64-bit variant of the syscall
1501*7c478bd9Sstevel@tonic-gate  * instruction (syscallq), so if there's -any- support for syscall,
1502*7c478bd9Sstevel@tonic-gate  * cpuid currently says "yes, we support this".
1503*7c478bd9Sstevel@tonic-gate  *
1504*7c478bd9Sstevel@tonic-gate  * However, Intel decided to -not- implement the 32-bit variant of the
1505*7c478bd9Sstevel@tonic-gate  * syscall instruction, so we provide a predicate to allow our caller
1506*7c478bd9Sstevel@tonic-gate  * to test that subtlety here.
1507*7c478bd9Sstevel@tonic-gate  */
1508*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1509*7c478bd9Sstevel@tonic-gate int
1510*7c478bd9Sstevel@tonic-gate cpuid_syscall32_insn(cpu_t *cpu)
1511*7c478bd9Sstevel@tonic-gate {
1512*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass((cpu == NULL ? CPU : cpu), 1));
1513*7c478bd9Sstevel@tonic-gate 
1514*7c478bd9Sstevel@tonic-gate 	if (x86_feature & X86_ASYSC)
1515*7c478bd9Sstevel@tonic-gate 		return (x86_vendor != X86_VENDOR_Intel);
1516*7c478bd9Sstevel@tonic-gate 	return (0);
1517*7c478bd9Sstevel@tonic-gate }
1518*7c478bd9Sstevel@tonic-gate 
1519*7c478bd9Sstevel@tonic-gate int
1520*7c478bd9Sstevel@tonic-gate cpuid_getidstr(cpu_t *cpu, char *s, size_t n)
1521*7c478bd9Sstevel@tonic-gate {
1522*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
1523*7c478bd9Sstevel@tonic-gate 
1524*7c478bd9Sstevel@tonic-gate 	static const char fmt[] =
1525*7c478bd9Sstevel@tonic-gate 	    "x86 (%s family %d model %d step %d clock %d MHz)";
1526*7c478bd9Sstevel@tonic-gate 	static const char fmt_ht[] =
1527*7c478bd9Sstevel@tonic-gate 	    "x86 (chipid 0x%x %s family %d model %d step %d clock %d MHz)";
1528*7c478bd9Sstevel@tonic-gate 
1529*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1530*7c478bd9Sstevel@tonic-gate 
1531*7c478bd9Sstevel@tonic-gate 	if (cpuid_is_ht(cpu))
1532*7c478bd9Sstevel@tonic-gate 		return (snprintf(s, n, fmt_ht, cpi->cpi_chipid,
1533*7c478bd9Sstevel@tonic-gate 		    cpi->cpi_vendorstr, cpi->cpi_family, cpi->cpi_model,
1534*7c478bd9Sstevel@tonic-gate 		    cpi->cpi_step, cpu->cpu_type_info.pi_clock));
1535*7c478bd9Sstevel@tonic-gate 	return (snprintf(s, n, fmt,
1536*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_vendorstr, cpi->cpi_family, cpi->cpi_model,
1537*7c478bd9Sstevel@tonic-gate 	    cpi->cpi_step, cpu->cpu_type_info.pi_clock));
1538*7c478bd9Sstevel@tonic-gate }
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate const char *
1541*7c478bd9Sstevel@tonic-gate cpuid_getvendorstr(cpu_t *cpu)
1542*7c478bd9Sstevel@tonic-gate {
1543*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1544*7c478bd9Sstevel@tonic-gate 	return ((const char *)cpu->cpu_m.mcpu_cpi->cpi_vendorstr);
1545*7c478bd9Sstevel@tonic-gate }
1546*7c478bd9Sstevel@tonic-gate 
1547*7c478bd9Sstevel@tonic-gate uint_t
1548*7c478bd9Sstevel@tonic-gate cpuid_getvendor(cpu_t *cpu)
1549*7c478bd9Sstevel@tonic-gate {
1550*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1551*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_vendor);
1552*7c478bd9Sstevel@tonic-gate }
1553*7c478bd9Sstevel@tonic-gate 
1554*7c478bd9Sstevel@tonic-gate uint_t
1555*7c478bd9Sstevel@tonic-gate cpuid_getfamily(cpu_t *cpu)
1556*7c478bd9Sstevel@tonic-gate {
1557*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1558*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_family);
1559*7c478bd9Sstevel@tonic-gate }
1560*7c478bd9Sstevel@tonic-gate 
1561*7c478bd9Sstevel@tonic-gate uint_t
1562*7c478bd9Sstevel@tonic-gate cpuid_getmodel(cpu_t *cpu)
1563*7c478bd9Sstevel@tonic-gate {
1564*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1565*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_model);
1566*7c478bd9Sstevel@tonic-gate }
1567*7c478bd9Sstevel@tonic-gate 
1568*7c478bd9Sstevel@tonic-gate uint_t
1569*7c478bd9Sstevel@tonic-gate cpuid_get_ncpu_per_chip(cpu_t *cpu)
1570*7c478bd9Sstevel@tonic-gate {
1571*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1572*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_ncpu_per_chip);
1573*7c478bd9Sstevel@tonic-gate }
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate uint_t
1576*7c478bd9Sstevel@tonic-gate cpuid_getstep(cpu_t *cpu)
1577*7c478bd9Sstevel@tonic-gate {
1578*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1579*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_step);
1580*7c478bd9Sstevel@tonic-gate }
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate chipid_t
1583*7c478bd9Sstevel@tonic-gate chip_plat_get_chipid(cpu_t *cpu)
1584*7c478bd9Sstevel@tonic-gate {
1585*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1586*7c478bd9Sstevel@tonic-gate 
1587*7c478bd9Sstevel@tonic-gate 	if (cpuid_is_ht(cpu))
1588*7c478bd9Sstevel@tonic-gate 		return (cpu->cpu_m.mcpu_cpi->cpi_chipid);
1589*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_id);
1590*7c478bd9Sstevel@tonic-gate }
1591*7c478bd9Sstevel@tonic-gate 
1592*7c478bd9Sstevel@tonic-gate int
1593*7c478bd9Sstevel@tonic-gate chip_plat_get_clogid(cpu_t *cpu)
1594*7c478bd9Sstevel@tonic-gate {
1595*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1596*7c478bd9Sstevel@tonic-gate 	return (cpu->cpu_m.mcpu_cpi->cpi_clogid);
1597*7c478bd9Sstevel@tonic-gate }
1598*7c478bd9Sstevel@tonic-gate 
1599*7c478bd9Sstevel@tonic-gate void
1600*7c478bd9Sstevel@tonic-gate cpuid_get_addrsize(cpu_t *cpu, uint_t *pabits, uint_t *vabits)
1601*7c478bd9Sstevel@tonic-gate {
1602*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi;
1603*7c478bd9Sstevel@tonic-gate 
1604*7c478bd9Sstevel@tonic-gate 	if (cpu == NULL)
1605*7c478bd9Sstevel@tonic-gate 		cpu = CPU;
1606*7c478bd9Sstevel@tonic-gate 	cpi = cpu->cpu_m.mcpu_cpi;
1607*7c478bd9Sstevel@tonic-gate 
1608*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1609*7c478bd9Sstevel@tonic-gate 
1610*7c478bd9Sstevel@tonic-gate 	if (pabits)
1611*7c478bd9Sstevel@tonic-gate 		*pabits = cpi->cpi_pabits;
1612*7c478bd9Sstevel@tonic-gate 	if (vabits)
1613*7c478bd9Sstevel@tonic-gate 		*vabits = cpi->cpi_vabits;
1614*7c478bd9Sstevel@tonic-gate }
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate /*
1617*7c478bd9Sstevel@tonic-gate  * Returns the number of data TLB entries for a corresponding
1618*7c478bd9Sstevel@tonic-gate  * pagesize.  If it can't be computed, or isn't known, the
1619*7c478bd9Sstevel@tonic-gate  * routine returns zero.  If you ask about an architecturally
1620*7c478bd9Sstevel@tonic-gate  * impossible pagesize, the routine will panic (so that the
1621*7c478bd9Sstevel@tonic-gate  * hat implementor knows that things are inconsistent.)
1622*7c478bd9Sstevel@tonic-gate  */
1623*7c478bd9Sstevel@tonic-gate uint_t
1624*7c478bd9Sstevel@tonic-gate cpuid_get_dtlb_nent(cpu_t *cpu, size_t pagesize)
1625*7c478bd9Sstevel@tonic-gate {
1626*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi;
1627*7c478bd9Sstevel@tonic-gate 	uint_t dtlb_nent = 0;
1628*7c478bd9Sstevel@tonic-gate 
1629*7c478bd9Sstevel@tonic-gate 	if (cpu == NULL)
1630*7c478bd9Sstevel@tonic-gate 		cpu = CPU;
1631*7c478bd9Sstevel@tonic-gate 	cpi = cpu->cpu_m.mcpu_cpi;
1632*7c478bd9Sstevel@tonic-gate 
1633*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid_checkpass(cpu, 1));
1634*7c478bd9Sstevel@tonic-gate 
1635*7c478bd9Sstevel@tonic-gate 	/*
1636*7c478bd9Sstevel@tonic-gate 	 * Check the L2 TLB info
1637*7c478bd9Sstevel@tonic-gate 	 */
1638*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax >= 0x80000006) {
1639*7c478bd9Sstevel@tonic-gate 		struct cpuidr *cp = &cpi->cpi_extd[6];
1640*7c478bd9Sstevel@tonic-gate 
1641*7c478bd9Sstevel@tonic-gate 		switch (pagesize) {
1642*7c478bd9Sstevel@tonic-gate 
1643*7c478bd9Sstevel@tonic-gate 		case 4 * 1024:
1644*7c478bd9Sstevel@tonic-gate 			/*
1645*7c478bd9Sstevel@tonic-gate 			 * All zero in the top 16 bits of the register
1646*7c478bd9Sstevel@tonic-gate 			 * indicates a unified TLB. Size is in low 16 bits.
1647*7c478bd9Sstevel@tonic-gate 			 */
1648*7c478bd9Sstevel@tonic-gate 			if ((cp->cp_ebx & 0xffff0000) == 0)
1649*7c478bd9Sstevel@tonic-gate 				dtlb_nent = cp->cp_ebx & 0x0000ffff;
1650*7c478bd9Sstevel@tonic-gate 			else
1651*7c478bd9Sstevel@tonic-gate 				dtlb_nent = BITX(cp->cp_ebx, 27, 16);
1652*7c478bd9Sstevel@tonic-gate 			break;
1653*7c478bd9Sstevel@tonic-gate 
1654*7c478bd9Sstevel@tonic-gate 		case 2 * 1024 * 1024:
1655*7c478bd9Sstevel@tonic-gate 			if ((cp->cp_eax & 0xffff0000) == 0)
1656*7c478bd9Sstevel@tonic-gate 				dtlb_nent = cp->cp_eax & 0x0000ffff;
1657*7c478bd9Sstevel@tonic-gate 			else
1658*7c478bd9Sstevel@tonic-gate 				dtlb_nent = BITX(cp->cp_eax, 27, 16);
1659*7c478bd9Sstevel@tonic-gate 			break;
1660*7c478bd9Sstevel@tonic-gate 
1661*7c478bd9Sstevel@tonic-gate 		default:
1662*7c478bd9Sstevel@tonic-gate 			panic("unknown L2 pagesize");
1663*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
1664*7c478bd9Sstevel@tonic-gate 		}
1665*7c478bd9Sstevel@tonic-gate 	}
1666*7c478bd9Sstevel@tonic-gate 
1667*7c478bd9Sstevel@tonic-gate 	if (dtlb_nent != 0)
1668*7c478bd9Sstevel@tonic-gate 		return (dtlb_nent);
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	/*
1671*7c478bd9Sstevel@tonic-gate 	 * No L2 TLB support for this size, try L1.
1672*7c478bd9Sstevel@tonic-gate 	 */
1673*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax >= 0x80000005) {
1674*7c478bd9Sstevel@tonic-gate 		struct cpuidr *cp = &cpi->cpi_extd[5];
1675*7c478bd9Sstevel@tonic-gate 
1676*7c478bd9Sstevel@tonic-gate 		switch (pagesize) {
1677*7c478bd9Sstevel@tonic-gate 		case 4 * 1024:
1678*7c478bd9Sstevel@tonic-gate 			dtlb_nent = BITX(cp->cp_ebx, 23, 16);
1679*7c478bd9Sstevel@tonic-gate 			break;
1680*7c478bd9Sstevel@tonic-gate 		case 2 * 1024 * 1024:
1681*7c478bd9Sstevel@tonic-gate 			dtlb_nent = BITX(cp->cp_eax, 23, 16);
1682*7c478bd9Sstevel@tonic-gate 			break;
1683*7c478bd9Sstevel@tonic-gate 		default:
1684*7c478bd9Sstevel@tonic-gate 			panic("unknown L1 d-TLB pagesize");
1685*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
1686*7c478bd9Sstevel@tonic-gate 		}
1687*7c478bd9Sstevel@tonic-gate 	}
1688*7c478bd9Sstevel@tonic-gate 
1689*7c478bd9Sstevel@tonic-gate 	return (dtlb_nent);
1690*7c478bd9Sstevel@tonic-gate }
1691*7c478bd9Sstevel@tonic-gate 
1692*7c478bd9Sstevel@tonic-gate /*
1693*7c478bd9Sstevel@tonic-gate  * Return 0 if the erratum is not present or not applicable, positive
1694*7c478bd9Sstevel@tonic-gate  * if it is, and negative if the status of the erratum is unknown.
1695*7c478bd9Sstevel@tonic-gate  *
1696*7c478bd9Sstevel@tonic-gate  * See "Revision Guide for AMD Athlon(tm) 64 and AMD Opteron(tm)
1697*7c478bd9Sstevel@tonic-gate  * Processors" #25759, Rev 3.50, May 2005
1698*7c478bd9Sstevel@tonic-gate  */
1699*7c478bd9Sstevel@tonic-gate int
1700*7c478bd9Sstevel@tonic-gate cpuid_opteron_erratum(cpu_t *cpu, uint_t erratum)
1701*7c478bd9Sstevel@tonic-gate {
1702*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
1703*7c478bd9Sstevel@tonic-gate 	uint_t eax;
1704*7c478bd9Sstevel@tonic-gate 
1705*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_vendor != X86_VENDOR_AMD)
1706*7c478bd9Sstevel@tonic-gate 		return (0);
1707*7c478bd9Sstevel@tonic-gate 
1708*7c478bd9Sstevel@tonic-gate 	eax = cpi->cpi_std[1].cp_eax;
1709*7c478bd9Sstevel@tonic-gate 
1710*7c478bd9Sstevel@tonic-gate #define	SH_B0(eax)	(eax == 0xf40 || eax == 0xf50)
1711*7c478bd9Sstevel@tonic-gate #define	SH_B3(eax) 	(eax == 0xf51)
1712*7c478bd9Sstevel@tonic-gate #define	B(eax)		(SH_B0(eax) | SH_B3(eax))
1713*7c478bd9Sstevel@tonic-gate 
1714*7c478bd9Sstevel@tonic-gate #define	SH_C0(eax)	(eax == 0xf48 || eax == 0xf58)
1715*7c478bd9Sstevel@tonic-gate 
1716*7c478bd9Sstevel@tonic-gate #define	SH_CG(eax)	(eax == 0xf4a || eax == 0xf5a || eax == 0xf7a)
1717*7c478bd9Sstevel@tonic-gate #define	DH_CG(eax)	(eax == 0xfc0 || eax == 0xfe0 || eax == 0xff0)
1718*7c478bd9Sstevel@tonic-gate #define	CH_CG(eax)	(eax == 0xf82 || eax == 0xfb2)
1719*7c478bd9Sstevel@tonic-gate #define	CG(eax)		(SH_CG(eax) | DH_CG(eax) | CH_CG(eax))
1720*7c478bd9Sstevel@tonic-gate 
1721*7c478bd9Sstevel@tonic-gate #define	SH_D0(eax)	(eax == 0x10f40 || eax == 0x10f50 || eax == 0x10f70)
1722*7c478bd9Sstevel@tonic-gate #define	DH_D0(eax)	(eax == 0x10fc0 || eax == 0x10ff0)
1723*7c478bd9Sstevel@tonic-gate #define	CH_D0(eax)	(eax == 0x10f80 || eax == 0x10fb0)
1724*7c478bd9Sstevel@tonic-gate #define	D0(eax)		(SH_D0(eax) | DH_D0(eax) | CH_D0(eax))
1725*7c478bd9Sstevel@tonic-gate 
1726*7c478bd9Sstevel@tonic-gate #define	SH_E0(eax)	(eax == 0x20f50 || eax == 0x20f40 || eax == 0x20f70)
1727*7c478bd9Sstevel@tonic-gate #define	JH_E1(eax)	(eax == 0x20f10)	/* JH8_E0 had 0x20f30 */
1728*7c478bd9Sstevel@tonic-gate #define	DH_E3(eax)	(eax == 0x20fc0 || eax == 0x20ff0)
1729*7c478bd9Sstevel@tonic-gate #define	SH_E4(eax)	(eax == 0x20f51 || eax == 0x20f71)
1730*7c478bd9Sstevel@tonic-gate #define	BH_E4(eax)	(eax == 0x20fb1)
1731*7c478bd9Sstevel@tonic-gate #define	SH_E5(eax)	(eax == 0x20f42)
1732*7c478bd9Sstevel@tonic-gate #define	DH_E6(eax)	(eax == 0x20ff2 || eax == 0x20fc2)
1733*7c478bd9Sstevel@tonic-gate #define	JH_E6(eax)	(eax == 0x20f12 || eax == 0x20f32)
1734*7c478bd9Sstevel@tonic-gate #define	EX(eax)		(SH_E0(eax) | JH_E1(eax) | DH_E3(eax) | SH_E4(eax) | \
1735*7c478bd9Sstevel@tonic-gate 			    BH_E4(eax) | SH_E5(eax) | DH_E6(eax) | JH_E6(eax))
1736*7c478bd9Sstevel@tonic-gate 
1737*7c478bd9Sstevel@tonic-gate 	switch (erratum) {
1738*7c478bd9Sstevel@tonic-gate 	case 1:
1739*7c478bd9Sstevel@tonic-gate 		return (1);
1740*7c478bd9Sstevel@tonic-gate 	case 51:	/* what does the asterisk mean? */
1741*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax));
1742*7c478bd9Sstevel@tonic-gate 	case 52:
1743*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1744*7c478bd9Sstevel@tonic-gate 	case 57:
1745*7c478bd9Sstevel@tonic-gate 		return (1);
1746*7c478bd9Sstevel@tonic-gate 	case 58:
1747*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1748*7c478bd9Sstevel@tonic-gate 	case 60:
1749*7c478bd9Sstevel@tonic-gate 		return (1);
1750*7c478bd9Sstevel@tonic-gate 	case 61:
1751*7c478bd9Sstevel@tonic-gate 	case 62:
1752*7c478bd9Sstevel@tonic-gate 	case 63:
1753*7c478bd9Sstevel@tonic-gate 	case 64:
1754*7c478bd9Sstevel@tonic-gate 	case 65:
1755*7c478bd9Sstevel@tonic-gate 	case 66:
1756*7c478bd9Sstevel@tonic-gate 	case 68:
1757*7c478bd9Sstevel@tonic-gate 	case 69:
1758*7c478bd9Sstevel@tonic-gate 	case 70:
1759*7c478bd9Sstevel@tonic-gate 	case 71:
1760*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1761*7c478bd9Sstevel@tonic-gate 	case 72:
1762*7c478bd9Sstevel@tonic-gate 		return (SH_B0(eax));
1763*7c478bd9Sstevel@tonic-gate 	case 74:
1764*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1765*7c478bd9Sstevel@tonic-gate 	case 75:
1766*7c478bd9Sstevel@tonic-gate 		return (1);
1767*7c478bd9Sstevel@tonic-gate 	case 76:
1768*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1769*7c478bd9Sstevel@tonic-gate 	case 77:
1770*7c478bd9Sstevel@tonic-gate 		return (1);
1771*7c478bd9Sstevel@tonic-gate 	case 78:
1772*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax));
1773*7c478bd9Sstevel@tonic-gate 	case 79:
1774*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax) || EX(eax));
1775*7c478bd9Sstevel@tonic-gate 	case 80:
1776*7c478bd9Sstevel@tonic-gate 	case 81:
1777*7c478bd9Sstevel@tonic-gate 	case 82:
1778*7c478bd9Sstevel@tonic-gate 		return (B(eax));
1779*7c478bd9Sstevel@tonic-gate 	case 83:
1780*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax));
1781*7c478bd9Sstevel@tonic-gate 	case 85:
1782*7c478bd9Sstevel@tonic-gate 		return (1);
1783*7c478bd9Sstevel@tonic-gate 	case 86:
1784*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax) || CG(eax));
1785*7c478bd9Sstevel@tonic-gate 	case 88:
1786*7c478bd9Sstevel@tonic-gate #if !defined(__amd64)
1787*7c478bd9Sstevel@tonic-gate 		return (0);
1788*7c478bd9Sstevel@tonic-gate #else
1789*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax));
1790*7c478bd9Sstevel@tonic-gate #endif
1791*7c478bd9Sstevel@tonic-gate 	case 89:
1792*7c478bd9Sstevel@tonic-gate 		return (1);
1793*7c478bd9Sstevel@tonic-gate 	case 90:
1794*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax));
1795*7c478bd9Sstevel@tonic-gate 	case 91:
1796*7c478bd9Sstevel@tonic-gate 	case 92:
1797*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax));
1798*7c478bd9Sstevel@tonic-gate 	case 93:
1799*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax));
1800*7c478bd9Sstevel@tonic-gate 	case 94:
1801*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax));
1802*7c478bd9Sstevel@tonic-gate 	case 95:
1803*7c478bd9Sstevel@tonic-gate #if !defined(__amd64)
1804*7c478bd9Sstevel@tonic-gate 		return (0);
1805*7c478bd9Sstevel@tonic-gate #else
1806*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax));
1807*7c478bd9Sstevel@tonic-gate #endif
1808*7c478bd9Sstevel@tonic-gate 	case 96:
1809*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax));
1810*7c478bd9Sstevel@tonic-gate 	case 97:
1811*7c478bd9Sstevel@tonic-gate 	case 98:
1812*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax) || CG(eax));
1813*7c478bd9Sstevel@tonic-gate 	case 99:
1814*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax));
1815*7c478bd9Sstevel@tonic-gate 	case 100:
1816*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax));
1817*7c478bd9Sstevel@tonic-gate 	case 101:
1818*7c478bd9Sstevel@tonic-gate 	case 103:
1819*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax));
1820*7c478bd9Sstevel@tonic-gate 	case 104:
1821*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax) || CG(eax) || D0(eax));
1822*7c478bd9Sstevel@tonic-gate 	case 105:
1823*7c478bd9Sstevel@tonic-gate 	case 106:
1824*7c478bd9Sstevel@tonic-gate 	case 107:
1825*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax));
1826*7c478bd9Sstevel@tonic-gate 	case 108:
1827*7c478bd9Sstevel@tonic-gate 		return (DH_CG(eax));
1828*7c478bd9Sstevel@tonic-gate 	case 109:
1829*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax) || CG(eax) || D0(eax));
1830*7c478bd9Sstevel@tonic-gate 	case 110:
1831*7c478bd9Sstevel@tonic-gate 		return (D0(eax) || EX(eax));
1832*7c478bd9Sstevel@tonic-gate 	case 111:
1833*7c478bd9Sstevel@tonic-gate 		return (CG(eax));
1834*7c478bd9Sstevel@tonic-gate 	case 112:
1835*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax) || EX(eax));
1836*7c478bd9Sstevel@tonic-gate 	case 113:
1837*7c478bd9Sstevel@tonic-gate 		return (eax == 0x20fc0);
1838*7c478bd9Sstevel@tonic-gate 	case 114:
1839*7c478bd9Sstevel@tonic-gate 		return (SH_E0(eax) || JH_E1(eax) || DH_E3(eax));
1840*7c478bd9Sstevel@tonic-gate 	case 115:
1841*7c478bd9Sstevel@tonic-gate 		return (SH_E0(eax) || JH_E1(eax));
1842*7c478bd9Sstevel@tonic-gate 	case 116:
1843*7c478bd9Sstevel@tonic-gate 		return (SH_E0(eax) || JH_E1(eax) || DH_E3(eax));
1844*7c478bd9Sstevel@tonic-gate 	case 117:
1845*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax));
1846*7c478bd9Sstevel@tonic-gate 	case 118:
1847*7c478bd9Sstevel@tonic-gate 		return (SH_E0(eax) || JH_E1(eax) || SH_E4(eax) || BH_E4(eax) ||
1848*7c478bd9Sstevel@tonic-gate 		    JH_E6(eax));
1849*7c478bd9Sstevel@tonic-gate 	case 121:
1850*7c478bd9Sstevel@tonic-gate 		return (B(eax) || SH_C0(eax) || CG(eax) || D0(eax) || EX(eax));
1851*7c478bd9Sstevel@tonic-gate 	case 122:
1852*7c478bd9Sstevel@tonic-gate 		return (SH_C0(eax) || CG(eax) || D0(eax) || EX(eax));
1853*7c478bd9Sstevel@tonic-gate 	case 123:
1854*7c478bd9Sstevel@tonic-gate 		return (JH_E1(eax) || BH_E4(eax) || JH_E6(eax));
1855*7c478bd9Sstevel@tonic-gate 
1856*7c478bd9Sstevel@tonic-gate 	default:
1857*7c478bd9Sstevel@tonic-gate 		return (-1);
1858*7c478bd9Sstevel@tonic-gate 	}
1859*7c478bd9Sstevel@tonic-gate }
1860*7c478bd9Sstevel@tonic-gate 
1861*7c478bd9Sstevel@tonic-gate static const char assoc_str[] = "associativity";
1862*7c478bd9Sstevel@tonic-gate static const char line_str[] = "line-size";
1863*7c478bd9Sstevel@tonic-gate static const char size_str[] = "size";
1864*7c478bd9Sstevel@tonic-gate 
1865*7c478bd9Sstevel@tonic-gate static void
1866*7c478bd9Sstevel@tonic-gate add_cache_prop(dev_info_t *devi, const char *label, const char *type,
1867*7c478bd9Sstevel@tonic-gate     uint32_t val)
1868*7c478bd9Sstevel@tonic-gate {
1869*7c478bd9Sstevel@tonic-gate 	char buf[128];
1870*7c478bd9Sstevel@tonic-gate 
1871*7c478bd9Sstevel@tonic-gate 	/*
1872*7c478bd9Sstevel@tonic-gate 	 * ndi_prop_update_int() is used because it is desirable for
1873*7c478bd9Sstevel@tonic-gate 	 * DDI_PROP_HW_DEF and DDI_PROP_DONTSLEEP to be set.
1874*7c478bd9Sstevel@tonic-gate 	 */
1875*7c478bd9Sstevel@tonic-gate 	if (snprintf(buf, sizeof (buf), "%s-%s", label, type) < sizeof (buf))
1876*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, devi, buf, val);
1877*7c478bd9Sstevel@tonic-gate }
1878*7c478bd9Sstevel@tonic-gate 
1879*7c478bd9Sstevel@tonic-gate /*
1880*7c478bd9Sstevel@tonic-gate  * Intel-style cache/tlb description
1881*7c478bd9Sstevel@tonic-gate  *
1882*7c478bd9Sstevel@tonic-gate  * Standard cpuid level 2 gives a randomly ordered
1883*7c478bd9Sstevel@tonic-gate  * selection of tags that index into a table that describes
1884*7c478bd9Sstevel@tonic-gate  * cache and tlb properties.
1885*7c478bd9Sstevel@tonic-gate  */
1886*7c478bd9Sstevel@tonic-gate 
1887*7c478bd9Sstevel@tonic-gate static const char l1_icache_str[] = "l1-icache";
1888*7c478bd9Sstevel@tonic-gate static const char l1_dcache_str[] = "l1-dcache";
1889*7c478bd9Sstevel@tonic-gate static const char l2_cache_str[] = "l2-cache";
1890*7c478bd9Sstevel@tonic-gate static const char itlb4k_str[] = "itlb-4K";
1891*7c478bd9Sstevel@tonic-gate static const char dtlb4k_str[] = "dtlb-4K";
1892*7c478bd9Sstevel@tonic-gate static const char itlb4M_str[] = "itlb-4M";
1893*7c478bd9Sstevel@tonic-gate static const char dtlb4M_str[] = "dtlb-4M";
1894*7c478bd9Sstevel@tonic-gate static const char itlb424_str[] = "itlb-4K-2M-4M";
1895*7c478bd9Sstevel@tonic-gate static const char dtlb44_str[] = "dtlb-4K-4M";
1896*7c478bd9Sstevel@tonic-gate static const char sl1_dcache_str[] = "sectored-l1-dcache";
1897*7c478bd9Sstevel@tonic-gate static const char sl2_cache_str[] = "sectored-l2-cache";
1898*7c478bd9Sstevel@tonic-gate static const char itrace_str[] = "itrace-cache";
1899*7c478bd9Sstevel@tonic-gate static const char sl3_cache_str[] = "sectored-l3-cache";
1900*7c478bd9Sstevel@tonic-gate 
1901*7c478bd9Sstevel@tonic-gate static const struct cachetab {
1902*7c478bd9Sstevel@tonic-gate 	uint8_t 	ct_code;
1903*7c478bd9Sstevel@tonic-gate 	uint8_t		ct_assoc;
1904*7c478bd9Sstevel@tonic-gate 	uint16_t 	ct_line_size;
1905*7c478bd9Sstevel@tonic-gate 	size_t		ct_size;
1906*7c478bd9Sstevel@tonic-gate 	const char	*ct_label;
1907*7c478bd9Sstevel@tonic-gate } intel_ctab[] = {
1908*7c478bd9Sstevel@tonic-gate 	/* maintain descending order! */
1909*7c478bd9Sstevel@tonic-gate 	{ 0xb3, 4, 0, 128, dtlb4k_str },
1910*7c478bd9Sstevel@tonic-gate 	{ 0xb0, 4, 0, 128, itlb4k_str },
1911*7c478bd9Sstevel@tonic-gate 	{ 0x87, 8, 64, 1024*1024, l2_cache_str},
1912*7c478bd9Sstevel@tonic-gate 	{ 0x86, 4, 64, 512*1024, l2_cache_str},
1913*7c478bd9Sstevel@tonic-gate 	{ 0x85, 8, 32, 2*1024*1024, l2_cache_str},
1914*7c478bd9Sstevel@tonic-gate 	{ 0x84, 8, 32, 1024*1024, l2_cache_str},
1915*7c478bd9Sstevel@tonic-gate 	{ 0x83, 8, 32, 512*1024, l2_cache_str},
1916*7c478bd9Sstevel@tonic-gate 	{ 0x82, 8, 32, 256*1024, l2_cache_str},
1917*7c478bd9Sstevel@tonic-gate 	{ 0x81, 8, 32, 128*1024, l2_cache_str},		/* suspect! */
1918*7c478bd9Sstevel@tonic-gate 	{ 0x7f, 2, 64, 512*1024, l2_cache_str},
1919*7c478bd9Sstevel@tonic-gate 	{ 0x7d, 8, 64, 2*1024*1024, sl2_cache_str},
1920*7c478bd9Sstevel@tonic-gate 	{ 0x7c, 8, 64, 1024*1024, sl2_cache_str},
1921*7c478bd9Sstevel@tonic-gate 	{ 0x7b, 8, 64, 512*1024, sl2_cache_str},
1922*7c478bd9Sstevel@tonic-gate 	{ 0x7a, 8, 64, 256*1024, sl2_cache_str},
1923*7c478bd9Sstevel@tonic-gate 	{ 0x79, 8, 64, 128*1024, sl2_cache_str},
1924*7c478bd9Sstevel@tonic-gate 	{ 0x78, 8, 64, 1024*1024, l2_cache_str},
1925*7c478bd9Sstevel@tonic-gate 	{ 0x72, 8, 0, 32*1024, itrace_str},
1926*7c478bd9Sstevel@tonic-gate 	{ 0x71, 8, 0, 16*1024, itrace_str},
1927*7c478bd9Sstevel@tonic-gate 	{ 0x70, 8, 0, 12*1024, itrace_str},
1928*7c478bd9Sstevel@tonic-gate 	{ 0x68, 4, 64, 32*1024, sl1_dcache_str},
1929*7c478bd9Sstevel@tonic-gate 	{ 0x67, 4, 64, 16*1024, sl1_dcache_str},
1930*7c478bd9Sstevel@tonic-gate 	{ 0x66, 4, 64, 8*1024, sl1_dcache_str},
1931*7c478bd9Sstevel@tonic-gate 	{ 0x60, 8, 64, 16*1024, sl1_dcache_str},
1932*7c478bd9Sstevel@tonic-gate 	{ 0x5d, 0, 0, 256, dtlb44_str},
1933*7c478bd9Sstevel@tonic-gate 	{ 0x5c, 0, 0, 128, dtlb44_str},
1934*7c478bd9Sstevel@tonic-gate 	{ 0x5b, 0, 0, 64, dtlb44_str},
1935*7c478bd9Sstevel@tonic-gate 	{ 0x52, 0, 0, 256, itlb424_str},
1936*7c478bd9Sstevel@tonic-gate 	{ 0x51, 0, 0, 128, itlb424_str},
1937*7c478bd9Sstevel@tonic-gate 	{ 0x50, 0, 0, 64, itlb424_str},
1938*7c478bd9Sstevel@tonic-gate 	{ 0x45, 4, 32, 2*1024*1024, l2_cache_str},
1939*7c478bd9Sstevel@tonic-gate 	{ 0x44, 4, 32, 1024*1024, l2_cache_str},
1940*7c478bd9Sstevel@tonic-gate 	{ 0x43, 4, 32, 512*1024, l2_cache_str},
1941*7c478bd9Sstevel@tonic-gate 	{ 0x42, 4, 32, 256*1024, l2_cache_str},
1942*7c478bd9Sstevel@tonic-gate 	{ 0x41, 4, 32, 128*1024, l2_cache_str},
1943*7c478bd9Sstevel@tonic-gate 	{ 0x3c, 4, 64, 256*1024, sl2_cache_str},
1944*7c478bd9Sstevel@tonic-gate 	{ 0x3b, 2, 64, 128*1024, sl2_cache_str},
1945*7c478bd9Sstevel@tonic-gate 	{ 0x39, 4, 64, 128*1024, sl2_cache_str},
1946*7c478bd9Sstevel@tonic-gate 	{ 0x30, 8, 64, 32*1024, l1_icache_str},
1947*7c478bd9Sstevel@tonic-gate 	{ 0x2c, 8, 64, 32*1024, l1_dcache_str},
1948*7c478bd9Sstevel@tonic-gate 	{ 0x29, 8, 64, 4096*1024, sl3_cache_str},
1949*7c478bd9Sstevel@tonic-gate 	{ 0x25, 8, 64, 2048*1024, sl3_cache_str},
1950*7c478bd9Sstevel@tonic-gate 	{ 0x23, 8, 64, 1024*1024, sl3_cache_str},
1951*7c478bd9Sstevel@tonic-gate 	{ 0x22, 4, 64, 512*1024, sl3_cache_str},
1952*7c478bd9Sstevel@tonic-gate 	{ 0x0c, 4, 32, 16*1024, l1_dcache_str},
1953*7c478bd9Sstevel@tonic-gate 	{ 0x0a, 2, 32, 8*1024, l1_dcache_str},
1954*7c478bd9Sstevel@tonic-gate 	{ 0x08, 4, 32, 16*1024, l1_icache_str},
1955*7c478bd9Sstevel@tonic-gate 	{ 0x06, 4, 32, 8*1024, l1_icache_str},
1956*7c478bd9Sstevel@tonic-gate 	{ 0x04, 4, 0, 8, dtlb4M_str},
1957*7c478bd9Sstevel@tonic-gate 	{ 0x03, 4, 0, 64, dtlb4k_str},
1958*7c478bd9Sstevel@tonic-gate 	{ 0x02, 4, 0, 2, itlb4M_str},
1959*7c478bd9Sstevel@tonic-gate 	{ 0x01, 4, 0, 32, itlb4k_str},
1960*7c478bd9Sstevel@tonic-gate 	{ 0 }
1961*7c478bd9Sstevel@tonic-gate };
1962*7c478bd9Sstevel@tonic-gate 
1963*7c478bd9Sstevel@tonic-gate static const struct cachetab cyrix_ctab[] = {
1964*7c478bd9Sstevel@tonic-gate 	{ 0x70, 4, 0, 32, "tlb-4K" },
1965*7c478bd9Sstevel@tonic-gate 	{ 0x80, 4, 16, 16*1024, "l1-cache" },
1966*7c478bd9Sstevel@tonic-gate 	{ 0 }
1967*7c478bd9Sstevel@tonic-gate };
1968*7c478bd9Sstevel@tonic-gate 
1969*7c478bd9Sstevel@tonic-gate /*
1970*7c478bd9Sstevel@tonic-gate  * Search a cache table for a matching entry
1971*7c478bd9Sstevel@tonic-gate  */
1972*7c478bd9Sstevel@tonic-gate static const struct cachetab *
1973*7c478bd9Sstevel@tonic-gate find_cacheent(const struct cachetab *ct, uint_t code)
1974*7c478bd9Sstevel@tonic-gate {
1975*7c478bd9Sstevel@tonic-gate 	if (code != 0) {
1976*7c478bd9Sstevel@tonic-gate 		for (; ct->ct_code != 0; ct++)
1977*7c478bd9Sstevel@tonic-gate 			if (ct->ct_code <= code)
1978*7c478bd9Sstevel@tonic-gate 				break;
1979*7c478bd9Sstevel@tonic-gate 		if (ct->ct_code == code)
1980*7c478bd9Sstevel@tonic-gate 			return (ct);
1981*7c478bd9Sstevel@tonic-gate 	}
1982*7c478bd9Sstevel@tonic-gate 	return (NULL);
1983*7c478bd9Sstevel@tonic-gate }
1984*7c478bd9Sstevel@tonic-gate 
1985*7c478bd9Sstevel@tonic-gate /*
1986*7c478bd9Sstevel@tonic-gate  * Walk the cacheinfo descriptor, applying 'func' to every valid element
1987*7c478bd9Sstevel@tonic-gate  * The walk is terminated if the walker returns non-zero.
1988*7c478bd9Sstevel@tonic-gate  */
1989*7c478bd9Sstevel@tonic-gate static void
1990*7c478bd9Sstevel@tonic-gate intel_walk_cacheinfo(struct cpuid_info *cpi,
1991*7c478bd9Sstevel@tonic-gate     void *arg, int (*func)(void *, const struct cachetab *))
1992*7c478bd9Sstevel@tonic-gate {
1993*7c478bd9Sstevel@tonic-gate 	const struct cachetab *ct;
1994*7c478bd9Sstevel@tonic-gate 	uint8_t *dp;
1995*7c478bd9Sstevel@tonic-gate 	int i;
1996*7c478bd9Sstevel@tonic-gate 
1997*7c478bd9Sstevel@tonic-gate 	if ((dp = cpi->cpi_cacheinfo) == NULL)
1998*7c478bd9Sstevel@tonic-gate 		return;
1999*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < cpi->cpi_ncache; i++, dp++)
2000*7c478bd9Sstevel@tonic-gate 		if ((ct = find_cacheent(intel_ctab, *dp)) != NULL) {
2001*7c478bd9Sstevel@tonic-gate 			if (func(arg, ct) != 0)
2002*7c478bd9Sstevel@tonic-gate 				break;
2003*7c478bd9Sstevel@tonic-gate 		}
2004*7c478bd9Sstevel@tonic-gate }
2005*7c478bd9Sstevel@tonic-gate 
2006*7c478bd9Sstevel@tonic-gate /*
2007*7c478bd9Sstevel@tonic-gate  * (Like the Intel one, except for Cyrix CPUs)
2008*7c478bd9Sstevel@tonic-gate  */
2009*7c478bd9Sstevel@tonic-gate static void
2010*7c478bd9Sstevel@tonic-gate cyrix_walk_cacheinfo(struct cpuid_info *cpi,
2011*7c478bd9Sstevel@tonic-gate     void *arg, int (*func)(void *, const struct cachetab *))
2012*7c478bd9Sstevel@tonic-gate {
2013*7c478bd9Sstevel@tonic-gate 	const struct cachetab *ct;
2014*7c478bd9Sstevel@tonic-gate 	uint8_t *dp;
2015*7c478bd9Sstevel@tonic-gate 	int i;
2016*7c478bd9Sstevel@tonic-gate 
2017*7c478bd9Sstevel@tonic-gate 	if ((dp = cpi->cpi_cacheinfo) == NULL)
2018*7c478bd9Sstevel@tonic-gate 		return;
2019*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < cpi->cpi_ncache; i++, dp++) {
2020*7c478bd9Sstevel@tonic-gate 		/*
2021*7c478bd9Sstevel@tonic-gate 		 * Search Cyrix-specific descriptor table first ..
2022*7c478bd9Sstevel@tonic-gate 		 */
2023*7c478bd9Sstevel@tonic-gate 		if ((ct = find_cacheent(cyrix_ctab, *dp)) != NULL) {
2024*7c478bd9Sstevel@tonic-gate 			if (func(arg, ct) != 0)
2025*7c478bd9Sstevel@tonic-gate 				break;
2026*7c478bd9Sstevel@tonic-gate 			continue;
2027*7c478bd9Sstevel@tonic-gate 		}
2028*7c478bd9Sstevel@tonic-gate 		/*
2029*7c478bd9Sstevel@tonic-gate 		 * .. else fall back to the Intel one
2030*7c478bd9Sstevel@tonic-gate 		 */
2031*7c478bd9Sstevel@tonic-gate 		if ((ct = find_cacheent(intel_ctab, *dp)) != NULL) {
2032*7c478bd9Sstevel@tonic-gate 			if (func(arg, ct) != 0)
2033*7c478bd9Sstevel@tonic-gate 				break;
2034*7c478bd9Sstevel@tonic-gate 			continue;
2035*7c478bd9Sstevel@tonic-gate 		}
2036*7c478bd9Sstevel@tonic-gate 	}
2037*7c478bd9Sstevel@tonic-gate }
2038*7c478bd9Sstevel@tonic-gate 
2039*7c478bd9Sstevel@tonic-gate /*
2040*7c478bd9Sstevel@tonic-gate  * A cacheinfo walker that adds associativity, line-size, and size properties
2041*7c478bd9Sstevel@tonic-gate  * to the devinfo node it is passed as an argument.
2042*7c478bd9Sstevel@tonic-gate  */
2043*7c478bd9Sstevel@tonic-gate static int
2044*7c478bd9Sstevel@tonic-gate add_cacheent_props(void *arg, const struct cachetab *ct)
2045*7c478bd9Sstevel@tonic-gate {
2046*7c478bd9Sstevel@tonic-gate 	dev_info_t *devi = arg;
2047*7c478bd9Sstevel@tonic-gate 
2048*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, ct->ct_label, assoc_str, ct->ct_assoc);
2049*7c478bd9Sstevel@tonic-gate 	if (ct->ct_line_size != 0)
2050*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, ct->ct_label, line_str,
2051*7c478bd9Sstevel@tonic-gate 		    ct->ct_line_size);
2052*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, ct->ct_label, size_str, ct->ct_size);
2053*7c478bd9Sstevel@tonic-gate 	return (0);
2054*7c478bd9Sstevel@tonic-gate }
2055*7c478bd9Sstevel@tonic-gate 
2056*7c478bd9Sstevel@tonic-gate static const char fully_assoc[] = "fully-associative?";
2057*7c478bd9Sstevel@tonic-gate 
2058*7c478bd9Sstevel@tonic-gate /*
2059*7c478bd9Sstevel@tonic-gate  * AMD style cache/tlb description
2060*7c478bd9Sstevel@tonic-gate  *
2061*7c478bd9Sstevel@tonic-gate  * Extended functions 5 and 6 directly describe properties of
2062*7c478bd9Sstevel@tonic-gate  * tlbs and various cache levels.
2063*7c478bd9Sstevel@tonic-gate  */
2064*7c478bd9Sstevel@tonic-gate static void
2065*7c478bd9Sstevel@tonic-gate add_amd_assoc(dev_info_t *devi, const char *label, uint_t assoc)
2066*7c478bd9Sstevel@tonic-gate {
2067*7c478bd9Sstevel@tonic-gate 	switch (assoc) {
2068*7c478bd9Sstevel@tonic-gate 	case 0:	/* reserved; ignore */
2069*7c478bd9Sstevel@tonic-gate 		break;
2070*7c478bd9Sstevel@tonic-gate 	default:
2071*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, assoc_str, assoc);
2072*7c478bd9Sstevel@tonic-gate 		break;
2073*7c478bd9Sstevel@tonic-gate 	case 0xff:
2074*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, fully_assoc, 1);
2075*7c478bd9Sstevel@tonic-gate 		break;
2076*7c478bd9Sstevel@tonic-gate 	}
2077*7c478bd9Sstevel@tonic-gate }
2078*7c478bd9Sstevel@tonic-gate 
2079*7c478bd9Sstevel@tonic-gate static void
2080*7c478bd9Sstevel@tonic-gate add_amd_tlb(dev_info_t *devi, const char *label, uint_t assoc, uint_t size)
2081*7c478bd9Sstevel@tonic-gate {
2082*7c478bd9Sstevel@tonic-gate 	if (size == 0)
2083*7c478bd9Sstevel@tonic-gate 		return;
2084*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, size_str, size);
2085*7c478bd9Sstevel@tonic-gate 	add_amd_assoc(devi, label, assoc);
2086*7c478bd9Sstevel@tonic-gate }
2087*7c478bd9Sstevel@tonic-gate 
2088*7c478bd9Sstevel@tonic-gate static void
2089*7c478bd9Sstevel@tonic-gate add_amd_cache(dev_info_t *devi, const char *label,
2090*7c478bd9Sstevel@tonic-gate     uint_t size, uint_t assoc, uint_t lines_per_tag, uint_t line_size)
2091*7c478bd9Sstevel@tonic-gate {
2092*7c478bd9Sstevel@tonic-gate 	if (size == 0 || line_size == 0)
2093*7c478bd9Sstevel@tonic-gate 		return;
2094*7c478bd9Sstevel@tonic-gate 	add_amd_assoc(devi, label, assoc);
2095*7c478bd9Sstevel@tonic-gate 	/*
2096*7c478bd9Sstevel@tonic-gate 	 * Most AMD parts have a sectored cache. Multiple cache lines are
2097*7c478bd9Sstevel@tonic-gate 	 * associated with each tag. A sector consists of all cache lines
2098*7c478bd9Sstevel@tonic-gate 	 * associated with a tag. For example, the AMD K6-III has a sector
2099*7c478bd9Sstevel@tonic-gate 	 * size of 2 cache lines per tag.
2100*7c478bd9Sstevel@tonic-gate 	 */
2101*7c478bd9Sstevel@tonic-gate 	if (lines_per_tag != 0)
2102*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, "lines-per-tag", lines_per_tag);
2103*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, line_str, line_size);
2104*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, size_str, size * 1024);
2105*7c478bd9Sstevel@tonic-gate }
2106*7c478bd9Sstevel@tonic-gate 
2107*7c478bd9Sstevel@tonic-gate static void
2108*7c478bd9Sstevel@tonic-gate add_amd_l2_assoc(dev_info_t *devi, const char *label, uint_t assoc)
2109*7c478bd9Sstevel@tonic-gate {
2110*7c478bd9Sstevel@tonic-gate 	switch (assoc) {
2111*7c478bd9Sstevel@tonic-gate 	case 0:	/* off */
2112*7c478bd9Sstevel@tonic-gate 		break;
2113*7c478bd9Sstevel@tonic-gate 	case 1:
2114*7c478bd9Sstevel@tonic-gate 	case 2:
2115*7c478bd9Sstevel@tonic-gate 	case 4:
2116*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, assoc_str, assoc);
2117*7c478bd9Sstevel@tonic-gate 		break;
2118*7c478bd9Sstevel@tonic-gate 	case 6:
2119*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, assoc_str, 8);
2120*7c478bd9Sstevel@tonic-gate 		break;
2121*7c478bd9Sstevel@tonic-gate 	case 8:
2122*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, assoc_str, 16);
2123*7c478bd9Sstevel@tonic-gate 		break;
2124*7c478bd9Sstevel@tonic-gate 	case 0xf:
2125*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, fully_assoc, 1);
2126*7c478bd9Sstevel@tonic-gate 		break;
2127*7c478bd9Sstevel@tonic-gate 	default: /* reserved; ignore */
2128*7c478bd9Sstevel@tonic-gate 		break;
2129*7c478bd9Sstevel@tonic-gate 	}
2130*7c478bd9Sstevel@tonic-gate }
2131*7c478bd9Sstevel@tonic-gate 
2132*7c478bd9Sstevel@tonic-gate static void
2133*7c478bd9Sstevel@tonic-gate add_amd_l2_tlb(dev_info_t *devi, const char *label, uint_t assoc, uint_t size)
2134*7c478bd9Sstevel@tonic-gate {
2135*7c478bd9Sstevel@tonic-gate 	if (size == 0 || assoc == 0)
2136*7c478bd9Sstevel@tonic-gate 		return;
2137*7c478bd9Sstevel@tonic-gate 	add_amd_l2_assoc(devi, label, assoc);
2138*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, size_str, size);
2139*7c478bd9Sstevel@tonic-gate }
2140*7c478bd9Sstevel@tonic-gate 
2141*7c478bd9Sstevel@tonic-gate static void
2142*7c478bd9Sstevel@tonic-gate add_amd_l2_cache(dev_info_t *devi, const char *label,
2143*7c478bd9Sstevel@tonic-gate     uint_t size, uint_t assoc, uint_t lines_per_tag, uint_t line_size)
2144*7c478bd9Sstevel@tonic-gate {
2145*7c478bd9Sstevel@tonic-gate 	if (size == 0 || assoc == 0 || line_size == 0)
2146*7c478bd9Sstevel@tonic-gate 		return;
2147*7c478bd9Sstevel@tonic-gate 	add_amd_l2_assoc(devi, label, assoc);
2148*7c478bd9Sstevel@tonic-gate 	if (lines_per_tag != 0)
2149*7c478bd9Sstevel@tonic-gate 		add_cache_prop(devi, label, "lines-per-tag", lines_per_tag);
2150*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, line_str, line_size);
2151*7c478bd9Sstevel@tonic-gate 	add_cache_prop(devi, label, size_str, size * 1024);
2152*7c478bd9Sstevel@tonic-gate }
2153*7c478bd9Sstevel@tonic-gate 
2154*7c478bd9Sstevel@tonic-gate static void
2155*7c478bd9Sstevel@tonic-gate amd_cache_info(struct cpuid_info *cpi, dev_info_t *devi)
2156*7c478bd9Sstevel@tonic-gate {
2157*7c478bd9Sstevel@tonic-gate 	struct cpuidr *cp;
2158*7c478bd9Sstevel@tonic-gate 
2159*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax < 0x80000005)
2160*7c478bd9Sstevel@tonic-gate 		return;
2161*7c478bd9Sstevel@tonic-gate 	cp = &cpi->cpi_extd[5];
2162*7c478bd9Sstevel@tonic-gate 
2163*7c478bd9Sstevel@tonic-gate 	/*
2164*7c478bd9Sstevel@tonic-gate 	 * 4M/2M L1 TLB configuration
2165*7c478bd9Sstevel@tonic-gate 	 *
2166*7c478bd9Sstevel@tonic-gate 	 * We report the size for 2M pages because AMD uses two
2167*7c478bd9Sstevel@tonic-gate 	 * TLB entries for one 4M page.
2168*7c478bd9Sstevel@tonic-gate 	 */
2169*7c478bd9Sstevel@tonic-gate 	add_amd_tlb(devi, "dtlb-2M",
2170*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_eax, 31, 24), BITX(cp->cp_eax, 23, 16));
2171*7c478bd9Sstevel@tonic-gate 	add_amd_tlb(devi, "itlb-2M",
2172*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_eax, 15, 8), BITX(cp->cp_eax, 7, 0));
2173*7c478bd9Sstevel@tonic-gate 
2174*7c478bd9Sstevel@tonic-gate 	/*
2175*7c478bd9Sstevel@tonic-gate 	 * 4K L1 TLB configuration
2176*7c478bd9Sstevel@tonic-gate 	 */
2177*7c478bd9Sstevel@tonic-gate 
2178*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2179*7c478bd9Sstevel@tonic-gate 		uint_t nentries;
2180*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
2181*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family >= 5) {
2182*7c478bd9Sstevel@tonic-gate 			/*
2183*7c478bd9Sstevel@tonic-gate 			 * Crusoe processors have 256 TLB entries, but
2184*7c478bd9Sstevel@tonic-gate 			 * cpuid data format constrains them to only
2185*7c478bd9Sstevel@tonic-gate 			 * reporting 255 of them.
2186*7c478bd9Sstevel@tonic-gate 			 */
2187*7c478bd9Sstevel@tonic-gate 			if ((nentries = BITX(cp->cp_ebx, 23, 16)) == 255)
2188*7c478bd9Sstevel@tonic-gate 				nentries = 256;
2189*7c478bd9Sstevel@tonic-gate 			/*
2190*7c478bd9Sstevel@tonic-gate 			 * Crusoe processors also have a unified TLB
2191*7c478bd9Sstevel@tonic-gate 			 */
2192*7c478bd9Sstevel@tonic-gate 			add_amd_tlb(devi, "tlb-4K", BITX(cp->cp_ebx, 31, 24),
2193*7c478bd9Sstevel@tonic-gate 			    nentries);
2194*7c478bd9Sstevel@tonic-gate 			break;
2195*7c478bd9Sstevel@tonic-gate 		}
2196*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2197*7c478bd9Sstevel@tonic-gate 	default:
2198*7c478bd9Sstevel@tonic-gate 		add_amd_tlb(devi, itlb4k_str,
2199*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_ebx, 31, 24), BITX(cp->cp_ebx, 23, 16));
2200*7c478bd9Sstevel@tonic-gate 		add_amd_tlb(devi, dtlb4k_str,
2201*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_ebx, 15, 8), BITX(cp->cp_ebx, 7, 0));
2202*7c478bd9Sstevel@tonic-gate 		break;
2203*7c478bd9Sstevel@tonic-gate 	}
2204*7c478bd9Sstevel@tonic-gate 
2205*7c478bd9Sstevel@tonic-gate 	/*
2206*7c478bd9Sstevel@tonic-gate 	 * data L1 cache configuration
2207*7c478bd9Sstevel@tonic-gate 	 */
2208*7c478bd9Sstevel@tonic-gate 
2209*7c478bd9Sstevel@tonic-gate 	add_amd_cache(devi, l1_dcache_str,
2210*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_ecx, 31, 24), BITX(cp->cp_ecx, 23, 16),
2211*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_ecx, 15, 8), BITX(cp->cp_ecx, 7, 0));
2212*7c478bd9Sstevel@tonic-gate 
2213*7c478bd9Sstevel@tonic-gate 	/*
2214*7c478bd9Sstevel@tonic-gate 	 * code L1 cache configuration
2215*7c478bd9Sstevel@tonic-gate 	 */
2216*7c478bd9Sstevel@tonic-gate 
2217*7c478bd9Sstevel@tonic-gate 	add_amd_cache(devi, l1_icache_str,
2218*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_edx, 31, 24), BITX(cp->cp_edx, 23, 16),
2219*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_edx, 15, 8), BITX(cp->cp_edx, 7, 0));
2220*7c478bd9Sstevel@tonic-gate 
2221*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax < 0x80000006)
2222*7c478bd9Sstevel@tonic-gate 		return;
2223*7c478bd9Sstevel@tonic-gate 	cp = &cpi->cpi_extd[6];
2224*7c478bd9Sstevel@tonic-gate 
2225*7c478bd9Sstevel@tonic-gate 	/* Check for a unified L2 TLB for large pages */
2226*7c478bd9Sstevel@tonic-gate 
2227*7c478bd9Sstevel@tonic-gate 	if (BITX(cp->cp_eax, 31, 16) == 0)
2228*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-tlb-2M",
2229*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 15, 12), BITX(cp->cp_eax, 11, 0));
2230*7c478bd9Sstevel@tonic-gate 	else {
2231*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-dtlb-2M",
2232*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 31, 28), BITX(cp->cp_eax, 27, 16));
2233*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-itlb-2M",
2234*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 15, 12), BITX(cp->cp_eax, 11, 0));
2235*7c478bd9Sstevel@tonic-gate 	}
2236*7c478bd9Sstevel@tonic-gate 
2237*7c478bd9Sstevel@tonic-gate 	/* Check for a unified L2 TLB for 4K pages */
2238*7c478bd9Sstevel@tonic-gate 
2239*7c478bd9Sstevel@tonic-gate 	if (BITX(cp->cp_ebx, 31, 16) == 0) {
2240*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-tlb-4K",
2241*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 15, 12), BITX(cp->cp_eax, 11, 0));
2242*7c478bd9Sstevel@tonic-gate 	} else {
2243*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-dtlb-4K",
2244*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 31, 28), BITX(cp->cp_eax, 27, 16));
2245*7c478bd9Sstevel@tonic-gate 		add_amd_l2_tlb(devi, "l2-itlb-4K",
2246*7c478bd9Sstevel@tonic-gate 		    BITX(cp->cp_eax, 15, 12), BITX(cp->cp_eax, 11, 0));
2247*7c478bd9Sstevel@tonic-gate 	}
2248*7c478bd9Sstevel@tonic-gate 
2249*7c478bd9Sstevel@tonic-gate 	add_amd_l2_cache(devi, l2_cache_str,
2250*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_ecx, 31, 16), BITX(cp->cp_ecx, 15, 12),
2251*7c478bd9Sstevel@tonic-gate 	    BITX(cp->cp_ecx, 11, 8), BITX(cp->cp_ecx, 7, 0));
2252*7c478bd9Sstevel@tonic-gate }
2253*7c478bd9Sstevel@tonic-gate 
2254*7c478bd9Sstevel@tonic-gate /*
2255*7c478bd9Sstevel@tonic-gate  * There are two basic ways that the x86 world describes it cache
2256*7c478bd9Sstevel@tonic-gate  * and tlb architecture - Intel's way and AMD's way.
2257*7c478bd9Sstevel@tonic-gate  *
2258*7c478bd9Sstevel@tonic-gate  * Return which flavor of cache architecture we should use
2259*7c478bd9Sstevel@tonic-gate  */
2260*7c478bd9Sstevel@tonic-gate static int
2261*7c478bd9Sstevel@tonic-gate x86_which_cacheinfo(struct cpuid_info *cpi)
2262*7c478bd9Sstevel@tonic-gate {
2263*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2264*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2265*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_maxeax >= 2)
2266*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_Intel);
2267*7c478bd9Sstevel@tonic-gate 		break;
2268*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2269*7c478bd9Sstevel@tonic-gate 		/*
2270*7c478bd9Sstevel@tonic-gate 		 * The K5 model 1 was the first part from AMD that reported
2271*7c478bd9Sstevel@tonic-gate 		 * cache sizes via extended cpuid functions.
2272*7c478bd9Sstevel@tonic-gate 		 */
2273*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family > 5 ||
2274*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_family == 5 && cpi->cpi_model >= 1))
2275*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_AMD);
2276*7c478bd9Sstevel@tonic-gate 		break;
2277*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
2278*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_family >= 5)
2279*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_AMD);
2280*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2281*7c478bd9Sstevel@tonic-gate 	default:
2282*7c478bd9Sstevel@tonic-gate 		/*
2283*7c478bd9Sstevel@tonic-gate 		 * If they have extended CPU data for 0x80000005
2284*7c478bd9Sstevel@tonic-gate 		 * then we assume they have AMD-format cache
2285*7c478bd9Sstevel@tonic-gate 		 * information.
2286*7c478bd9Sstevel@tonic-gate 		 *
2287*7c478bd9Sstevel@tonic-gate 		 * If not, and the vendor happens to be Cyrix,
2288*7c478bd9Sstevel@tonic-gate 		 * then try our-Cyrix specific handler.
2289*7c478bd9Sstevel@tonic-gate 		 *
2290*7c478bd9Sstevel@tonic-gate 		 * If we're not Cyrix, then assume we're using Intel's
2291*7c478bd9Sstevel@tonic-gate 		 * table-driven format instead.
2292*7c478bd9Sstevel@tonic-gate 		 */
2293*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_xmaxeax >= 0x80000005)
2294*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_AMD);
2295*7c478bd9Sstevel@tonic-gate 		else if (cpi->cpi_vendor == X86_VENDOR_Cyrix)
2296*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_Cyrix);
2297*7c478bd9Sstevel@tonic-gate 		else if (cpi->cpi_maxeax >= 2)
2298*7c478bd9Sstevel@tonic-gate 			return (X86_VENDOR_Intel);
2299*7c478bd9Sstevel@tonic-gate 		break;
2300*7c478bd9Sstevel@tonic-gate 	}
2301*7c478bd9Sstevel@tonic-gate 	return (-1);
2302*7c478bd9Sstevel@tonic-gate }
2303*7c478bd9Sstevel@tonic-gate 
2304*7c478bd9Sstevel@tonic-gate /*
2305*7c478bd9Sstevel@tonic-gate  * create a node for the given cpu under the prom root node.
2306*7c478bd9Sstevel@tonic-gate  * Also, create a cpu node in the device tree.
2307*7c478bd9Sstevel@tonic-gate  */
2308*7c478bd9Sstevel@tonic-gate static dev_info_t *cpu_nex_devi = NULL;
2309*7c478bd9Sstevel@tonic-gate static kmutex_t cpu_node_lock;
2310*7c478bd9Sstevel@tonic-gate 
2311*7c478bd9Sstevel@tonic-gate /*
2312*7c478bd9Sstevel@tonic-gate  * Called from post_startup() and mp_startup()
2313*7c478bd9Sstevel@tonic-gate  */
2314*7c478bd9Sstevel@tonic-gate void
2315*7c478bd9Sstevel@tonic-gate add_cpunode2devtree(processorid_t cpu_id, struct cpuid_info *cpi)
2316*7c478bd9Sstevel@tonic-gate {
2317*7c478bd9Sstevel@tonic-gate 	dev_info_t *cpu_devi;
2318*7c478bd9Sstevel@tonic-gate 	int create;
2319*7c478bd9Sstevel@tonic-gate 
2320*7c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_node_lock);
2321*7c478bd9Sstevel@tonic-gate 
2322*7c478bd9Sstevel@tonic-gate 	/*
2323*7c478bd9Sstevel@tonic-gate 	 * create a nexus node for all cpus identified as 'cpu_id' under
2324*7c478bd9Sstevel@tonic-gate 	 * the root node.
2325*7c478bd9Sstevel@tonic-gate 	 */
2326*7c478bd9Sstevel@tonic-gate 	if (cpu_nex_devi == NULL) {
2327*7c478bd9Sstevel@tonic-gate 		if (ndi_devi_alloc(ddi_root_node(), "cpus",
2328*7c478bd9Sstevel@tonic-gate 		    (dnode_t)DEVI_SID_NODEID, &cpu_nex_devi) != NDI_SUCCESS) {
2329*7c478bd9Sstevel@tonic-gate 			mutex_exit(&cpu_node_lock);
2330*7c478bd9Sstevel@tonic-gate 			return;
2331*7c478bd9Sstevel@tonic-gate 		}
2332*7c478bd9Sstevel@tonic-gate 		(void) ndi_devi_online(cpu_nex_devi, 0);
2333*7c478bd9Sstevel@tonic-gate 	}
2334*7c478bd9Sstevel@tonic-gate 
2335*7c478bd9Sstevel@tonic-gate 	/*
2336*7c478bd9Sstevel@tonic-gate 	 * create a child node for cpu identified as 'cpu_id'
2337*7c478bd9Sstevel@tonic-gate 	 */
2338*7c478bd9Sstevel@tonic-gate 	cpu_devi = ddi_add_child(cpu_nex_devi, "cpu", DEVI_SID_NODEID,
2339*7c478bd9Sstevel@tonic-gate 		cpu_id);
2340*7c478bd9Sstevel@tonic-gate 	if (cpu_devi == NULL) {
2341*7c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_node_lock);
2342*7c478bd9Sstevel@tonic-gate 		return;
2343*7c478bd9Sstevel@tonic-gate 	}
2344*7c478bd9Sstevel@tonic-gate 
2345*7c478bd9Sstevel@tonic-gate 	/* device_type */
2346*7c478bd9Sstevel@tonic-gate 
2347*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_string(DDI_DEV_T_NONE, cpu_devi,
2348*7c478bd9Sstevel@tonic-gate 	    "device_type", "cpu");
2349*7c478bd9Sstevel@tonic-gate 
2350*7c478bd9Sstevel@tonic-gate 	/* reg */
2351*7c478bd9Sstevel@tonic-gate 
2352*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2353*7c478bd9Sstevel@tonic-gate 	    "reg", cpu_id);
2354*7c478bd9Sstevel@tonic-gate 
2355*7c478bd9Sstevel@tonic-gate 	/* cpu-mhz, and clock-frequency */
2356*7c478bd9Sstevel@tonic-gate 
2357*7c478bd9Sstevel@tonic-gate 	if (cpu_freq > 0) {
2358*7c478bd9Sstevel@tonic-gate 		long long mul;
2359*7c478bd9Sstevel@tonic-gate 
2360*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2361*7c478bd9Sstevel@tonic-gate 		    "cpu-mhz", cpu_freq);
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate 		if ((mul = cpu_freq * 1000000LL) <= INT_MAX)
2364*7c478bd9Sstevel@tonic-gate 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2365*7c478bd9Sstevel@tonic-gate 			    "clock-frequency", (int)mul);
2366*7c478bd9Sstevel@tonic-gate 	}
2367*7c478bd9Sstevel@tonic-gate 
2368*7c478bd9Sstevel@tonic-gate 	(void) ndi_devi_online(cpu_devi, 0);
2369*7c478bd9Sstevel@tonic-gate 
2370*7c478bd9Sstevel@tonic-gate 	if ((x86_feature & X86_CPUID) == 0) {
2371*7c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_node_lock);
2372*7c478bd9Sstevel@tonic-gate 		return;
2373*7c478bd9Sstevel@tonic-gate 	}
2374*7c478bd9Sstevel@tonic-gate 
2375*7c478bd9Sstevel@tonic-gate 	/* vendor-id */
2376*7c478bd9Sstevel@tonic-gate 
2377*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_string(DDI_DEV_T_NONE, cpu_devi,
2378*7c478bd9Sstevel@tonic-gate 		"vendor-id", cpi->cpi_vendorstr);
2379*7c478bd9Sstevel@tonic-gate 
2380*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_maxeax == 0) {
2381*7c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_node_lock);
2382*7c478bd9Sstevel@tonic-gate 		return;
2383*7c478bd9Sstevel@tonic-gate 	}
2384*7c478bd9Sstevel@tonic-gate 
2385*7c478bd9Sstevel@tonic-gate 	/*
2386*7c478bd9Sstevel@tonic-gate 	 * family, model, and step
2387*7c478bd9Sstevel@tonic-gate 	 */
2388*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2389*7c478bd9Sstevel@tonic-gate 		"family", CPI_FAMILY(cpi));
2390*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2391*7c478bd9Sstevel@tonic-gate 		"cpu-model", CPI_MODEL(cpi));
2392*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2393*7c478bd9Sstevel@tonic-gate 		"stepping-id", CPI_STEP(cpi));
2394*7c478bd9Sstevel@tonic-gate 
2395*7c478bd9Sstevel@tonic-gate 	/* type */
2396*7c478bd9Sstevel@tonic-gate 
2397*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2398*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2399*7c478bd9Sstevel@tonic-gate 		create = 1;
2400*7c478bd9Sstevel@tonic-gate 		break;
2401*7c478bd9Sstevel@tonic-gate 	default:
2402*7c478bd9Sstevel@tonic-gate 		create = 0;
2403*7c478bd9Sstevel@tonic-gate 		break;
2404*7c478bd9Sstevel@tonic-gate 	}
2405*7c478bd9Sstevel@tonic-gate 	if (create)
2406*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2407*7c478bd9Sstevel@tonic-gate 			"type", CPI_TYPE(cpi));
2408*7c478bd9Sstevel@tonic-gate 
2409*7c478bd9Sstevel@tonic-gate 	/* ext-family */
2410*7c478bd9Sstevel@tonic-gate 
2411*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2412*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2413*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2414*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_family >= 0xf;
2415*7c478bd9Sstevel@tonic-gate 		break;
2416*7c478bd9Sstevel@tonic-gate 	default:
2417*7c478bd9Sstevel@tonic-gate 		create = 0;
2418*7c478bd9Sstevel@tonic-gate 		break;
2419*7c478bd9Sstevel@tonic-gate 	}
2420*7c478bd9Sstevel@tonic-gate 	if (create)
2421*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2422*7c478bd9Sstevel@tonic-gate 		    "ext-family", CPI_FAMILY_XTD(cpi));
2423*7c478bd9Sstevel@tonic-gate 
2424*7c478bd9Sstevel@tonic-gate 	/* ext-model */
2425*7c478bd9Sstevel@tonic-gate 
2426*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2427*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2428*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2429*7c478bd9Sstevel@tonic-gate 		create = CPI_MODEL(cpi) == 0xf;
2430*7c478bd9Sstevel@tonic-gate 		break;
2431*7c478bd9Sstevel@tonic-gate 	default:
2432*7c478bd9Sstevel@tonic-gate 		create = 0;
2433*7c478bd9Sstevel@tonic-gate 		break;
2434*7c478bd9Sstevel@tonic-gate 	}
2435*7c478bd9Sstevel@tonic-gate 	if (create)
2436*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2437*7c478bd9Sstevel@tonic-gate 			"ext-model", CPI_MODEL_XTD(cpi));
2438*7c478bd9Sstevel@tonic-gate 
2439*7c478bd9Sstevel@tonic-gate 	/* generation */
2440*7c478bd9Sstevel@tonic-gate 
2441*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2442*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2443*7c478bd9Sstevel@tonic-gate 		/*
2444*7c478bd9Sstevel@tonic-gate 		 * AMD K5 model 1 was the first part to support this
2445*7c478bd9Sstevel@tonic-gate 		 */
2446*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_xmaxeax >= 0x80000001;
2447*7c478bd9Sstevel@tonic-gate 		break;
2448*7c478bd9Sstevel@tonic-gate 	default:
2449*7c478bd9Sstevel@tonic-gate 		create = 0;
2450*7c478bd9Sstevel@tonic-gate 		break;
2451*7c478bd9Sstevel@tonic-gate 	}
2452*7c478bd9Sstevel@tonic-gate 	if (create)
2453*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2454*7c478bd9Sstevel@tonic-gate 		    "generation", BITX((cpi)->cpi_extd[1].cp_eax, 11, 8));
2455*7c478bd9Sstevel@tonic-gate 
2456*7c478bd9Sstevel@tonic-gate 	/* brand-id */
2457*7c478bd9Sstevel@tonic-gate 
2458*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2459*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2460*7c478bd9Sstevel@tonic-gate 		/*
2461*7c478bd9Sstevel@tonic-gate 		 * brand id first appeared on Pentium III Xeon model 8,
2462*7c478bd9Sstevel@tonic-gate 		 * and Celeron model 8 processors and Opteron
2463*7c478bd9Sstevel@tonic-gate 		 */
2464*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_family > 6 ||
2465*7c478bd9Sstevel@tonic-gate 		    (cpi->cpi_family == 6 && cpi->cpi_model >= 8);
2466*7c478bd9Sstevel@tonic-gate 		break;
2467*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2468*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_family >= 0xf;
2469*7c478bd9Sstevel@tonic-gate 		break;
2470*7c478bd9Sstevel@tonic-gate 	default:
2471*7c478bd9Sstevel@tonic-gate 		create = 0;
2472*7c478bd9Sstevel@tonic-gate 		break;
2473*7c478bd9Sstevel@tonic-gate 	}
2474*7c478bd9Sstevel@tonic-gate 	if (create && cpi->cpi_brandid != 0) {
2475*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2476*7c478bd9Sstevel@tonic-gate 		    "brand-id", cpi->cpi_brandid);
2477*7c478bd9Sstevel@tonic-gate 	}
2478*7c478bd9Sstevel@tonic-gate 
2479*7c478bd9Sstevel@tonic-gate 	/* chunks, and apic-id */
2480*7c478bd9Sstevel@tonic-gate 
2481*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2482*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2483*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2484*7c478bd9Sstevel@tonic-gate 		/*
2485*7c478bd9Sstevel@tonic-gate 		 * first available on Pentium IV and Opteron (K8)
2486*7c478bd9Sstevel@tonic-gate 		 */
2487*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_family >= 0xf;
2488*7c478bd9Sstevel@tonic-gate 		break;
2489*7c478bd9Sstevel@tonic-gate 	default:
2490*7c478bd9Sstevel@tonic-gate 		create = 0;
2491*7c478bd9Sstevel@tonic-gate 		break;
2492*7c478bd9Sstevel@tonic-gate 	}
2493*7c478bd9Sstevel@tonic-gate 	if (create) {
2494*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2495*7c478bd9Sstevel@tonic-gate 			"chunks", CPI_CHUNKS(cpi));
2496*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2497*7c478bd9Sstevel@tonic-gate 			"apic-id", CPI_APIC_ID(cpi));
2498*7c478bd9Sstevel@tonic-gate 		if (cpi->cpi_chipid >= 0)
2499*7c478bd9Sstevel@tonic-gate 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2500*7c478bd9Sstevel@tonic-gate 			    "chip#", cpi->cpi_chipid);
2501*7c478bd9Sstevel@tonic-gate 	}
2502*7c478bd9Sstevel@tonic-gate 
2503*7c478bd9Sstevel@tonic-gate 	/* cpuid-features */
2504*7c478bd9Sstevel@tonic-gate 
2505*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2506*7c478bd9Sstevel@tonic-gate 	    "cpuid-features", CPI_FEATURES_EDX(cpi));
2507*7c478bd9Sstevel@tonic-gate 
2508*7c478bd9Sstevel@tonic-gate 
2509*7c478bd9Sstevel@tonic-gate 	/* cpuid-features-ecx */
2510*7c478bd9Sstevel@tonic-gate 
2511*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2512*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2513*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_family >= 0xf;
2514*7c478bd9Sstevel@tonic-gate 		break;
2515*7c478bd9Sstevel@tonic-gate 	default:
2516*7c478bd9Sstevel@tonic-gate 		create = 0;
2517*7c478bd9Sstevel@tonic-gate 		break;
2518*7c478bd9Sstevel@tonic-gate 	}
2519*7c478bd9Sstevel@tonic-gate 	if (create)
2520*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2521*7c478bd9Sstevel@tonic-gate 		    "cpuid-features-ecx", CPI_FEATURES_ECX(cpi));
2522*7c478bd9Sstevel@tonic-gate 
2523*7c478bd9Sstevel@tonic-gate 	/* ext-cpuid-features */
2524*7c478bd9Sstevel@tonic-gate 
2525*7c478bd9Sstevel@tonic-gate 	switch (cpi->cpi_vendor) {
2526*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2527*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
2528*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_TM:
2529*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Centaur:
2530*7c478bd9Sstevel@tonic-gate 		/*
2531*7c478bd9Sstevel@tonic-gate 		 * The extended cpuid features are not relevant on
2532*7c478bd9Sstevel@tonic-gate 		 * Intel but are available from the AMD K5 model 1
2533*7c478bd9Sstevel@tonic-gate 		 * and most Cyrix GXm and later.
2534*7c478bd9Sstevel@tonic-gate 		 */
2535*7c478bd9Sstevel@tonic-gate 		create = cpi->cpi_xmaxeax >= 0x80000001;
2536*7c478bd9Sstevel@tonic-gate 		break;
2537*7c478bd9Sstevel@tonic-gate 	default:
2538*7c478bd9Sstevel@tonic-gate 		create = 0;
2539*7c478bd9Sstevel@tonic-gate 		break;
2540*7c478bd9Sstevel@tonic-gate 	}
2541*7c478bd9Sstevel@tonic-gate 	if (create)
2542*7c478bd9Sstevel@tonic-gate 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, cpu_devi,
2543*7c478bd9Sstevel@tonic-gate 			"ext-cpuid-features", CPI_FEATURES_XTD_EDX(cpi));
2544*7c478bd9Sstevel@tonic-gate 
2545*7c478bd9Sstevel@tonic-gate 	/*
2546*7c478bd9Sstevel@tonic-gate 	 * Brand String first appeared in Intel Pentium IV, AMD K5
2547*7c478bd9Sstevel@tonic-gate 	 * model 1, and Cyrix GXm.  On earlier models we try and
2548*7c478bd9Sstevel@tonic-gate 	 * simulate something similar .. so this string should always
2549*7c478bd9Sstevel@tonic-gate 	 * same -something- about the processor, however lame.
2550*7c478bd9Sstevel@tonic-gate 	 */
2551*7c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_string(DDI_DEV_T_NONE, cpu_devi,
2552*7c478bd9Sstevel@tonic-gate 	    "brand-string", cpi->cpi_brandstr);
2553*7c478bd9Sstevel@tonic-gate 
2554*7c478bd9Sstevel@tonic-gate 	/*
2555*7c478bd9Sstevel@tonic-gate 	 * Finally, cache and tlb information
2556*7c478bd9Sstevel@tonic-gate 	 */
2557*7c478bd9Sstevel@tonic-gate 	switch (x86_which_cacheinfo(cpi)) {
2558*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2559*7c478bd9Sstevel@tonic-gate 		intel_walk_cacheinfo(cpi, cpu_devi, add_cacheent_props);
2560*7c478bd9Sstevel@tonic-gate 		break;
2561*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
2562*7c478bd9Sstevel@tonic-gate 		cyrix_walk_cacheinfo(cpi, cpu_devi, add_cacheent_props);
2563*7c478bd9Sstevel@tonic-gate 		break;
2564*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2565*7c478bd9Sstevel@tonic-gate 		amd_cache_info(cpi, cpu_devi);
2566*7c478bd9Sstevel@tonic-gate 		break;
2567*7c478bd9Sstevel@tonic-gate 	default:
2568*7c478bd9Sstevel@tonic-gate 		break;
2569*7c478bd9Sstevel@tonic-gate 	}
2570*7c478bd9Sstevel@tonic-gate 
2571*7c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_node_lock);
2572*7c478bd9Sstevel@tonic-gate }
2573*7c478bd9Sstevel@tonic-gate 
2574*7c478bd9Sstevel@tonic-gate struct l2info {
2575*7c478bd9Sstevel@tonic-gate 	int *l2i_csz;
2576*7c478bd9Sstevel@tonic-gate 	int *l2i_lsz;
2577*7c478bd9Sstevel@tonic-gate 	int *l2i_assoc;
2578*7c478bd9Sstevel@tonic-gate 	int l2i_ret;
2579*7c478bd9Sstevel@tonic-gate };
2580*7c478bd9Sstevel@tonic-gate 
2581*7c478bd9Sstevel@tonic-gate /*
2582*7c478bd9Sstevel@tonic-gate  * A cacheinfo walker that fetches the size, line-size and associativity
2583*7c478bd9Sstevel@tonic-gate  * of the L2 cache
2584*7c478bd9Sstevel@tonic-gate  */
2585*7c478bd9Sstevel@tonic-gate static int
2586*7c478bd9Sstevel@tonic-gate intel_l2cinfo(void *arg, const struct cachetab *ct)
2587*7c478bd9Sstevel@tonic-gate {
2588*7c478bd9Sstevel@tonic-gate 	struct l2info *l2i = arg;
2589*7c478bd9Sstevel@tonic-gate 	int *ip;
2590*7c478bd9Sstevel@tonic-gate 
2591*7c478bd9Sstevel@tonic-gate 	if (ct->ct_label != l2_cache_str &&
2592*7c478bd9Sstevel@tonic-gate 	    ct->ct_label != sl2_cache_str)
2593*7c478bd9Sstevel@tonic-gate 		return (0);	/* not an L2 -- keep walking */
2594*7c478bd9Sstevel@tonic-gate 
2595*7c478bd9Sstevel@tonic-gate 	if ((ip = l2i->l2i_csz) != NULL)
2596*7c478bd9Sstevel@tonic-gate 		*ip = ct->ct_size;
2597*7c478bd9Sstevel@tonic-gate 	if ((ip = l2i->l2i_lsz) != NULL)
2598*7c478bd9Sstevel@tonic-gate 		*ip = ct->ct_line_size;
2599*7c478bd9Sstevel@tonic-gate 	if ((ip = l2i->l2i_assoc) != NULL)
2600*7c478bd9Sstevel@tonic-gate 		*ip = ct->ct_assoc;
2601*7c478bd9Sstevel@tonic-gate 	l2i->l2i_ret = ct->ct_size;
2602*7c478bd9Sstevel@tonic-gate 	return (1);		/* was an L2 -- terminate walk */
2603*7c478bd9Sstevel@tonic-gate }
2604*7c478bd9Sstevel@tonic-gate 
2605*7c478bd9Sstevel@tonic-gate static void
2606*7c478bd9Sstevel@tonic-gate amd_l2cacheinfo(struct cpuid_info *cpi, struct l2info *l2i)
2607*7c478bd9Sstevel@tonic-gate {
2608*7c478bd9Sstevel@tonic-gate 	struct cpuidr *cp;
2609*7c478bd9Sstevel@tonic-gate 	uint_t size, assoc;
2610*7c478bd9Sstevel@tonic-gate 	int *ip;
2611*7c478bd9Sstevel@tonic-gate 
2612*7c478bd9Sstevel@tonic-gate 	if (cpi->cpi_xmaxeax < 0x80000006)
2613*7c478bd9Sstevel@tonic-gate 		return;
2614*7c478bd9Sstevel@tonic-gate 	cp = &cpi->cpi_extd[6];
2615*7c478bd9Sstevel@tonic-gate 
2616*7c478bd9Sstevel@tonic-gate 	if ((assoc = BITX(cp->cp_ecx, 15, 12)) != 0 &&
2617*7c478bd9Sstevel@tonic-gate 	    (size = BITX(cp->cp_ecx, 31, 16)) != 0) {
2618*7c478bd9Sstevel@tonic-gate 		uint_t cachesz = size * 1024;
2619*7c478bd9Sstevel@tonic-gate 
2620*7c478bd9Sstevel@tonic-gate 
2621*7c478bd9Sstevel@tonic-gate 		if ((ip = l2i->l2i_csz) != NULL)
2622*7c478bd9Sstevel@tonic-gate 			*ip = cachesz;
2623*7c478bd9Sstevel@tonic-gate 		if ((ip = l2i->l2i_lsz) != NULL)
2624*7c478bd9Sstevel@tonic-gate 			*ip = BITX(cp->cp_ecx, 7, 0);
2625*7c478bd9Sstevel@tonic-gate 		if ((ip = l2i->l2i_assoc) != NULL)
2626*7c478bd9Sstevel@tonic-gate 			*ip = assoc;
2627*7c478bd9Sstevel@tonic-gate 		l2i->l2i_ret = cachesz;
2628*7c478bd9Sstevel@tonic-gate 	}
2629*7c478bd9Sstevel@tonic-gate }
2630*7c478bd9Sstevel@tonic-gate 
2631*7c478bd9Sstevel@tonic-gate int
2632*7c478bd9Sstevel@tonic-gate getl2cacheinfo(cpu_t *cpu, int *csz, int *lsz, int *assoc)
2633*7c478bd9Sstevel@tonic-gate {
2634*7c478bd9Sstevel@tonic-gate 	struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
2635*7c478bd9Sstevel@tonic-gate 	struct l2info __l2info, *l2i = &__l2info;
2636*7c478bd9Sstevel@tonic-gate 
2637*7c478bd9Sstevel@tonic-gate 	l2i->l2i_csz = csz;
2638*7c478bd9Sstevel@tonic-gate 	l2i->l2i_lsz = lsz;
2639*7c478bd9Sstevel@tonic-gate 	l2i->l2i_assoc = assoc;
2640*7c478bd9Sstevel@tonic-gate 	l2i->l2i_ret = -1;
2641*7c478bd9Sstevel@tonic-gate 
2642*7c478bd9Sstevel@tonic-gate 	switch (x86_which_cacheinfo(cpi)) {
2643*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Intel:
2644*7c478bd9Sstevel@tonic-gate 		intel_walk_cacheinfo(cpi, l2i, intel_l2cinfo);
2645*7c478bd9Sstevel@tonic-gate 		break;
2646*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_Cyrix:
2647*7c478bd9Sstevel@tonic-gate 		cyrix_walk_cacheinfo(cpi, l2i, intel_l2cinfo);
2648*7c478bd9Sstevel@tonic-gate 		break;
2649*7c478bd9Sstevel@tonic-gate 	case X86_VENDOR_AMD:
2650*7c478bd9Sstevel@tonic-gate 		amd_l2cacheinfo(cpi, l2i);
2651*7c478bd9Sstevel@tonic-gate 		break;
2652*7c478bd9Sstevel@tonic-gate 	default:
2653*7c478bd9Sstevel@tonic-gate 		break;
2654*7c478bd9Sstevel@tonic-gate 	}
2655*7c478bd9Sstevel@tonic-gate 	return (l2i->l2i_ret);
2656*7c478bd9Sstevel@tonic-gate }
2657