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 */
46int
47bi_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
139void
140bi_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