1*6320Sbholler /* 2*6320Sbholler * CDDL HEADER START 3*6320Sbholler * 4*6320Sbholler * The contents of this file are subject to the terms of the 5*6320Sbholler * Common Development and Distribution License (the "License"). 6*6320Sbholler * You may not use this file except in compliance with the License. 7*6320Sbholler * 8*6320Sbholler * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6320Sbholler * or http://www.opensolaris.org/os/licensing. 10*6320Sbholler * See the License for the specific language governing permissions 11*6320Sbholler * and limitations under the License. 12*6320Sbholler * 13*6320Sbholler * When distributing Covered Code, include this CDDL HEADER in each 14*6320Sbholler * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6320Sbholler * If applicable, add the following below this CDDL HEADER, with the 16*6320Sbholler * fields enclosed by brackets "[]" replaced with your own identifying 17*6320Sbholler * information: Portions Copyright [yyyy] [name of copyright owner] 18*6320Sbholler * 19*6320Sbholler * CDDL HEADER END 20*6320Sbholler */ 21*6320Sbholler 22*6320Sbholler /* 23*6320Sbholler * Copyright (c) 2008, Intel Corporation. 24*6320Sbholler * All rights reserved. 25*6320Sbholler */ 26*6320Sbholler 27*6320Sbholler #pragma ident "%Z%%M% %I% %E% SMI" 28*6320Sbholler 29*6320Sbholler #include <sys/types.h> 30*6320Sbholler #include "proc64_id.h" 31*6320Sbholler 32*6320Sbholler /* 33*6320Sbholler * Intel cpuid eax=4 Cache Types 34*6320Sbholler */ 35*6320Sbholler #define NULL_CACHE 0x0 36*6320Sbholler #define DATA_CACHE 0x1 37*6320Sbholler #define INSTRUCTION_CACHE 0x2 38*6320Sbholler #define UNIFIED_CACHE 0x3 39*6320Sbholler 40*6320Sbholler struct cpuid_values { 41*6320Sbholler uint_t eax; 42*6320Sbholler uint_t ebx; 43*6320Sbholler uint_t ecx; 44*6320Sbholler uint_t edx; 45*6320Sbholler }; 46*6320Sbholler 47*6320Sbholler extern void __amd64id(void); 48*6320Sbholler 49*6320Sbholler /* 50*6320Sbholler * get_intel_cache_info() 51*6320Sbholler * Get cpu cache sizes for optimized 64-bit libc functions mem* and str*. 52*6320Sbholler * Find the sizes of the 1st, 2nd and largest level caches. 53*6320Sbholler */ 54*6320Sbholler static void 55*6320Sbholler get_intel_cache_info(void) 56*6320Sbholler { 57*6320Sbholler int cache_level; 58*6320Sbholler int largest_cache_level = 0; 59*6320Sbholler int cache_index = 0; 60*6320Sbholler int cache_type; 61*6320Sbholler int line_size, partitions, ways, sets; 62*6320Sbholler uint_t cache_size; 63*6320Sbholler uint_t l1_cache_size = 0; 64*6320Sbholler uint_t l2_cache_size = 0; 65*6320Sbholler uint_t largest_level_cache = 0; 66*6320Sbholler struct cpuid_values cpuid_info; 67*6320Sbholler 68*6320Sbholler while (1) { 69*6320Sbholler __libc_get_cpuid(4, (uint_t *)&cpuid_info, cache_index); 70*6320Sbholler 71*6320Sbholler cache_type = cpuid_info.eax & 0x1f; 72*6320Sbholler if (cache_type == NULL_CACHE) { 73*6320Sbholler /* 74*6320Sbholler * No more caches. 75*6320Sbholler */ 76*6320Sbholler break; 77*6320Sbholler } 78*6320Sbholler cache_index += 1; 79*6320Sbholler 80*6320Sbholler if (cache_type == INSTRUCTION_CACHE) { 81*6320Sbholler /* 82*6320Sbholler * Don't care for memops 83*6320Sbholler */ 84*6320Sbholler continue; 85*6320Sbholler } 86*6320Sbholler 87*6320Sbholler cache_level = (cpuid_info.eax >> 0x5) & 0x7; 88*6320Sbholler line_size = (cpuid_info.ebx & 0xfff) + 1; 89*6320Sbholler partitions = ((cpuid_info.ebx >> 12) & 0x3ff) + 1; 90*6320Sbholler ways = ((cpuid_info.ebx >> 22) & 0x3ff) + 1; 91*6320Sbholler sets = cpuid_info.ecx + 1; 92*6320Sbholler cache_size = ways * partitions * line_size * sets; 93*6320Sbholler 94*6320Sbholler if (cache_level == 1) { 95*6320Sbholler l1_cache_size = cache_size; 96*6320Sbholler } 97*6320Sbholler if (cache_level == 2) { 98*6320Sbholler l2_cache_size = cache_size; 99*6320Sbholler } 100*6320Sbholler if (cache_level > largest_cache_level) { 101*6320Sbholler largest_cache_level = cache_level; 102*6320Sbholler largest_level_cache = cache_size; 103*6320Sbholler } 104*6320Sbholler } 105*6320Sbholler 106*6320Sbholler __intel_set_cache_sizes(l1_cache_size, l2_cache_size, 107*6320Sbholler largest_level_cache); 108*6320Sbholler } 109*6320Sbholler 110*6320Sbholler /* 111*6320Sbholler * proc64_id() 112*6320Sbholler * Determine cache and SSE level to use for memops and strops specific to 113*6320Sbholler * processor type. 114*6320Sbholler */ 115*6320Sbholler void 116*6320Sbholler __proc64id(void) 117*6320Sbholler { 118*6320Sbholler int use_sse = NO_SSE; 119*6320Sbholler struct cpuid_values cpuid_info; 120*6320Sbholler 121*6320Sbholler __libc_get_cpuid(0, &cpuid_info, 0); 122*6320Sbholler 123*6320Sbholler /* 124*6320Sbholler * Check for AuthenticAMD 125*6320Sbholler */ 126*6320Sbholler if ((cpuid_info.ebx == 0x68747541) && /* Auth */ 127*6320Sbholler (cpuid_info.edx == 0x69746e65) && /* enti */ 128*6320Sbholler (cpuid_info.ecx == 0x444d4163)) { /* cAMD */ 129*6320Sbholler __amd64id(); 130*6320Sbholler return; 131*6320Sbholler } 132*6320Sbholler 133*6320Sbholler /* 134*6320Sbholler * Check for GenuineIntel 135*6320Sbholler */ 136*6320Sbholler if ((cpuid_info.ebx != 0x756e6547) || /* Genu */ 137*6320Sbholler (cpuid_info.edx != 0x49656e69) || /* ineI */ 138*6320Sbholler (cpuid_info.ecx != 0x6c65746e)) { /* ntel */ 139*6320Sbholler /* 140*6320Sbholler * Not Intel - use defaults. 141*6320Sbholler */ 142*6320Sbholler return; 143*6320Sbholler } 144*6320Sbholler 145*6320Sbholler /* 146*6320Sbholler * Genuine Intel 147*6320Sbholler */ 148*6320Sbholler 149*6320Sbholler /* 150*6320Sbholler * Look for CPUID function 4 support - Deterministic Cache Parameters. 151*6320Sbholler * Otherwise use default cache sizes. 152*6320Sbholler */ 153*6320Sbholler if (cpuid_info.eax >= 4) { 154*6320Sbholler get_intel_cache_info(); 155*6320Sbholler 156*6320Sbholler /* 157*6320Sbholler * Check what SSE versions are supported. 158*6320Sbholler */ 159*6320Sbholler __libc_get_cpuid(1, &cpuid_info, 0); 160*6320Sbholler if (cpuid_info.ecx & CPUID_INTC_ECX_SSE4_2) { 161*6320Sbholler use_sse |= USE_SSE4_2; 162*6320Sbholler } 163*6320Sbholler if (cpuid_info.ecx & CPUID_INTC_ECX_SSE4_1) { 164*6320Sbholler use_sse |= USE_SSE4_1; 165*6320Sbholler } 166*6320Sbholler if (cpuid_info.ecx & CPUID_INTC_ECX_SSSE3) { 167*6320Sbholler use_sse |= USE_SSSE3; 168*6320Sbholler } 169*6320Sbholler if (cpuid_info.ecx & CPUID_INTC_ECX_SSE3) { 170*6320Sbholler use_sse |= USE_SSE3; 171*6320Sbholler } 172*6320Sbholler if (cpuid_info.edx & CPUID_INTC_EDX_SSE2) { 173*6320Sbholler use_sse |= USE_SSE2; 174*6320Sbholler } 175*6320Sbholler __intel_set_memops_method(use_sse); 176*6320Sbholler } else { 177*6320Sbholler __intel_set_cache_sizes(INTEL_DFLT_L1_CACHE_SIZE, 178*6320Sbholler INTEL_DFLT_L2_CACHE_SIZE, 179*6320Sbholler INTEL_DFLT_LARGEST_CACHE_SIZE); 180*6320Sbholler __intel_set_memops_method(use_sse); 181*6320Sbholler } 182*6320Sbholler } 183