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