identcpu.c revision 1.7
1/*	$OpenBSD: identcpu.c,v 1.7 2006/03/07 05:21:40 jsg Exp $	*/
2/*	$NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $	*/
3
4/*
5 * Copyright (c) 2003 Wasabi Systems, Inc.
6 * All rights reserved.
7 *
8 * Written by Frank van der Linden for Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *      This product includes software developed for the NetBSD Project by
21 *      Wasabi Systems, Inc.
22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23 *    or promote products derived from this software without specific prior
24 *    written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/proc.h>
43#include <sys/user.h>
44#include <sys/sysctl.h>
45#include <machine/cpu.h>
46#include <machine/cpufunc.h>
47
48/* sysctl wants this. */
49char cpu_model[48];
50int cpuspeed;
51
52const struct {
53	u_int32_t	bit;
54	char		str[8];
55} cpu_cpuid_features[] = {
56	{ CPUID_FPU,	"FPU" },
57	{ CPUID_VME,	"VME" },
58	{ CPUID_DE,	"DE" },
59	{ CPUID_PSE,	"PSE" },
60	{ CPUID_TSC,	"TSC" },
61	{ CPUID_MSR,	"MSR" },
62	{ CPUID_PAE,	"PAE" },
63	{ CPUID_MCE,	"MCE" },
64	{ CPUID_CX8,	"CX8" },
65	{ CPUID_APIC,	"APIC" },
66	{ CPUID_SEP,	"SEP" },
67	{ CPUID_MTRR,	"MTRR" },
68	{ CPUID_PGE,	"PGE" },
69	{ CPUID_MCA,	"MCA" },
70	{ CPUID_CMOV,	"CMOV" },
71	{ CPUID_PAT,	"PAT" },
72	{ CPUID_PSE36,	"PSE36" },
73	{ CPUID_PN,	"PN" },
74	{ CPUID_CFLUSH,	"CFLUSH" },
75	{ CPUID_DS,	"DS" },
76	{ CPUID_ACPI,	"ACPI" },
77	{ CPUID_MMX,	"MMX" },
78	{ CPUID_FXSR,	"FXSR" },
79	{ CPUID_SSE,	"SSE" },
80	{ CPUID_SSE2,	"SSE2" },
81	{ CPUID_SS,	"SS" },
82	{ CPUID_HTT,	"HTT" },
83	{ CPUID_TM,	"TM" },
84	{ CPUID_SBF,	"SBF" }
85}, cpu_ecpuid_features[] = {
86	{ CPUID_MPC,	"MPC" },
87	{ CPUID_NXE,	"NXE" },
88	{ CPUID_MMXX,	"MMXX" },
89	{ CPUID_FFXSR,	"FFXSR" },
90	{ CPUID_LONG,	"LONG" },
91	{ CPUID_3DNOW2,	"3DNOW2" },
92	{ CPUID_3DNOW,	"3DNOW" }
93}, cpu_cpuid_ecxfeatures[] = {
94	{ CPUIDECX_SSE3, "SSE3" }
95};
96
97int
98cpu_amd64speed(int *freq)
99{
100	*freq = cpuspeed;
101	return (0);
102}
103
104void
105identifycpu(struct cpu_info *ci)
106{
107	u_int64_t last_tsc;
108	u_int32_t dummy, val;
109	u_int32_t brand[12];
110	int i, max;
111	char *brandstr_from, *brandstr_to;
112	int skipspace;
113
114	CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags);
115	CPUID(0x80000001, dummy, dummy, dummy, ci->ci_feature_eflags);
116
117	CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
118	CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
119	CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
120
121	strlcpy(cpu_model, (char *)brand, sizeof(cpu_model));
122
123	/* Remove leading and duplicated spaces from cpu_model */
124	brandstr_from = brandstr_to = cpu_model;
125	skipspace = 1;
126	while (*brandstr_from != '\0') {
127		if (!skipspace || *brandstr_from != ' ') {
128			skipspace = 0;
129			*(brandstr_to++) = *brandstr_from;
130		}
131		if (*brandstr_from == ' ')
132			skipspace = 1;
133		brandstr_from++;
134	}
135	*brandstr_to = '\0';
136
137	if (cpu_model[0] == 0)
138		strlcpy(cpu_model, "Opteron or Athlon 64", sizeof(cpu_model));
139
140	last_tsc = rdtsc();
141	delay(100000);
142	ci->ci_tsc_freq = (rdtsc() - last_tsc) * 10;
143
144	amd_cpu_cacheinfo(ci);
145
146	printf("%s: %s", ci->ci_dev->dv_xname, cpu_model);
147
148	if (ci->ci_tsc_freq != 0)
149		printf(", %lu.%02lu MHz", (ci->ci_tsc_freq + 4999) / 1000000,
150		    ((ci->ci_tsc_freq + 4999) / 10000) % 100);
151	cpuspeed = (ci->ci_tsc_freq + 4999) / 1000000;
152	cpu_cpuspeed = cpu_amd64speed;
153
154	printf("\n%s: ", ci->ci_dev->dv_xname);
155
156	max = sizeof(cpu_cpuid_features) / sizeof(cpu_cpuid_features[0]);
157	for (i = 0; i < max; i++)
158		if (ci->ci_feature_flags & cpu_cpuid_features[i].bit)
159			printf("%s%s", i? "," : "", cpu_cpuid_features[i].str);
160	max = sizeof(cpu_cpuid_ecxfeatures) / sizeof(cpu_cpuid_ecxfeatures[0]);
161	for (i = 0; i < max; i++)
162		if (cpu_ecxfeature & cpu_cpuid_ecxfeatures[i].bit)
163			printf(",%s", cpu_cpuid_ecxfeatures[i].str);
164	max = sizeof(cpu_ecpuid_features) / sizeof(cpu_ecpuid_features[0]);
165	for (i = 0; i < max; i++)
166		if (ci->ci_feature_eflags & cpu_ecpuid_features[i].bit)
167			printf(",%s", cpu_ecpuid_features[i].str);
168	printf("\n");
169
170	x86_print_cacheinfo(ci);
171}
172
173void
174cpu_probe_features(struct cpu_info *ci)
175{
176	ci->ci_feature_flags = cpu_feature;
177	ci->ci_signature = 0;
178}
179