1 /* 2 * @file architecture specific interfaces 3 * @remark Copyright 2008 Intel Corporation 4 * @remark Read the file COPYING 5 * @author Andi Kleen 6 */ 7 8 #if defined(__i386__) || defined(__x86_64__) 9 10 /* Assume we run on the same host as the profilee */ 11 12 #define num_to_mask(x) ((1U << (x)) - 1) 13 14 static inline int cpuid_vendor(char *vnd) 15 { 16 union { 17 struct { 18 unsigned b,d,c; 19 }; 20 char v[12]; 21 } v; 22 unsigned eax; 23 asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" 24 : "=a" (eax), "=S" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0)); 25 return !strncmp(v.v, vnd, 12); 26 } 27 28 /* Work around Nehalem spec update AAJ79: CPUID incorrectly indicates 29 unhalted reference cycle architectural event is supported. We assume 30 steppings after C0 report correct data in CPUID. */ 31 static inline void workaround_nehalem_aaj79(unsigned *ebx) 32 { 33 union { 34 unsigned eax; 35 struct { 36 unsigned stepping : 4; 37 unsigned model : 4; 38 unsigned family : 4; 39 unsigned type : 2; 40 unsigned res : 2; 41 unsigned ext_model : 4; 42 unsigned ext_family : 8; 43 unsigned res2 : 4; 44 }; 45 } v; 46 unsigned model; 47 48 if (!cpuid_vendor("GenuineIntel")) 49 return; 50 asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" 51 : "=a" (v.eax) : "0" (1) : "ecx","edx"); 52 model = (v.ext_model << 4) + v.model; 53 if (v.family != 6 || model != 26 || v.stepping > 4) 54 return; 55 *ebx |= (1 << 2); /* disable unsupported event */ 56 } 57 58 static inline unsigned arch_get_filter(op_cpu cpu_type) 59 { 60 if (cpu_type == CPU_ARCH_PERFMON) { 61 unsigned ebx, eax; 62 asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" 63 : "=a" (eax), "=S" (ebx) : "0" (0xa) : "ecx","edx"); 64 workaround_nehalem_aaj79(&ebx); 65 return ebx & num_to_mask(eax >> 24); 66 } 67 return -1U; 68 } 69 70 static inline int arch_num_counters(op_cpu cpu_type) 71 { 72 if (cpu_type == CPU_ARCH_PERFMON) { 73 unsigned v; 74 asm volatile( "pushl %%ebx; cpuid; movl %%eax, %1; popl %%ebx" 75 : "=a" (v) : "0" (0xa) : "ecx","edx"); 76 return (v >> 8) & 0xff; 77 } 78 return -1; 79 } 80 81 static inline unsigned arch_get_counter_mask(void) 82 { 83 unsigned v; 84 asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" 85 : "=a" (v) : "0" (0xa) : "ecx","edx"); 86 return num_to_mask((v >> 8) & 0xff); 87 } 88 89 #else 90 91 static inline unsigned arch_get_filter(op_cpu cpu_type) 92 { 93 /* Do something with passed arg to shut up the compiler warning */ 94 if (cpu_type != CPU_NO_GOOD) 95 return 0; 96 return 0; 97 } 98 99 static inline int arch_num_counters(op_cpu cpu_type) 100 { 101 /* Do something with passed arg to shut up the compiler warning */ 102 if (cpu_type != CPU_NO_GOOD) 103 return -1; 104 return -1; 105 } 106 107 static inline unsigned arch_get_counter_mask(void) 108 { 109 return 0; 110 } 111 112 #endif 113