X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1..8f6c56a50524aa785f7e596d52dddfb331e18961:/osfmk/i386/cpuid.c diff --git a/osfmk/i386/cpuid.c b/osfmk/i386/cpuid.c index 86fa8959d..d4879d3a3 100644 --- a/osfmk/i386/cpuid.c +++ b/osfmk/i386/cpuid.c @@ -1,49 +1,39 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ -#include -#include + #include #include "cpuid.h" -#if MACH_KDB -#include -#include -#include -#include -#include -#include -#include -#include -#endif #define min(a,b) ((a) < (b) ? (a) : (b)) -#define quad(hi,lo) (((uint64_t)(hi)) << 32 | (lo)) - -#define bit(n) (1UL << (n)) -#define bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1)) -#define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l) /* * CPU identification routines. @@ -88,10 +78,10 @@ cpuid_get_info(i386_cpu_info_t *info_p) /* do cpuid 0 to get vendor */ do_cpuid(0, cpuid_result); - cpuid_maxcpuid = cpuid_result[eax]; - bcopy((char *)&cpuid_result[ebx], &info_p->cpuid_vendor[0], 4); /* ug */ - bcopy((char *)&cpuid_result[ecx], &info_p->cpuid_vendor[8], 4); - bcopy((char *)&cpuid_result[edx], &info_p->cpuid_vendor[4], 4); + cpuid_maxcpuid = cpuid_result[0]; + bcopy((char *)&cpuid_result[1], &info_p->cpuid_vendor[0], 4); /* ugh */ + bcopy((char *)&cpuid_result[2], &info_p->cpuid_vendor[8], 4); + bcopy((char *)&cpuid_result[3], &info_p->cpuid_vendor[4], 4); info_p->cpuid_vendor[12] = 0; /* look up vendor */ @@ -171,8 +161,6 @@ CACHE_DESC(CPUID_CACHE_UCACHE_1M, L2U, 1*1024*1024, 32, \ "Unified L2 cache, 1M, 4-way set associative, 32byte line size"), CACHE_DESC(CPUID_CACHE_UCACHE_2M, L2U, 2*1024*1024, 32, \ "Unified L2 cache, 2M, 4-way set associative, 32byte line size"), -CACHE_DESC(CPUID_CACHE_UCACHE_4M, L2U, 4*1024*1024, 64, \ - "Unified L2 cache, 4M, 16-way set associative, 64byte line size"), CACHE_DESC(CPUID_CACHE_UCACHE_128K_64, L2U, 128*1024, 64, \ "Unified L2 cache, 128K, 8-way set associative, 64byte line size"), CACHE_DESC(CPUID_CACHE_UCACHE_256K_64, L2U, 256*1024, 64, \ @@ -223,12 +211,9 @@ CACHE_DESC(CPUID_CACHE_NULL, Lnone, 0, 0, \ (char *)0), }; -static const char * get_intel_model_string( i386_cpu_info_t * info_p, cpu_type_t* type, cpu_subtype_t* subtype) +static const char * get_intel_model_string( i386_cpu_info_t * info_p ) { - *type = CPU_TYPE_X86; - *subtype = CPU_SUBTYPE_X86_ARCH1; - - /* check for brand id string */ + /* check for brand id */ switch(info_p->cpuid_brand) { case CPUID_BRAND_UNSUPPORTED: /* brand ID not supported; use alternate method. */ @@ -257,13 +242,14 @@ static const char * get_intel_model_string( i386_cpu_info_t * info_p, cpu_type_t default: return "Unknown Intel P6 Family"; } + case CPUID_FAMILY_ITANIUM: + return "Intel Itanium"; case CPUID_FAMILY_EXTENDED: switch (info_p->cpuid_extfamily) { case CPUID_EXTFAMILY_PENTIUM4: - *subtype = CPU_SUBTYPE_PENTIUM_4; return "Intel Pentium 4"; - default: - return "Unknown Intel Extended Family"; + case CPUID_EXTFAMILY_ITANIUM2: + return "Intel Itanium 2"; } default: return "Unknown Intel Family"; @@ -277,11 +263,10 @@ static const char * get_intel_model_string( i386_cpu_info_t * info_p, cpu_type_t case CPUID_BRAND_PENTIUM_III_4: return "Pentium III"; case CPUID_BRAND_PIII_XEON: - if (info_p->cpuid_signature == 0x6B1) { - return "Intel Celeron"; - } else { - return "Intel Pentium III Xeon"; - } + if (info_p->cpuid_signature == 0x6B1) + return "Intel Celeron"; + else + return "Intel Pentium III Xeon"; case CPUID_BRAND_PENTIUM_III_M: return "Mobile Intel Pentium III-M"; case CPUID_BRAND_M_CELERON_7: @@ -291,19 +276,16 @@ static const char * get_intel_model_string( i386_cpu_info_t * info_p, cpu_type_t return "Mobile Intel Celeron"; case CPUID_BRAND_PENTIUM4_8: case CPUID_BRAND_PENTIUM4_9: - *subtype = CPU_SUBTYPE_PENTIUM_4; return "Intel Pentium 4"; case CPUID_BRAND_XEON: return "Intel Xeon"; case CPUID_BRAND_XEON_MP: return "Intel Xeon MP"; case CPUID_BRAND_PENTIUM4_M: - if (info_p->cpuid_signature == 0xF13) { - return "Intel Xeon"; - } else { - *subtype = CPU_SUBTYPE_PENTIUM_4; - return "Mobile Intel Pentium 4"; - } + if (info_p->cpuid_signature == 0xF13) + return "Intel Xeon"; + else + return "Mobile Intel Pentium 4"; case CPUID_BRAND_CELERON_M: return "Intel Celeron M"; case CPUID_BRAND_PENTIUM_M: @@ -312,6 +294,7 @@ static const char * get_intel_model_string( i386_cpu_info_t * info_p, cpu_type_t case CPUID_BRAND_MOBILE_17: return "Mobile Intel"; } + return "Unknown Intel"; } @@ -370,69 +353,17 @@ static void set_intel_cache_info( i386_cpu_info_t * info_p ) /* If we have no L2 cache, use the L1 data cache line size */ if (info_p->cache_size[L2U] == 0) info_p->cache_linesize = l1d_cache_linesize; - - /* - * Get cache sharing info if available. - */ - do_cpuid(0, cpuid_result); - if (cpuid_result[eax] >= 4) { - uint32_t reg[4]; - uint32_t index; - for (index = 0;; index++) { - /* - * Scan making calls for cpuid with %eax = 4 - * to get info about successive cache levels - * until a null type is returned. - */ - cache_type_t type = Lnone; - uint32_t cache_type; - uint32_t cache_level; - uint32_t cache_sharing; - - reg[eax] = 4; /* cpuid request 4 */ - reg[ecx] = index; /* index starting at 0 */ - cpuid(reg); -//kprintf("cpuid(4) index=%d eax=%p\n", index, reg[eax]); - cache_type = bitfield(reg[eax], 4, 0); - if (cache_type == 0) - break; /* done with cache info */ - cache_level = bitfield(reg[eax], 7, 5); - cache_sharing = bitfield(reg[eax], 25, 14); - info_p->cpuid_cores_per_package = - bitfield(reg[eax], 31, 26) + 1; - switch (cache_level) { - case 1: - type = cache_type == 1 ? L1D : - cache_type == 2 ? L1I : - Lnone; - break; - case 2: - type = cache_type == 3 ? L2U : - Lnone; - break; - case 3: - type = cache_type == 3 ? L3U : - Lnone; - } - if (type != Lnone) - info_p->cache_sharing[type] = cache_sharing + 1; - } - } } static void set_cpu_intel( i386_cpu_info_t * info_p ) { set_cpu_generic(info_p); set_intel_cache_info(info_p); - info_p->cpuid_model_string = get_intel_model_string(info_p, &info_p->cpuid_cpu_type, &info_p->cpuid_cpu_subtype); + info_p->cpuid_model_string = get_intel_model_string(info_p); } -static const char * get_amd_model_string( i386_cpu_info_t * info_p, cpu_type_t* type, cpu_subtype_t* subtype ) +static const char * get_amd_model_string( i386_cpu_info_t * info_p ) { - *type = CPU_TYPE_X86; - *subtype = CPU_SUBTYPE_X86_ARCH1; - - /* check for brand id string */ switch (info_p->cpuid_family) { case CPUID_FAMILY_486: @@ -513,11 +444,11 @@ static void set_amd_cache_info( i386_cpu_info_t * info_p ) /* (ignore) */ /* ECX: L1 Data Cache Information */ - info_p->cache_size[L1D] = ((cpuid_result[ecx] >> 24) & 0xFF) * 1024; - info_p->cache_linesize = (cpuid_result[ecx] & 0xFF); + info_p->cache_size[L1D] = ((cpuid_result[2] >> 24) & 0xFF) * 1024; + info_p->cache_linesize = (cpuid_result[2] & 0xFF); /* EDX: L1 Instruction Cache Information */ - info_p->cache_size[L1I] = ((cpuid_result[edx] >> 24) & 0xFF) * 1024; + info_p->cache_size[L1I] = ((cpuid_result[3] >> 24) & 0xFF) * 1024; /* L2 Cache Information */ do_cpuid(0x80000006, cpuid_result); @@ -529,16 +460,16 @@ static void set_amd_cache_info( i386_cpu_info_t * info_p ) /* (ignore) */ /* ECX: L2 Cache Information */ - info_p->cache_size[L2U] = ((cpuid_result[ecx] >> 16) & 0xFFFF) * 1024; + info_p->cache_size[L2U] = ((cpuid_result[2] >> 16) & 0xFFFF) * 1024; if (info_p->cache_size[L2U] > 0) - info_p->cache_linesize = cpuid_result[ecx] & 0xFF; + info_p->cache_linesize = cpuid_result[2] & 0xFF; } static void set_cpu_amd( i386_cpu_info_t * info_p ) { set_cpu_generic(info_p); set_amd_cache_info(info_p); - info_p->cpuid_model_string = get_amd_model_string(info_p, &info_p->cpuid_cpu_type, &info_p->cpuid_cpu_subtype); + info_p->cpuid_model_string = get_amd_model_string(info_p); } static void set_cpu_nsc( i386_cpu_info_t * info_p ) @@ -546,16 +477,12 @@ static void set_cpu_nsc( i386_cpu_info_t * info_p ) set_cpu_generic(info_p); set_amd_cache_info(info_p); - /* check for brand id string */ - if (info_p->cpuid_family == CPUID_FAMILY_586 && info_p->cpuid_model == CPUID_MODEL_GX1) { + if (info_p->cpuid_family == CPUID_FAMILY_586 && info_p->cpuid_model == CPUID_MODEL_GX1) info_p->cpuid_model_string = "AMD Geode GX1"; - } else if (info_p->cpuid_family == CPUID_FAMILY_586 && info_p->cpuid_model == CPUID_MODEL_GX2) { + else if (info_p->cpuid_family == CPUID_FAMILY_586 && info_p->cpuid_model == CPUID_MODEL_GX2) info_p->cpuid_model_string = "AMD Geode GX"; - } else { + else info_p->cpuid_model_string = "Unknown National Semiconductor"; - } - info_p->cpuid_cpu_type = CPU_TYPE_X86; - info_p->cpuid_cpu_subtype = CPU_SUBTYPE_X86_ARCH1; } static void @@ -567,7 +494,7 @@ set_cpu_generic(i386_cpu_info_t *info_p) /* get extended cpuid results */ do_cpuid(0x80000000, cpuid_result); - max_extid = cpuid_result[eax]; + max_extid = cpuid_result[0]; /* check to see if we can get brand string */ if (max_extid >= 0x80000004) { @@ -599,23 +526,15 @@ set_cpu_generic(i386_cpu_info_t *info_p) /* get processor signature and decode */ do_cpuid(1, cpuid_result); - info_p->cpuid_signature = cpuid_result[eax]; - info_p->cpuid_stepping = bitfield(cpuid_result[eax], 3, 0); - info_p->cpuid_model = bitfield(cpuid_result[eax], 7, 4); - info_p->cpuid_family = bitfield(cpuid_result[eax], 11, 8); - info_p->cpuid_type = bitfield(cpuid_result[eax], 13, 12); - info_p->cpuid_extmodel = bitfield(cpuid_result[eax], 19, 16); - info_p->cpuid_extfamily = bitfield(cpuid_result[eax], 27, 20); - info_p->cpuid_brand = bitfield(cpuid_result[ebx], 7, 0); - info_p->cpuid_logical_per_package = - bitfield(cpuid_result[ebx], 23, 16); - info_p->cpuid_features = quad(cpuid_result[ecx], cpuid_result[edx]); - - if (max_extid >= 0x80000001) { - do_cpuid(0x80000001, cpuid_result); - info_p->cpuid_extfeatures = - quad(cpuid_result[ecx], cpuid_result[edx]); - } + info_p->cpuid_signature = cpuid_result[0]; + info_p->cpuid_stepping = cpuid_result[0] & 0x0f; + info_p->cpuid_model = (cpuid_result[0] >> 4) & 0x0f; + info_p->cpuid_family = (cpuid_result[0] >> 8) & 0x0f; + info_p->cpuid_type = (cpuid_result[0] >> 12) & 0x03; + info_p->cpuid_extmodel = (cpuid_result[0] >> 16) & 0x0f; + info_p->cpuid_extfamily = (cpuid_result[0] >> 20) & 0xff; + info_p->cpuid_brand = cpuid_result[1] & 0xff; + info_p->cpuid_features = cpuid_result[3]; return; } @@ -628,9 +547,9 @@ set_cpu_unknown(__unused i386_cpu_info_t *info_p) static struct { - uint64_t mask; + uint32_t mask; const char *name; -} feature_map[] = { +} feature_names[] = { {CPUID_FEATURE_FPU, "FPU",}, {CPUID_FEATURE_VME, "VME",}, {CPUID_FEATURE_DE, "DE",}, @@ -659,65 +578,25 @@ static struct { {CPUID_FEATURE_SS, "SS",}, {CPUID_FEATURE_HTT, "HTT",}, {CPUID_FEATURE_TM, "TM",}, - {CPUID_FEATURE_SSE3, "SSE3"}, - {CPUID_FEATURE_MONITOR, "MON"}, - {CPUID_FEATURE_DSCPL, "DSCPL"}, - {CPUID_FEATURE_VMX, "VMX"}, - {CPUID_FEATURE_SMX, "SMX"}, - {CPUID_FEATURE_EST, "EST"}, - {CPUID_FEATURE_TM2, "TM2"}, - {CPUID_FEATURE_MNI, "MNI"}, - {CPUID_FEATURE_CID, "CID"}, - {CPUID_FEATURE_CX16, "CX16"}, - {CPUID_FEATURE_xTPR, "TPR"}, - {0, 0} -}, -extfeature_map[] = { - {CPUID_EXTFEATURE_SYSCALL, "SYSCALL"}, - {CPUID_EXTFEATURE_XD, "XD"}, - {CPUID_EXTFEATURE_EM64T, "EM64T"}, - {CPUID_EXTFEATURE_LAHF, "LAHF"}, {0, 0} }; char * -cpuid_get_feature_names(uint64_t features, char *buf, unsigned buf_len) +cpuid_get_feature_names(uint32_t feature, char *buf, unsigned buf_len) { - int len = -1; - char *p = buf; int i; - - for (i = 0; feature_map[i].mask != 0; i++) { - if ((features & feature_map[i].mask) == 0) - continue; - if (len > 0) - *p++ = ' '; - len = min(strlen(feature_map[i].name), (buf_len-1) - (p-buf)); - if (len == 0) - break; - bcopy(feature_map[i].name, p, len); - p += len; - } - *p = '\0'; - return buf; -} - -char * -cpuid_get_extfeature_names(uint64_t extfeatures, char *buf, unsigned buf_len) -{ - int len = -1; + int len; char *p = buf; - int i; - for (i = 0; extfeature_map[i].mask != 0; i++) { - if ((extfeatures & extfeature_map[i].mask) == 0) + for (i = 0; feature_names[i].mask != 0; i++) { + if ((feature & feature_names[i].mask) == 0) continue; - if (len > 0) + if (i > 0) *p++ = ' '; - len = min(strlen(extfeature_map[i].name), (buf_len-1)-(p-buf)); + len = min(strlen(feature_names[i].name), (buf_len-1) - (p-buf)); if (len == 0) break; - bcopy(extfeature_map[i].name, p, len); + bcopy(feature_names[i].name, p, len); p += len; } *p = '\0'; @@ -726,41 +605,23 @@ cpuid_get_extfeature_names(uint64_t extfeatures, char *buf, unsigned buf_len) void cpuid_feature_display( - const char *header) -{ - char buf[256]; - - kprintf("%s: %s\n", header, - cpuid_get_feature_names(cpuid_features(), - buf, sizeof(buf))); - if (cpuid_features() & CPUID_FEATURE_HTT) { -#define s_if_plural(n) ((n > 1) ? "s" : "") - kprintf(" HTT: %d core%s per package;" - " %d logical cpu%s per package\n", - cpuid_cpu_info.cpuid_cores_per_package, - s_if_plural(cpuid_cpu_info.cpuid_cores_per_package), - cpuid_cpu_info.cpuid_logical_per_package, - s_if_plural(cpuid_cpu_info.cpuid_logical_per_package)); - } -} - -void -cpuid_extfeature_display( - const char *header) + const char *header, + __unused int my_cpu) { char buf[256]; - kprintf("%s: %s\n", header, - cpuid_get_extfeature_names(cpuid_extfeatures(), - buf, sizeof(buf))); + printf("%s: %s\n", header, + cpuid_get_feature_names(cpuid_features(), buf, sizeof(buf))); } void cpuid_cpu_display( - const char *header) + const char *header, + __unused int my_cpu) { if (cpuid_cpu_info.cpuid_brand_string[0] != '\0') { - kprintf("%s: %s\n", header, cpuid_cpu_info.cpuid_brand_string); + printf("%s: %s\n", header, + cpuid_cpu_info.cpuid_brand_string); } } @@ -770,19 +631,7 @@ cpuid_family(void) return cpuid_cpu_info.cpuid_family; } -cpu_type_t -cpuid_cputype(void) -{ - return cpuid_cpu_info.cpuid_cpu_type; -} - -cpu_subtype_t -cpuid_cpusubtype(void) -{ - return cpuid_cpu_info.cpuid_cpu_subtype; -} - -uint64_t +unsigned int cpuid_features(void) { static int checked = 0; @@ -804,65 +653,17 @@ cpuid_features(void) return cpuid_cpu_info.cpuid_features; } -uint64_t -cpuid_extfeatures(void) -{ - return cpuid_cpu_info.cpuid_extfeatures; -} - i386_cpu_info_t * cpuid_info(void) { return &cpuid_cpu_info; } +/* XXX for temporary compatibility */ void -cpuid_set_info(void) +set_cpu_model(void) { cpuid_get_info(&cpuid_cpu_info); + cpuid_feature = cpuid_cpu_info.cpuid_features; /* XXX compat */ } -#if MACH_KDB - -/* - * Display the cpuid - * * - * cp - */ -void -db_cpuid(__unused db_expr_t addr, - __unused int have_addr, - __unused db_expr_t count, - __unused char *modif) -{ - - uint32_t i, mid; - uint32_t cpid[4]; - - do_cpuid(0, cpid); /* Get the first cpuid which is the number of - * basic ids */ - db_printf("%08X - %08X %08X %08X %08X\n", - 0, cpid[eax], cpid[ebx], cpid[ecx], cpid[edx]); - - mid = cpid[eax]; /* Set the number */ - for (i = 1; i <= mid; i++) { /* Dump 'em out */ - do_cpuid(i, cpid); /* Get the next */ - db_printf("%08X - %08X %08X %08X %08X\n", - i, cpid[eax], cpid[ebx], cpid[ecx], cpid[edx]); - } - db_printf("\n"); - - do_cpuid(0x80000000, cpid); /* Get the first extended cpuid which - * is the number of extended ids */ - db_printf("%08X - %08X %08X %08X %08X\n", - 0x80000000, cpid[eax], cpid[ebx], cpid[ecx], cpid[edx]); - - mid = cpid[eax]; /* Set the number */ - for (i = 0x80000001; i <= mid; i++) { /* Dump 'em out */ - do_cpuid(i, cpid); /* Get the next */ - db_printf("%08X - %08X %08X %08X %08X\n", - i, cpid[eax], cpid[ebx], cpid[ecx], cpid[edx]); - } -} - -#endif