1/*
2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31#include <vm/vm_page.h>
32#include <pexpert/pexpert.h>
33
34#include <i386/cpuid.h>
35
36static	boolean_t	cpuid_dbg
37#if DEBUG
38				  = TRUE;
39#else
40				  = FALSE;
41#endif
42#define DBG(x...)			\
43	do {				\
44		if (cpuid_dbg)		\
45			kprintf(x);	\
46	} while (0)			\
47
48#define min(a,b) ((a) < (b) ? (a) : (b))
49#define quad(hi,lo)	(((uint64_t)(hi)) << 32 | (lo))
50
51/* Only for 32bit values */
52#define bit32(n)		(1U << (n))
53#define bitmask32(h,l)		((bit32(h)|(bit32(h)-1)) & ~(bit32(l)-1))
54#define bitfield32(x,h,l)	((((x) & bitmask32(h,l)) >> l))
55
56/*
57 * Leaf 2 cache descriptor encodings.
58 */
59typedef enum {
60	_NULL_,		/* NULL (empty) descriptor */
61	CACHE,		/* Cache */
62	TLB,		/* TLB */
63	STLB,		/* Shared second-level unified TLB */
64	PREFETCH	/* Prefetch size */
65} cpuid_leaf2_desc_type_t;
66
67typedef enum {
68	NA,		/* Not Applicable */
69	FULLY,		/* Fully-associative */
70	TRACE,		/* Trace Cache (P4 only) */
71	INST,		/* Instruction TLB */
72	DATA,		/* Data TLB */
73	DATA0,		/* Data TLB, 1st level */
74	DATA1,		/* Data TLB, 2nd level */
75	L1,		/* L1 (unified) cache */
76	L1_INST,	/* L1 Instruction cache */
77	L1_DATA,	/* L1 Data cache */
78	L2,		/* L2 (unified) cache */
79	L3,		/* L3 (unified) cache */
80	L2_2LINESECTOR,	/* L2 (unified) cache with 2 lines per sector */
81	L3_2LINESECTOR,	/* L3(unified) cache with 2 lines per sector */
82	SMALL,		/* Small page TLB */
83	LARGE,		/* Large page TLB */
84	BOTH		/* Small and Large page TLB */
85} cpuid_leaf2_qualifier_t;
86
87typedef struct cpuid_cache_descriptor {
88	uint8_t		value;		/* descriptor code */
89	uint8_t		type;		/* cpuid_leaf2_desc_type_t */
90	uint8_t		level;		/* level of cache/TLB hierachy */
91	uint8_t		ways;		/* wayness of cache */
92	uint16_t	size;		/* cachesize or TLB pagesize */
93	uint16_t	entries;	/* number of TLB entries or linesize */
94} cpuid_cache_descriptor_t;
95
96/*
97 * These multipliers are used to encode 1*K .. 64*M in a 16 bit size field
98 */
99#define	K	(1)
100#define	M	(1024)
101
102/*
103 * Intel cache descriptor table:
104 */
105static cpuid_cache_descriptor_t intel_cpuid_leaf2_descriptor_table[] = {
106//	-------------------------------------------------------
107//	value	type	level		ways	size	entries
108//	-------------------------------------------------------
109	{ 0x00,	_NULL_,	NA,		NA,	NA,	NA  },
110	{ 0x01,	TLB,	INST,		4,	SMALL,	32  },
111	{ 0x02,	TLB,	INST,		FULLY,	LARGE,	2   },
112	{ 0x03,	TLB,	DATA,		4,	SMALL,	64  },
113	{ 0x04,	TLB,	DATA,		4,	LARGE,	8   },
114	{ 0x05,	TLB,	DATA1,		4,	LARGE,	32  },
115	{ 0x06,	CACHE,	L1_INST,	4,	8*K,	32  },
116	{ 0x08,	CACHE,	L1_INST,	4,	16*K,	32  },
117	{ 0x09,	CACHE,	L1_INST,	4,	32*K,	64  },
118	{ 0x0A,	CACHE,	L1_DATA,	2,	8*K,	32  },
119	{ 0x0B,	TLB,	INST,		4,	LARGE,	4   },
120	{ 0x0C,	CACHE,	L1_DATA,	4,	16*K,	32  },
121	{ 0x0D,	CACHE,	L1_DATA,	4,	16*K,	64  },
122	{ 0x0E,	CACHE,	L1_DATA,	6,	24*K,	64  },
123	{ 0x21,	CACHE,	L2,		8,	256*K,	64  },
124	{ 0x22,	CACHE,	L3_2LINESECTOR,	4,	512*K,	64  },
125	{ 0x23,	CACHE,	L3_2LINESECTOR, 8,	1*M,	64  },
126	{ 0x25,	CACHE,	L3_2LINESECTOR,	8,	2*M,	64  },
127	{ 0x29,	CACHE,	L3_2LINESECTOR, 8,	4*M,	64  },
128	{ 0x2C,	CACHE,	L1_DATA,	8,	32*K,	64  },
129	{ 0x30,	CACHE,	L1_INST,	8,	32*K,	64  },
130	{ 0x40,	CACHE,	L2,		NA,	0,	NA  },
131	{ 0x41,	CACHE,	L2,		4,	128*K,	32  },
132	{ 0x42,	CACHE,	L2,		4,	256*K,	32  },
133	{ 0x43,	CACHE,	L2,		4,	512*K,	32  },
134	{ 0x44,	CACHE,	L2,		4,	1*M,	32  },
135	{ 0x45,	CACHE,	L2,		4,	2*M,	32  },
136	{ 0x46,	CACHE,	L3,		4,	4*M,	64  },
137	{ 0x47,	CACHE,	L3,		8,	8*M,	64  },
138	{ 0x48,	CACHE,	L2,		12, 	3*M,	64  },
139	{ 0x49,	CACHE,	L2,		16,	4*M,	64  },
140	{ 0x4A,	CACHE,	L3,		12, 	6*M,	64  },
141	{ 0x4B,	CACHE,	L3,		16,	8*M,	64  },
142	{ 0x4C,	CACHE,	L3,		12, 	12*M,	64  },
143	{ 0x4D,	CACHE,	L3,		16,	16*M,	64  },
144	{ 0x4E,	CACHE,	L2,		24,	6*M,	64  },
145	{ 0x4F,	TLB,	INST,		NA,	SMALL,	32  },
146	{ 0x50,	TLB,	INST,		NA,	BOTH,	64  },
147	{ 0x51,	TLB,	INST,		NA,	BOTH,	128 },
148	{ 0x52,	TLB,	INST,		NA,	BOTH,	256 },
149	{ 0x55,	TLB,	INST,		FULLY,	BOTH,	7   },
150	{ 0x56,	TLB,	DATA0,		4,	LARGE,	16  },
151	{ 0x57,	TLB,	DATA0,		4,	SMALL,	16  },
152	{ 0x59,	TLB,	DATA0,		FULLY,	SMALL,	16  },
153	{ 0x5A,	TLB,	DATA0,		4,	LARGE,	32  },
154	{ 0x5B,	TLB,	DATA,		NA,	BOTH,	64  },
155	{ 0x5C,	TLB,	DATA,		NA,	BOTH,	128 },
156	{ 0x5D,	TLB,	DATA,		NA,	BOTH,	256 },
157	{ 0x60,	CACHE,	L1,		16*K,	8,	64  },
158	{ 0x61,	CACHE,	L1,		4,	8*K,	64  },
159	{ 0x62,	CACHE,	L1,		4,	16*K,	64  },
160	{ 0x63,	CACHE,	L1,		4,	32*K,	64  },
161	{ 0x70,	CACHE,	TRACE,		8,	12*K,	NA  },
162	{ 0x71,	CACHE,	TRACE,		8,	16*K,	NA  },
163	{ 0x72,	CACHE,	TRACE,		8,	32*K,	NA  },
164	{ 0x76,	TLB,	INST,		NA,	BOTH,	8   },
165	{ 0x78,	CACHE,	L2,		4,	1*M,	64  },
166	{ 0x79,	CACHE,	L2_2LINESECTOR,	8,	128*K,	64  },
167	{ 0x7A,	CACHE,	L2_2LINESECTOR,	8,	256*K,	64  },
168	{ 0x7B,	CACHE,	L2_2LINESECTOR,	8,	512*K,	64  },
169	{ 0x7C,	CACHE,	L2_2LINESECTOR,	8,	1*M,	64  },
170	{ 0x7D,	CACHE,	L2,		8,	2*M,	64  },
171	{ 0x7F,	CACHE,	L2,		2,	512*K,	64  },
172	{ 0x80,	CACHE,	L2,		8,	512*K,	64  },
173	{ 0x82,	CACHE,	L2,		8,	256*K,	32  },
174	{ 0x83,	CACHE,	L2,		8,	512*K,	32  },
175	{ 0x84,	CACHE,	L2,		8,	1*M,	32  },
176	{ 0x85,	CACHE,	L2,		8,	2*M,	32  },
177	{ 0x86,	CACHE,	L2,		4,	512*K,	64  },
178	{ 0x87,	CACHE,	L2,		8,	1*M,	64  },
179	{ 0xB0,	TLB,	INST,		4,	SMALL,	128 },
180	{ 0xB1,	TLB,	INST,		4,	LARGE,	8   },
181	{ 0xB2,	TLB,	INST,		4,	SMALL,	64  },
182	{ 0xB3,	TLB,	DATA,		4,	SMALL,	128 },
183	{ 0xB4,	TLB,	DATA1,		4,	SMALL,	256 },
184	{ 0xB5,	TLB,	DATA1,		8,	SMALL,	64  },
185	{ 0xB6,	TLB,	DATA1,		8,	SMALL,	128 },
186	{ 0xBA,	TLB,	DATA1,		4,	BOTH,	64  },
187	{ 0xC1,	STLB,	DATA1,		8,	SMALL,	1024},
188	{ 0xCA,	STLB,	DATA1,		4,	SMALL,	512 },
189	{ 0xD0,	CACHE,	L3,		4,	512*K,	64  },
190	{ 0xD1,	CACHE,	L3,		4,	1*M,	64  },
191	{ 0xD2,	CACHE,	L3,		4,	2*M,	64  },
192	{ 0xD3,	CACHE,	L3,		4,	4*M,	64  },
193	{ 0xD4,	CACHE,	L3,		4,	8*M,	64  },
194	{ 0xD6,	CACHE,	L3,		8,	1*M,	64  },
195	{ 0xD7,	CACHE,	L3,		8,	2*M,	64  },
196	{ 0xD8,	CACHE,	L3,		8,	4*M,	64  },
197	{ 0xD9,	CACHE,	L3,		8,	8*M,	64  },
198	{ 0xDA,	CACHE,	L3,		8,	12*M,	64  },
199	{ 0xDC,	CACHE,	L3,		12, 	1536*K,	64  },
200	{ 0xDD,	CACHE,	L3,		12, 	3*M,	64  },
201	{ 0xDE,	CACHE,	L3,		12, 	6*M,	64  },
202	{ 0xDF,	CACHE,	L3,		12,	12*M,	64  },
203	{ 0xE0,	CACHE,	L3,		12,	18*M,	64  },
204	{ 0xE2,	CACHE,	L3,		16,	2*M,	64  },
205	{ 0xE3,	CACHE,	L3,		16,	4*M,	64  },
206	{ 0xE4,	CACHE,	L3,		16,	8*M,	64  },
207	{ 0xE5,	CACHE,	L3,		16,	16*M,	64  },
208	{ 0xE6,	CACHE,	L3,		16,	24*M,	64  },
209	{ 0xF0,	PREFETCH, NA,		NA,	64,	NA  },
210	{ 0xF1,	PREFETCH, NA,		NA,	128,	NA  },
211	{ 0xFF,	CACHE,  NA,		NA,	0,	NA  }
212};
213#define	INTEL_LEAF2_DESC_NUM (sizeof(intel_cpuid_leaf2_descriptor_table) / \
214				sizeof(cpuid_cache_descriptor_t))
215
216static inline cpuid_cache_descriptor_t *
217cpuid_leaf2_find(uint8_t value)
218{
219	unsigned int	i;
220
221	for (i = 0; i < INTEL_LEAF2_DESC_NUM; i++)
222		if (intel_cpuid_leaf2_descriptor_table[i].value == value)
223			return &intel_cpuid_leaf2_descriptor_table[i];
224	return NULL;
225}
226
227/*
228 * CPU identification routines.
229 */
230
231static i386_cpu_info_t	cpuid_cpu_info;
232static i386_cpu_info_t	*cpuid_cpu_infop = NULL;
233
234static void cpuid_fn(uint32_t selector, uint32_t *result)
235{
236	do_cpuid(selector, result);
237	DBG("cpuid_fn(0x%08x) eax:0x%08x ebx:0x%08x ecx:0x%08x edx:0x%08x\n",
238		selector, result[0], result[1], result[2], result[3]);
239}
240
241static const char *cache_type_str[LCACHE_MAX] = {
242	"Lnone", "L1I", "L1D", "L2U", "L3U"
243};
244
245/* this function is Intel-specific */
246static void
247cpuid_set_cache_info( i386_cpu_info_t * info_p )
248{
249	uint32_t	cpuid_result[4];
250	uint32_t	reg[4];
251	uint32_t	index;
252	uint32_t	linesizes[LCACHE_MAX];
253	unsigned int	i;
254	unsigned int	j;
255	boolean_t	cpuid_deterministic_supported = FALSE;
256
257	DBG("cpuid_set_cache_info(%p)\n", info_p);
258
259	bzero( linesizes, sizeof(linesizes) );
260
261	/* Get processor cache descriptor info using leaf 2.  We don't use
262	 * this internally, but must publish it for KEXTs.
263	 */
264	cpuid_fn(2, cpuid_result);
265	for (j = 0; j < 4; j++) {
266		if ((cpuid_result[j] >> 31) == 1) 	/* bit31 is validity */
267			continue;
268		((uint32_t *) info_p->cache_info)[j] = cpuid_result[j];
269	}
270	/* first byte gives number of cpuid calls to get all descriptors */
271	for (i = 1; i < info_p->cache_info[0]; i++) {
272		if (i*16 > sizeof(info_p->cache_info))
273			break;
274		cpuid_fn(2, cpuid_result);
275		for (j = 0; j < 4; j++) {
276			if ((cpuid_result[j] >> 31) == 1)
277				continue;
278			((uint32_t *) info_p->cache_info)[4*i+j] =
279				cpuid_result[j];
280		}
281	}
282
283	/*
284	 * Get cache info using leaf 4, the "deterministic cache parameters."
285	 * Most processors Mac OS X supports implement this flavor of CPUID.
286	 * Loop over each cache on the processor.
287	 */
288	cpuid_fn(0, cpuid_result);
289	if (cpuid_result[eax] >= 4)
290		cpuid_deterministic_supported = TRUE;
291
292	for (index = 0; cpuid_deterministic_supported; index++) {
293		cache_type_t	type = Lnone;
294		uint32_t	cache_type;
295		uint32_t	cache_level;
296		uint32_t	cache_sharing;
297		uint32_t	cache_linesize;
298		uint32_t	cache_sets;
299		uint32_t	cache_associativity;
300		uint32_t	cache_size;
301		uint32_t	cache_partitions;
302		uint32_t	colors;
303
304		reg[eax] = 4;		/* cpuid request 4 */
305		reg[ecx] = index;	/* index starting at 0 */
306		cpuid(reg);
307		DBG("cpuid(4) index=%d eax=0x%x\n", index, reg[eax]);
308		cache_type = bitfield32(reg[eax], 4, 0);
309		if (cache_type == 0)
310			break;		/* no more caches */
311		cache_level  		= bitfield32(reg[eax],  7,  5);
312		cache_sharing	 	= bitfield32(reg[eax], 25, 14) + 1;
313		info_p->cpuid_cores_per_package
314					= bitfield32(reg[eax], 31, 26) + 1;
315		cache_linesize		= bitfield32(reg[ebx], 11,  0) + 1;
316		cache_partitions	= bitfield32(reg[ebx], 21, 12) + 1;
317		cache_associativity	= bitfield32(reg[ebx], 31, 22) + 1;
318		cache_sets 		= bitfield32(reg[ecx], 31,  0) + 1;
319
320		/* Map type/levels returned by CPUID into cache_type_t */
321		switch (cache_level) {
322		case 1:
323			type = cache_type == 1 ? L1D :
324			       cache_type == 2 ? L1I :
325						 Lnone;
326			break;
327		case 2:
328			type = cache_type == 3 ? L2U :
329						 Lnone;
330			break;
331		case 3:
332			type = cache_type == 3 ? L3U :
333						 Lnone;
334			break;
335		default:
336			type = Lnone;
337		}
338
339		/* The total size of a cache is:
340		 *	( linesize * sets * associativity * partitions )
341		 */
342		if (type != Lnone) {
343			cache_size = cache_linesize * cache_sets *
344				     cache_associativity * cache_partitions;
345			info_p->cache_size[type] = cache_size;
346			info_p->cache_sharing[type] = cache_sharing;
347			info_p->cache_partitions[type] = cache_partitions;
348			linesizes[type] = cache_linesize;
349
350			DBG(" cache_size[%s]      : %d\n",
351			    cache_type_str[type], cache_size);
352			DBG(" cache_sharing[%s]   : %d\n",
353			    cache_type_str[type], cache_sharing);
354			DBG(" cache_partitions[%s]: %d\n",
355			    cache_type_str[type], cache_partitions);
356
357			/*
358			 * Overwrite associativity determined via
359			 * CPUID.0x80000006 -- this leaf is more
360			 * accurate
361			 */
362			if (type == L2U)
363				info_p->cpuid_cache_L2_associativity = cache_associativity;
364
365			/* Compute the number of page colors for this cache,
366			 * which is:
367			 *	( linesize * sets ) / page_size
368			 *
369			 * To help visualize this, consider two views of a
370			 * physical address.  To the cache, it is composed
371			 * of a line offset, a set selector, and a tag.
372			 * To VM, it is composed of a page offset, a page
373			 * color, and other bits in the pageframe number:
374			 *
375			 *           +-----------------+---------+--------+
376			 *  cache:   |       tag       |   set   | offset |
377			 *           +-----------------+---------+--------+
378			 *
379			 *           +-----------------+-------+----------+
380			 *  VM:      |    don't care   | color | pg offset|
381			 *           +-----------------+-------+----------+
382			 *
383			 * The color is those bits in (set+offset) not covered
384			 * by the page offset.
385			 */
386			 colors = ( cache_linesize * cache_sets ) >> 12;
387
388			 if ( colors > vm_cache_geometry_colors )
389				vm_cache_geometry_colors = colors;
390		}
391	}
392	DBG(" vm_cache_geometry_colors: %d\n", vm_cache_geometry_colors);
393
394	/*
395	 * If deterministic cache parameters are not available, use
396	 * something else
397	 */
398	if (info_p->cpuid_cores_per_package == 0) {
399		info_p->cpuid_cores_per_package = 1;
400
401		/* cpuid define in 1024 quantities */
402		info_p->cache_size[L2U] = info_p->cpuid_cache_size * 1024;
403		info_p->cache_sharing[L2U] = 1;
404		info_p->cache_partitions[L2U] = 1;
405
406		linesizes[L2U] = info_p->cpuid_cache_linesize;
407
408		DBG(" cache_size[L2U]      : %d\n",
409		    info_p->cache_size[L2U]);
410		DBG(" cache_sharing[L2U]   : 1\n");
411		DBG(" cache_partitions[L2U]: 1\n");
412		DBG(" linesizes[L2U]       : %d\n",
413		    info_p->cpuid_cache_linesize);
414	}
415
416	/*
417	 * What linesize to publish?  We use the L2 linesize if any,
418	 * else the L1D.
419	 */
420	if ( linesizes[L2U] )
421		info_p->cache_linesize = linesizes[L2U];
422	else if (linesizes[L1D])
423		info_p->cache_linesize = linesizes[L1D];
424	else panic("no linesize");
425	DBG(" cache_linesize    : %d\n", info_p->cache_linesize);
426
427	/*
428	 * Extract and publish TLB information from Leaf 2 descriptors.
429	 */
430	DBG(" %ld leaf2 descriptors:\n", sizeof(info_p->cache_info));
431	for (i = 1; i < sizeof(info_p->cache_info); i++) {
432		cpuid_cache_descriptor_t	*descp;
433		int				id;
434		int				level;
435		int				page;
436
437		DBG(" 0x%02x", info_p->cache_info[i]);
438		descp = cpuid_leaf2_find(info_p->cache_info[i]);
439		if (descp == NULL)
440			continue;
441
442		switch (descp->type) {
443		case TLB:
444			page = (descp->size == SMALL) ? TLB_SMALL : TLB_LARGE;
445			/* determine I or D: */
446			switch (descp->level) {
447			case INST:
448				id = TLB_INST;
449				break;
450			case DATA:
451			case DATA0:
452			case DATA1:
453				id = TLB_DATA;
454				break;
455			default:
456				continue;
457			}
458			/* determine level: */
459			switch (descp->level) {
460			case DATA1:
461				level = 1;
462				break;
463			default:
464				level = 0;
465			}
466			info_p->cpuid_tlb[id][page][level] = descp->entries;
467			break;
468		case STLB:
469			info_p->cpuid_stlb = descp->entries;
470		}
471	}
472	DBG("\n");
473}
474
475static void
476cpuid_set_generic_info(i386_cpu_info_t *info_p)
477{
478	uint32_t	reg[4];
479        char            str[128], *p;
480
481	DBG("cpuid_set_generic_info(%p)\n", info_p);
482
483	/* do cpuid 0 to get vendor */
484	cpuid_fn(0, reg);
485	info_p->cpuid_max_basic = reg[eax];
486	bcopy((char *)&reg[ebx], &info_p->cpuid_vendor[0], 4); /* ug */
487	bcopy((char *)&reg[ecx], &info_p->cpuid_vendor[8], 4);
488	bcopy((char *)&reg[edx], &info_p->cpuid_vendor[4], 4);
489	info_p->cpuid_vendor[12] = 0;
490
491	/* get extended cpuid results */
492	cpuid_fn(0x80000000, reg);
493	info_p->cpuid_max_ext = reg[eax];
494
495	/* check to see if we can get brand string */
496	if (info_p->cpuid_max_ext >= 0x80000004) {
497		/*
498		 * The brand string 48 bytes (max), guaranteed to
499		 * be NUL terminated.
500		 */
501		cpuid_fn(0x80000002, reg);
502		bcopy((char *)reg, &str[0], 16);
503		cpuid_fn(0x80000003, reg);
504		bcopy((char *)reg, &str[16], 16);
505		cpuid_fn(0x80000004, reg);
506		bcopy((char *)reg, &str[32], 16);
507		for (p = str; *p != '\0'; p++) {
508			if (*p != ' ') break;
509		}
510		strlcpy(info_p->cpuid_brand_string,
511			p, sizeof(info_p->cpuid_brand_string));
512
513                if (!strncmp(info_p->cpuid_brand_string, CPUID_STRING_UNKNOWN,
514			     min(sizeof(info_p->cpuid_brand_string),
515				 strlen(CPUID_STRING_UNKNOWN) + 1))) {
516                    /*
517                     * This string means we have a firmware-programmable brand string,
518                     * and the firmware couldn't figure out what sort of CPU we have.
519                     */
520                    info_p->cpuid_brand_string[0] = '\0';
521                }
522	}
523
524	/* Get cache and addressing info. */
525	if (info_p->cpuid_max_ext >= 0x80000006) {
526		uint32_t assoc;
527		cpuid_fn(0x80000006, reg);
528		info_p->cpuid_cache_linesize   = bitfield32(reg[ecx], 7, 0);
529		assoc = bitfield32(reg[ecx],15,12);
530		/*
531		 * L2 associativity is encoded, though in an insufficiently
532		 * descriptive fashion, e.g. 24-way is mapped to 16-way.
533		 * Represent a fully associative cache as 0xFFFF.
534		 * Overwritten by associativity as determined via CPUID.4
535		 * if available.
536		 */
537		if (assoc == 6)
538			assoc = 8;
539		else if (assoc == 8)
540			assoc = 16;
541		else if (assoc == 0xF)
542			assoc = 0xFFFF;
543		info_p->cpuid_cache_L2_associativity = assoc;
544		info_p->cpuid_cache_size       = bitfield32(reg[ecx],31,16);
545		cpuid_fn(0x80000008, reg);
546		info_p->cpuid_address_bits_physical =
547						 bitfield32(reg[eax], 7, 0);
548		info_p->cpuid_address_bits_virtual =
549						 bitfield32(reg[eax],15, 8);
550	}
551
552	/*
553	 * Get processor signature and decode
554	 * and bracket this with the approved procedure for reading the
555	 * the microcode version number a.k.a. signature a.k.a. BIOS ID
556	 */
557	wrmsr64(MSR_IA32_BIOS_SIGN_ID, 0);
558	cpuid_fn(1, reg);
559	info_p->cpuid_microcode_version =
560		(uint32_t) (rdmsr64(MSR_IA32_BIOS_SIGN_ID) >> 32);
561	info_p->cpuid_signature = reg[eax];
562	info_p->cpuid_stepping  = bitfield32(reg[eax],  3,  0);
563	info_p->cpuid_model     = bitfield32(reg[eax],  7,  4);
564	info_p->cpuid_family    = bitfield32(reg[eax], 11,  8);
565	info_p->cpuid_type      = bitfield32(reg[eax], 13, 12);
566	info_p->cpuid_extmodel  = bitfield32(reg[eax], 19, 16);
567	info_p->cpuid_extfamily = bitfield32(reg[eax], 27, 20);
568	info_p->cpuid_brand     = bitfield32(reg[ebx],  7,  0);
569	info_p->cpuid_features  = quad(reg[ecx], reg[edx]);
570
571	/* Get "processor flag"; necessary for microcode update matching */
572	info_p->cpuid_processor_flag = (rdmsr64(MSR_IA32_PLATFORM_ID)>> 50) & 0x7;
573
574	/* Fold extensions into family/model */
575	if (info_p->cpuid_family == 0x0f)
576		info_p->cpuid_family += info_p->cpuid_extfamily;
577	if (info_p->cpuid_family == 0x0f || info_p->cpuid_family == 0x06)
578		info_p->cpuid_model += (info_p->cpuid_extmodel << 4);
579
580	if (info_p->cpuid_features & CPUID_FEATURE_HTT)
581		info_p->cpuid_logical_per_package =
582				bitfield32(reg[ebx], 23, 16);
583	else
584		info_p->cpuid_logical_per_package = 1;
585
586	if (info_p->cpuid_max_ext >= 0x80000001) {
587		cpuid_fn(0x80000001, reg);
588		info_p->cpuid_extfeatures =
589				quad(reg[ecx], reg[edx]);
590	}
591
592	DBG(" max_basic           : %d\n", info_p->cpuid_max_basic);
593	DBG(" max_ext             : 0x%08x\n", info_p->cpuid_max_ext);
594	DBG(" vendor              : %s\n", info_p->cpuid_vendor);
595	DBG(" brand_string        : %s\n", info_p->cpuid_brand_string);
596	DBG(" signature           : 0x%08x\n", info_p->cpuid_signature);
597	DBG(" stepping            : %d\n", info_p->cpuid_stepping);
598	DBG(" model               : %d\n", info_p->cpuid_model);
599	DBG(" family              : %d\n", info_p->cpuid_family);
600	DBG(" type                : %d\n", info_p->cpuid_type);
601	DBG(" extmodel            : %d\n", info_p->cpuid_extmodel);
602	DBG(" extfamily           : %d\n", info_p->cpuid_extfamily);
603	DBG(" brand               : %d\n", info_p->cpuid_brand);
604	DBG(" features            : 0x%016llx\n", info_p->cpuid_features);
605	DBG(" extfeatures         : 0x%016llx\n", info_p->cpuid_extfeatures);
606	DBG(" logical_per_package : %d\n", info_p->cpuid_logical_per_package);
607	DBG(" microcode_version   : 0x%08x\n", info_p->cpuid_microcode_version);
608
609	/* Fold in the Invariant TSC feature bit, if present */
610	if (info_p->cpuid_max_ext >= 0x80000007) {
611		cpuid_fn(0x80000007, reg);
612		info_p->cpuid_extfeatures |=
613				reg[edx] & (uint32_t)CPUID_EXTFEATURE_TSCI;
614		DBG(" extfeatures         : 0x%016llx\n",
615		    info_p->cpuid_extfeatures);
616	}
617
618	if (info_p->cpuid_max_basic >= 0x5) {
619		cpuid_mwait_leaf_t	*cmp = &info_p->cpuid_mwait_leaf;
620
621		/*
622		 * Extract the Monitor/Mwait Leaf info:
623		 */
624		cpuid_fn(5, reg);
625		cmp->linesize_min = reg[eax];
626		cmp->linesize_max = reg[ebx];
627		cmp->extensions   = reg[ecx];
628		cmp->sub_Cstates  = reg[edx];
629		info_p->cpuid_mwait_leafp = cmp;
630
631		DBG(" Monitor/Mwait Leaf:\n");
632		DBG("  linesize_min : %d\n", cmp->linesize_min);
633		DBG("  linesize_max : %d\n", cmp->linesize_max);
634		DBG("  extensions   : %d\n", cmp->extensions);
635		DBG("  sub_Cstates  : 0x%08x\n", cmp->sub_Cstates);
636	}
637
638	if (info_p->cpuid_max_basic >= 0x6) {
639		cpuid_thermal_leaf_t	*ctp = &info_p->cpuid_thermal_leaf;
640
641		/*
642		 * The thermal and Power Leaf:
643		 */
644		cpuid_fn(6, reg);
645		ctp->sensor 		  = bitfield32(reg[eax], 0, 0);
646		ctp->dynamic_acceleration = bitfield32(reg[eax], 1, 1);
647		ctp->invariant_APIC_timer = bitfield32(reg[eax], 2, 2);
648		ctp->core_power_limits    = bitfield32(reg[eax], 4, 4);
649		ctp->fine_grain_clock_mod = bitfield32(reg[eax], 5, 5);
650		ctp->package_thermal_intr = bitfield32(reg[eax], 6, 6);
651		ctp->thresholds		  = bitfield32(reg[ebx], 3, 0);
652		ctp->ACNT_MCNT		  = bitfield32(reg[ecx], 0, 0);
653		ctp->hardware_feedback	  = bitfield32(reg[ecx], 1, 1);
654		ctp->energy_policy	  = bitfield32(reg[ecx], 3, 3);
655		info_p->cpuid_thermal_leafp = ctp;
656
657		DBG(" Thermal/Power Leaf:\n");
658		DBG("  sensor               : %d\n", ctp->sensor);
659		DBG("  dynamic_acceleration : %d\n", ctp->dynamic_acceleration);
660		DBG("  invariant_APIC_timer : %d\n", ctp->invariant_APIC_timer);
661		DBG("  core_power_limits    : %d\n", ctp->core_power_limits);
662		DBG("  fine_grain_clock_mod : %d\n", ctp->fine_grain_clock_mod);
663		DBG("  package_thermal_intr : %d\n", ctp->package_thermal_intr);
664		DBG("  thresholds           : %d\n", ctp->thresholds);
665		DBG("  ACNT_MCNT            : %d\n", ctp->ACNT_MCNT);
666		DBG("  ACNT2                : %d\n", ctp->hardware_feedback);
667		DBG("  energy_policy        : %d\n", ctp->energy_policy);
668	}
669
670	if (info_p->cpuid_max_basic >= 0xa) {
671		cpuid_arch_perf_leaf_t	*capp = &info_p->cpuid_arch_perf_leaf;
672
673		/*
674		 * Architectural Performance Monitoring Leaf:
675		 */
676		cpuid_fn(0xa, reg);
677		capp->version	    = bitfield32(reg[eax],  7,  0);
678		capp->number	    = bitfield32(reg[eax], 15,  8);
679		capp->width	    = bitfield32(reg[eax], 23, 16);
680		capp->events_number = bitfield32(reg[eax], 31, 24);
681		capp->events	    = reg[ebx];
682		capp->fixed_number  = bitfield32(reg[edx],  4,  0);
683		capp->fixed_width   = bitfield32(reg[edx], 12,  5);
684		info_p->cpuid_arch_perf_leafp = capp;
685
686		DBG(" Architectural Performance Monitoring Leaf:\n");
687		DBG("  version       : %d\n", capp->version);
688		DBG("  number        : %d\n", capp->number);
689		DBG("  width         : %d\n", capp->width);
690		DBG("  events_number : %d\n", capp->events_number);
691		DBG("  events        : %d\n", capp->events);
692		DBG("  fixed_number  : %d\n", capp->fixed_number);
693		DBG("  fixed_width   : %d\n", capp->fixed_width);
694	}
695
696	if (info_p->cpuid_max_basic >= 0xd) {
697		cpuid_xsave_leaf_t	*xsp = &info_p->cpuid_xsave_leaf;
698		/*
699		 * XSAVE Features:
700		 */
701		cpuid_fn(0xd, info_p->cpuid_xsave_leaf.extended_state);
702		info_p->cpuid_xsave_leafp = xsp;
703
704		DBG(" XSAVE Leaf:\n");
705		DBG("  EAX           : 0x%x\n", xsp->extended_state[eax]);
706		DBG("  EBX           : 0x%x\n", xsp->extended_state[ebx]);
707		DBG("  ECX           : 0x%x\n", xsp->extended_state[ecx]);
708		DBG("  EDX           : 0x%x\n", xsp->extended_state[edx]);
709	}
710
711	if (info_p->cpuid_model >= CPUID_MODEL_IVYBRIDGE) {
712		/*
713		 * Leaf7 Features:
714		 */
715		cpuid_fn(0x7, reg);
716		info_p->cpuid_leaf7_features = reg[ebx];
717
718		DBG(" Feature Leaf7:\n");
719		DBG("  EBX           : 0x%x\n", reg[ebx]);
720	}
721
722	return;
723}
724
725static uint32_t
726cpuid_set_cpufamily(i386_cpu_info_t *info_p)
727{
728	uint32_t cpufamily = CPUFAMILY_UNKNOWN;
729
730	switch (info_p->cpuid_family) {
731	case 6:
732		switch (info_p->cpuid_model) {
733		case 15:
734			cpufamily = CPUFAMILY_INTEL_MEROM;
735			break;
736		case 23:
737			cpufamily = CPUFAMILY_INTEL_PENRYN;
738			break;
739		case CPUID_MODEL_NEHALEM:
740		case CPUID_MODEL_FIELDS:
741		case CPUID_MODEL_DALES:
742		case CPUID_MODEL_NEHALEM_EX:
743			cpufamily = CPUFAMILY_INTEL_NEHALEM;
744			break;
745		case CPUID_MODEL_DALES_32NM:
746		case CPUID_MODEL_WESTMERE:
747		case CPUID_MODEL_WESTMERE_EX:
748			cpufamily = CPUFAMILY_INTEL_WESTMERE;
749			break;
750		case CPUID_MODEL_SANDYBRIDGE:
751		case CPUID_MODEL_JAKETOWN:
752			cpufamily = CPUFAMILY_INTEL_SANDYBRIDGE;
753			break;
754		case CPUID_MODEL_IVYBRIDGE:
755		case CPUID_MODEL_IVYBRIDGE_EP:
756			cpufamily = CPUFAMILY_INTEL_IVYBRIDGE;
757			break;
758		case CPUID_MODEL_HASWELL:
759		case CPUID_MODEL_HASWELL_ULT:
760		case CPUID_MODEL_CRYSTALWELL:
761			cpufamily = CPUFAMILY_INTEL_HASWELL;
762			break;
763		}
764		break;
765	}
766
767	info_p->cpuid_cpufamily = cpufamily;
768	DBG("cpuid_set_cpufamily(%p) returning 0x%x\n", info_p, cpufamily);
769	return cpufamily;
770}
771/*
772 * Must be invoked either when executing single threaded, or with
773 * independent synchronization.
774 */
775void
776cpuid_set_info(void)
777{
778	i386_cpu_info_t		*info_p = &cpuid_cpu_info;
779	boolean_t		enable_x86_64h = TRUE;
780
781	cpuid_set_generic_info(info_p);
782
783	/* verify we are running on a supported CPU */
784	if ((strncmp(CPUID_VID_INTEL, info_p->cpuid_vendor,
785		     min(strlen(CPUID_STRING_UNKNOWN) + 1,
786			 sizeof(info_p->cpuid_vendor)))) ||
787	   (cpuid_set_cpufamily(info_p) == CPUFAMILY_UNKNOWN))
788		panic("Unsupported CPU");
789
790	info_p->cpuid_cpu_type = CPU_TYPE_X86;
791
792	if (!PE_parse_boot_argn("-enable_x86_64h", &enable_x86_64h, sizeof(enable_x86_64h))) {
793		boolean_t		disable_x86_64h = FALSE;
794
795		if (PE_parse_boot_argn("-disable_x86_64h", &disable_x86_64h, sizeof(disable_x86_64h))) {
796			enable_x86_64h = FALSE;
797		}
798	}
799
800	if (enable_x86_64h &&
801	    ((info_p->cpuid_features & CPUID_X86_64_H_FEATURE_SUBSET) == CPUID_X86_64_H_FEATURE_SUBSET) &&
802	    ((info_p->cpuid_extfeatures & CPUID_X86_64_H_EXTFEATURE_SUBSET) == CPUID_X86_64_H_EXTFEATURE_SUBSET) &&
803	    ((info_p->cpuid_leaf7_features & CPUID_X86_64_H_LEAF7_FEATURE_SUBSET) == CPUID_X86_64_H_LEAF7_FEATURE_SUBSET)) {
804		info_p->cpuid_cpu_subtype = CPU_SUBTYPE_X86_64_H;
805	} else {
806		info_p->cpuid_cpu_subtype = CPU_SUBTYPE_X86_ARCH1;
807	}
808
809	/* Must be invoked after set_generic_info */
810	cpuid_set_cache_info(info_p);
811
812	/*
813	 * Find the number of enabled cores and threads
814	 * (which determines whether SMT/Hyperthreading is active).
815	 */
816	switch (info_p->cpuid_cpufamily) {
817	case CPUFAMILY_INTEL_WESTMERE: {
818		uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT);
819		info_p->core_count   = bitfield32((uint32_t)msr, 19, 16);
820		info_p->thread_count = bitfield32((uint32_t)msr, 15,  0);
821		break;
822		}
823	case CPUFAMILY_INTEL_HASWELL:
824	case CPUFAMILY_INTEL_IVYBRIDGE:
825	case CPUFAMILY_INTEL_SANDYBRIDGE:
826	case CPUFAMILY_INTEL_NEHALEM: {
827		uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT);
828		info_p->core_count   = bitfield32((uint32_t)msr, 31, 16);
829		info_p->thread_count = bitfield32((uint32_t)msr, 15,  0);
830		break;
831		}
832	}
833	if (info_p->core_count == 0) {
834		info_p->core_count   = info_p->cpuid_cores_per_package;
835		info_p->thread_count = info_p->cpuid_logical_per_package;
836	}
837	DBG("cpuid_set_info():\n");
838	DBG("  core_count   : %d\n", info_p->core_count);
839	DBG("  thread_count : %d\n", info_p->thread_count);
840	DBG("       cpu_type: 0x%08x\n", info_p->cpuid_cpu_type);
841	DBG("    cpu_subtype: 0x%08x\n", info_p->cpuid_cpu_subtype);
842
843	info_p->cpuid_model_string = ""; /* deprecated */
844}
845
846static struct table {
847	uint64_t	mask;
848	const char	*name;
849} feature_map[] = {
850	{CPUID_FEATURE_FPU,       "FPU"},
851	{CPUID_FEATURE_VME,       "VME"},
852	{CPUID_FEATURE_DE,        "DE"},
853	{CPUID_FEATURE_PSE,       "PSE"},
854	{CPUID_FEATURE_TSC,       "TSC"},
855	{CPUID_FEATURE_MSR,       "MSR"},
856	{CPUID_FEATURE_PAE,       "PAE"},
857	{CPUID_FEATURE_MCE,       "MCE"},
858	{CPUID_FEATURE_CX8,       "CX8"},
859	{CPUID_FEATURE_APIC,      "APIC"},
860	{CPUID_FEATURE_SEP,       "SEP"},
861	{CPUID_FEATURE_MTRR,      "MTRR"},
862	{CPUID_FEATURE_PGE,       "PGE"},
863	{CPUID_FEATURE_MCA,       "MCA"},
864	{CPUID_FEATURE_CMOV,      "CMOV"},
865	{CPUID_FEATURE_PAT,       "PAT"},
866	{CPUID_FEATURE_PSE36,     "PSE36"},
867	{CPUID_FEATURE_PSN,       "PSN"},
868	{CPUID_FEATURE_CLFSH,     "CLFSH"},
869	{CPUID_FEATURE_DS,        "DS"},
870	{CPUID_FEATURE_ACPI,      "ACPI"},
871	{CPUID_FEATURE_MMX,       "MMX"},
872	{CPUID_FEATURE_FXSR,      "FXSR"},
873	{CPUID_FEATURE_SSE,       "SSE"},
874	{CPUID_FEATURE_SSE2,      "SSE2"},
875	{CPUID_FEATURE_SS,        "SS"},
876	{CPUID_FEATURE_HTT,       "HTT"},
877	{CPUID_FEATURE_TM,        "TM"},
878	{CPUID_FEATURE_PBE,       "PBE"},
879	{CPUID_FEATURE_SSE3,      "SSE3"},
880	{CPUID_FEATURE_PCLMULQDQ, "PCLMULQDQ"},
881	{CPUID_FEATURE_DTES64,    "DTES64"},
882	{CPUID_FEATURE_MONITOR,   "MON"},
883	{CPUID_FEATURE_DSCPL,     "DSCPL"},
884	{CPUID_FEATURE_VMX,       "VMX"},
885	{CPUID_FEATURE_SMX,       "SMX"},
886	{CPUID_FEATURE_EST,       "EST"},
887	{CPUID_FEATURE_TM2,       "TM2"},
888	{CPUID_FEATURE_SSSE3,     "SSSE3"},
889	{CPUID_FEATURE_CID,       "CID"},
890	{CPUID_FEATURE_FMA,       "FMA"},
891	{CPUID_FEATURE_CX16,      "CX16"},
892	{CPUID_FEATURE_xTPR,      "TPR"},
893	{CPUID_FEATURE_PDCM,      "PDCM"},
894	{CPUID_FEATURE_SSE4_1,    "SSE4.1"},
895	{CPUID_FEATURE_SSE4_2,    "SSE4.2"},
896	{CPUID_FEATURE_x2APIC,    "x2APIC"},
897	{CPUID_FEATURE_MOVBE,     "MOVBE"},
898	{CPUID_FEATURE_POPCNT,    "POPCNT"},
899	{CPUID_FEATURE_AES,       "AES"},
900	{CPUID_FEATURE_VMM,       "VMM"},
901	{CPUID_FEATURE_PCID,      "PCID"},
902	{CPUID_FEATURE_XSAVE,     "XSAVE"},
903	{CPUID_FEATURE_OSXSAVE,   "OSXSAVE"},
904	{CPUID_FEATURE_SEGLIM64,  "SEGLIM64"},
905	{CPUID_FEATURE_TSCTMR,    "TSCTMR"},
906	{CPUID_FEATURE_AVX1_0,    "AVX1.0"},
907	{CPUID_FEATURE_RDRAND,    "RDRAND"},
908	{CPUID_FEATURE_F16C,      "F16C"},
909	{0, 0}
910},
911extfeature_map[] = {
912	{CPUID_EXTFEATURE_SYSCALL, "SYSCALL"},
913	{CPUID_EXTFEATURE_XD,      "XD"},
914	{CPUID_EXTFEATURE_1GBPAGE, "1GBPAGE"},
915	{CPUID_EXTFEATURE_EM64T,   "EM64T"},
916	{CPUID_EXTFEATURE_LAHF,    "LAHF"},
917	{CPUID_EXTFEATURE_LZCNT,   "LZCNT"},
918	{CPUID_EXTFEATURE_PREFETCHW, "PREFETCHW"},
919	{CPUID_EXTFEATURE_RDTSCP,  "RDTSCP"},
920	{CPUID_EXTFEATURE_TSCI,    "TSCI"},
921	{0, 0}
922
923},
924leaf7_feature_map[] = {
925	{CPUID_LEAF7_FEATURE_SMEP,     "SMEP"},
926	{CPUID_LEAF7_FEATURE_ERMS,     "ERMS"},
927	{CPUID_LEAF7_FEATURE_RDWRFSGS, "RDWRFSGS"},
928	{CPUID_LEAF7_FEATURE_TSCOFF,   "TSC_THREAD_OFFSET"},
929	{CPUID_LEAF7_FEATURE_BMI1,     "BMI1"},
930	{CPUID_LEAF7_FEATURE_HLE,      "HLE"},
931	{CPUID_LEAF7_FEATURE_AVX2,     "AVX2"},
932	{CPUID_LEAF7_FEATURE_BMI2,     "BMI2"},
933	{CPUID_LEAF7_FEATURE_INVPCID,  "INVPCID"},
934	{CPUID_LEAF7_FEATURE_RTM,      "RTM"},
935	{0, 0}
936};
937
938static char *
939cpuid_get_names(struct table *map, uint64_t bits, char *buf, unsigned buf_len)
940{
941	size_t	len = 0;
942	char	*p = buf;
943	int	i;
944
945	for (i = 0; map[i].mask != 0; i++) {
946		if ((bits & map[i].mask) == 0)
947			continue;
948		if (len && ((size_t) (p - buf) < (buf_len - 1)))
949			*p++ = ' ';
950		len = min(strlen(map[i].name), (size_t)((buf_len-1)-(p-buf)));
951		if (len == 0)
952			break;
953		bcopy(map[i].name, p, len);
954		p += len;
955	}
956	*p = '\0';
957	return buf;
958}
959
960i386_cpu_info_t	*
961cpuid_info(void)
962{
963	/* Set-up the cpuid_info stucture lazily */
964	if (cpuid_cpu_infop == NULL) {
965		PE_parse_boot_argn("-cpuid", &cpuid_dbg, sizeof(cpuid_dbg));
966		cpuid_set_info();
967		cpuid_cpu_infop = &cpuid_cpu_info;
968	}
969	return cpuid_cpu_infop;
970}
971
972char *
973cpuid_get_feature_names(uint64_t features, char *buf, unsigned buf_len)
974{
975	return cpuid_get_names(feature_map, features, buf, buf_len);
976}
977
978char *
979cpuid_get_extfeature_names(uint64_t extfeatures, char *buf, unsigned buf_len)
980{
981	return cpuid_get_names(extfeature_map, extfeatures, buf, buf_len);
982}
983
984char *
985cpuid_get_leaf7_feature_names(uint64_t features, char *buf, unsigned buf_len)
986{
987	return cpuid_get_names(leaf7_feature_map, features, buf, buf_len);
988}
989
990void
991cpuid_feature_display(
992	const char	*header)
993{
994	char	buf[256];
995
996	kprintf("%s: %s", header,
997		 cpuid_get_feature_names(cpuid_features(), buf, sizeof(buf)));
998	if (cpuid_leaf7_features())
999		kprintf(" %s", cpuid_get_leaf7_feature_names(
1000				cpuid_leaf7_features(), buf, sizeof(buf)));
1001	kprintf("\n");
1002	if (cpuid_features() & CPUID_FEATURE_HTT) {
1003#define s_if_plural(n)	((n > 1) ? "s" : "")
1004		kprintf("  HTT: %d core%s per package;"
1005			     " %d logical cpu%s per package\n",
1006			cpuid_cpu_infop->cpuid_cores_per_package,
1007			s_if_plural(cpuid_cpu_infop->cpuid_cores_per_package),
1008			cpuid_cpu_infop->cpuid_logical_per_package,
1009			s_if_plural(cpuid_cpu_infop->cpuid_logical_per_package));
1010	}
1011}
1012
1013void
1014cpuid_extfeature_display(
1015	const char	*header)
1016{
1017	char	buf[256];
1018
1019	kprintf("%s: %s\n", header,
1020		  cpuid_get_extfeature_names(cpuid_extfeatures(),
1021						buf, sizeof(buf)));
1022}
1023
1024void
1025cpuid_cpu_display(
1026	const char	*header)
1027{
1028    if (cpuid_cpu_infop->cpuid_brand_string[0] != '\0') {
1029	kprintf("%s: %s\n", header, cpuid_cpu_infop->cpuid_brand_string);
1030    }
1031}
1032
1033unsigned int
1034cpuid_family(void)
1035{
1036	return cpuid_info()->cpuid_family;
1037}
1038
1039uint32_t
1040cpuid_cpufamily(void)
1041{
1042	return cpuid_info()->cpuid_cpufamily;
1043}
1044
1045cpu_type_t
1046cpuid_cputype(void)
1047{
1048	return cpuid_info()->cpuid_cpu_type;
1049}
1050
1051cpu_subtype_t
1052cpuid_cpusubtype(void)
1053{
1054	return cpuid_info()->cpuid_cpu_subtype;
1055}
1056
1057uint64_t
1058cpuid_features(void)
1059{
1060	static int checked = 0;
1061	char	fpu_arg[20] = { 0 };
1062
1063	(void) cpuid_info();
1064	if (!checked) {
1065		    /* check for boot-time fpu limitations */
1066			if (PE_parse_boot_argn("_fpu", &fpu_arg[0], sizeof (fpu_arg))) {
1067				printf("limiting fpu features to: %s\n", fpu_arg);
1068				if (!strncmp("387", fpu_arg, sizeof("387")) || !strncmp("mmx", fpu_arg, sizeof("mmx"))) {
1069					printf("no sse or sse2\n");
1070					cpuid_cpu_infop->cpuid_features &= ~(CPUID_FEATURE_SSE | CPUID_FEATURE_SSE2 | CPUID_FEATURE_FXSR);
1071				} else if (!strncmp("sse", fpu_arg, sizeof("sse"))) {
1072					printf("no sse2\n");
1073					cpuid_cpu_infop->cpuid_features &= ~(CPUID_FEATURE_SSE2);
1074				}
1075			}
1076			checked = 1;
1077	}
1078	return cpuid_cpu_infop->cpuid_features;
1079}
1080
1081uint64_t
1082cpuid_extfeatures(void)
1083{
1084	return cpuid_info()->cpuid_extfeatures;
1085}
1086
1087uint64_t
1088cpuid_leaf7_features(void)
1089{
1090	return cpuid_info()->cpuid_leaf7_features;
1091}
1092
1093static i386_vmm_info_t	*_cpuid_vmm_infop = NULL;
1094static i386_vmm_info_t	_cpuid_vmm_info;
1095
1096static void
1097cpuid_init_vmm_info(i386_vmm_info_t *info_p)
1098{
1099	uint32_t	reg[4];
1100	uint32_t	max_vmm_leaf;
1101
1102	bzero(info_p, sizeof(*info_p));
1103
1104	if (!cpuid_vmm_present())
1105		return;
1106
1107	DBG("cpuid_init_vmm_info(%p)\n", info_p);
1108
1109	/* do cpuid 0x40000000 to get VMM vendor */
1110	cpuid_fn(0x40000000, reg);
1111	max_vmm_leaf = reg[eax];
1112	bcopy((char *)&reg[ebx], &info_p->cpuid_vmm_vendor[0], 4);
1113	bcopy((char *)&reg[ecx], &info_p->cpuid_vmm_vendor[4], 4);
1114	bcopy((char *)&reg[edx], &info_p->cpuid_vmm_vendor[8], 4);
1115	info_p->cpuid_vmm_vendor[12] = '\0';
1116
1117	if (0 == strcmp(info_p->cpuid_vmm_vendor, CPUID_VMM_ID_VMWARE)) {
1118		/* VMware identification string: kb.vmware.com/kb/1009458 */
1119		info_p->cpuid_vmm_family = CPUID_VMM_FAMILY_VMWARE;
1120	} else if (0 == strcmp(info_p->cpuid_vmm_vendor, CPUID_VMM_ID_PARALLELS)) {
1121		/* Parallels identification string */
1122		info_p->cpuid_vmm_family = CPUID_VMM_FAMILY_PARALLELS;
1123	} else {
1124		info_p->cpuid_vmm_family = CPUID_VMM_FAMILY_UNKNOWN;
1125	}
1126
1127	/* VMM generic leaves: https://lkml.org/lkml/2008/10/1/246 */
1128	if (max_vmm_leaf >= 0x40000010) {
1129		cpuid_fn(0x40000010, reg);
1130
1131		info_p->cpuid_vmm_tsc_frequency = reg[eax];
1132		info_p->cpuid_vmm_bus_frequency = reg[ebx];
1133	}
1134
1135	DBG(" vmm_vendor          : %s\n", info_p->cpuid_vmm_vendor);
1136	DBG(" vmm_family          : %u\n", info_p->cpuid_vmm_family);
1137	DBG(" vmm_bus_frequency   : %u\n", info_p->cpuid_vmm_bus_frequency);
1138	DBG(" vmm_tsc_frequency   : %u\n", info_p->cpuid_vmm_tsc_frequency);
1139}
1140
1141boolean_t
1142cpuid_vmm_present(void)
1143{
1144	return (cpuid_features() & CPUID_FEATURE_VMM) ? TRUE : FALSE;
1145}
1146
1147i386_vmm_info_t *
1148cpuid_vmm_info(void)
1149{
1150	if (_cpuid_vmm_infop == NULL) {
1151		cpuid_init_vmm_info(&_cpuid_vmm_info);
1152		_cpuid_vmm_infop = &_cpuid_vmm_info;
1153	}
1154	return _cpuid_vmm_infop;
1155}
1156
1157uint32_t
1158cpuid_vmm_family(void)
1159{
1160	return cpuid_vmm_info()->cpuid_vmm_family;
1161}
1162
1163