xref: /illumos-gate/usr/src/boot/i386/libi386/cpuid.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 
29 #include <stand.h>
30 /*
31 #include <sys/param.h>
32 #include <sys/reboot.h>
33 #include <sys/linker.h>
34 #include <machine/bootinfo.h>
35 #include <machine/metadata.h>
36 #include "bootstrap.h"
37 */
38 #include <machine/psl.h>
39 #include <machine/cpufunc.h>
40 #include <machine/specialreg.h>
41 #include "libi386.h"
42 
43 /*
44  * Check to see if this CPU supports long mode.
45  */
46 int
47 bi_checkcpu(void)
48 {
49 	unsigned long flags;
50 	unsigned int regs[4];
51 	unsigned int maxeax;
52 	unsigned int max_maxeax = 0x100;
53 	unsigned int stdfeatures = 0, xtdfeatures = 0;
54 	int amd64 = 0;
55 
56 	/* Check for presence of "cpuid". */
57 #if defined(__LP64__)
58 	flags = read_rflags();
59 	write_rflags(flags ^ PSL_ID);
60 	if (!((flags ^ read_rflags()) & PSL_ID))
61 		return (0);
62 #else
63 	flags = read_eflags();
64 	write_eflags(flags ^ PSL_ID);
65 	if (!((flags ^ read_eflags()) & PSL_ID))
66 		return (0);
67 #endif /* __LP64__ */
68 
69 	/* Fetch the vendor string. */
70 	do_cpuid(0, regs);
71 	maxeax = regs[0];
72 
73 	/*
74 	 * Limit the range in case of weird hardware
75 	 */
76 	if (maxeax > max_maxeax)
77 		maxeax = max_maxeax;
78 	if (maxeax < 1)
79 		return (0);
80 	else {
81 		do_cpuid(1, regs);
82 		stdfeatures = regs[3];
83 	}
84 
85 	/* Has to support AMD features. */
86 	do_cpuid(0x80000000, regs);
87 	if (regs[0] & 0x80000000) {
88 		maxeax = regs[0];
89 		max_maxeax = 0x80000100;
90 		if (maxeax > max_maxeax)
91 			maxeax = max_maxeax;
92 		if (maxeax >= 0x80000001) {
93 			do_cpuid(0x80000001, regs);
94 			xtdfeatures = regs[3];
95 		}
96 	}
97 
98 	/* Check for long mode. */
99 	if (xtdfeatures & AMDID_LM)
100 		amd64++;
101 
102 	/* Check for FPU. */
103 	if ((stdfeatures & CPUID_FPU) == 0)
104 		amd64 = 0;
105 
106 	if ((stdfeatures & CPUID_TSC) == 0)
107 		amd64 = 0;
108 
109 	if ((stdfeatures & CPUID_MSR) == 0)
110 		amd64 = 0;
111 
112 	if ((stdfeatures & CPUID_PAE) == 0)
113 		amd64 = 0;
114 
115 	if ((stdfeatures & CPUID_CX8) == 0)
116 		amd64 = 0;
117 
118 	if ((stdfeatures & CPUID_PGE) == 0)
119 		amd64 = 0;
120 
121 	if ((stdfeatures & CPUID_CLFSH) == 0)
122 		amd64 = 0;
123 
124 	if ((stdfeatures & CPUID_MMX) == 0)
125 		amd64 = 0;
126 
127 	if ((stdfeatures & CPUID_FXSR) == 0)
128 		amd64 = 0;
129 
130 	if ((stdfeatures & CPUID_SSE) == 0)
131 		amd64 = 0;
132 
133         if ((stdfeatures & CPUID_SSE2) == 0)
134 		amd64 = 0;
135 
136 	return (amd64);
137 }
138 
139 void
140 bi_isadir(void)
141 {
142 	int rc;
143 
144 	if (bi_checkcpu())
145 		rc = setenv("ISADIR", "amd64", 1);
146 	else
147 		rc = setenv("ISADIR", "", 1);
148 
149 	if (rc != 0) {
150 		printf("Warning: failed to set ISADIR environment "
151 		    "variable: %d\n", rc);
152 	}
153 }
154