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 #include <machine/psl.h>
31 #include <machine/cpufunc.h>
32 #include <machine/specialreg.h>
33
34 /*
35 * Check to see if this CPU supports long mode.
36 */
37 int
bi_checkcpu(void)38 bi_checkcpu(void)
39 {
40 unsigned long flags;
41 unsigned int regs[4];
42 unsigned int maxeax;
43 unsigned int max_maxeax = 0x100;
44 unsigned int stdfeatures = 0, xtdfeatures = 0;
45 int amd64 = 0;
46
47 /* Check for presence of "cpuid". */
48 #if defined(__LP64__)
49 flags = read_rflags();
50 write_rflags(flags ^ PSL_ID);
51 if (!((flags ^ read_rflags()) & PSL_ID))
52 return (0);
53 #else
54 flags = read_eflags();
55 write_eflags(flags ^ PSL_ID);
56 if (!((flags ^ read_eflags()) & PSL_ID))
57 return (0);
58 #endif /* __LP64__ */
59
60 /* Fetch the vendor string. */
61 do_cpuid(0, regs);
62 maxeax = regs[0];
63
64 /*
65 * Limit the range in case of weird hardware
66 */
67 if (maxeax > max_maxeax)
68 maxeax = max_maxeax;
69 if (maxeax < 1)
70 return (0);
71 else {
72 do_cpuid(1, regs);
73 stdfeatures = regs[3];
74 }
75
76 /* Has to support AMD features. */
77 do_cpuid(0x80000000, regs);
78 if (regs[0] & 0x80000000) {
79 maxeax = regs[0];
80 max_maxeax = 0x80000100;
81 if (maxeax > max_maxeax)
82 maxeax = max_maxeax;
83 if (maxeax >= 0x80000001) {
84 do_cpuid(0x80000001, regs);
85 xtdfeatures = regs[3];
86 }
87 }
88
89 /* Check for long mode. */
90 if (xtdfeatures & AMDID_LM)
91 amd64++;
92
93 /* Check for FPU. */
94 if ((stdfeatures & CPUID_FPU) == 0)
95 amd64 = 0;
96
97 if ((stdfeatures & CPUID_TSC) == 0)
98 amd64 = 0;
99
100 if ((stdfeatures & CPUID_MSR) == 0)
101 amd64 = 0;
102
103 if ((stdfeatures & CPUID_PAE) == 0)
104 amd64 = 0;
105
106 if ((stdfeatures & CPUID_CX8) == 0)
107 amd64 = 0;
108
109 if ((stdfeatures & CPUID_PGE) == 0)
110 amd64 = 0;
111
112 if ((stdfeatures & CPUID_CLFSH) == 0)
113 amd64 = 0;
114
115 if ((stdfeatures & CPUID_MMX) == 0)
116 amd64 = 0;
117
118 if ((stdfeatures & CPUID_FXSR) == 0)
119 amd64 = 0;
120
121 if ((stdfeatures & CPUID_SSE) == 0)
122 amd64 = 0;
123
124 if ((stdfeatures & CPUID_SSE2) == 0)
125 amd64 = 0;
126
127 return (amd64);
128 }
129
130 void
bi_isadir(void)131 bi_isadir(void)
132 {
133 int rc;
134
135 if (bi_checkcpu())
136 rc = setenv("ISADIR", "amd64", 1);
137 else
138 rc = setenv("ISADIR", "", 1);
139
140 if (rc != 0) {
141 printf("Warning: failed to set ISADIR environment "
142 "variable: %d\n", rc);
143 }
144 }
145