op_hw_specific.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #if defined(__i386__) || defined(__x86_64__)
00009
00010
00011
00012 #define num_to_mask(x) ((1U << (x)) - 1)
00013
00014 typedef struct {
00015 unsigned eax, ebx, ecx, edx;
00016 } cpuid_data;
00017
00018 #if defined(__i386__)
00019 static inline void cpuid(int func, cpuid_data * p)
00020 {
00021 asm("push %%ebx; cpuid; mov %%ebx, %%esi; pop %%ebx"
00022 : "=a" (p->eax), "=S" (p->ebx), "=c" (p->ecx), "=d" (p->edx)
00023 : "0" (func));
00024 }
00025 #else
00026 static inline void cpuid(int func, cpuid_data * p)
00027 {
00028 asm("cpuid"
00029 : "=a" (p->eax), "=b" (p->ebx), "=c" (p->ecx), "=d" (p->edx)
00030 : "0" (func));
00031 }
00032 #endif
00033
00034 static inline int cpuid_vendor(char *vnd)
00035 {
00036 union {
00037 struct {
00038 unsigned b,d,c;
00039 };
00040 char v[12];
00041 } v;
00042 cpuid_data data;
00043 cpuid(0, &data);
00044 v.b = data.ebx; v.c = data.ecx; v.d = data.edx;
00045 return !strncmp(v.v, vnd, 12);
00046 }
00047
00048 static inline unsigned int cpuid_signature()
00049 {
00050 cpuid_data data;
00051 cpuid(1, &data);
00052 return data.eax;
00053 }
00054
00055 static inline unsigned int cpu_model(unsigned int eax)
00056 {
00057 unsigned model = (eax & 0xf0) >> 4;
00058 unsigned ext_model = (eax & 0xf0000) >> 12;
00059 return ext_model + model;
00060 }
00061
00062 static inline unsigned int cpu_family(unsigned int eax)
00063 {
00064 unsigned family = (eax & 0xf00) >> 8;
00065 unsigned ext_family = (eax & 0xff00000) >> 20;
00066 return ext_family + family;
00067 }
00068
00069 static inline unsigned int cpu_stepping(unsigned int eax)
00070 {
00071 return (eax & 0xf);
00072 }
00073
00074
00075
00076
00077
00078 static inline void workaround_nehalem_aaj79(unsigned *ebx)
00079 {
00080 unsigned eax;
00081
00082 if (!cpuid_vendor("GenuineIntel"))
00083 return;
00084 eax = cpuid_signature();
00085 if (cpu_family(eax) != 6 || cpu_model(eax) != 26
00086 || cpu_stepping(eax) > 4)
00087 return;
00088 *ebx |= (1 << 2);
00089 }
00090
00091 static inline unsigned arch_get_filter(op_cpu cpu_type)
00092 {
00093 if (op_cpu_base_type(cpu_type) == CPU_ARCH_PERFMON) {
00094 cpuid_data data;
00095 cpuid(0xa, &data);
00096 workaround_nehalem_aaj79(&data.ebx);
00097 return data.ebx & num_to_mask(data.eax >> 24);
00098 }
00099 return -1U;
00100 }
00101
00102 static inline int arch_num_counters(op_cpu cpu_type)
00103 {
00104 if (op_cpu_base_type(cpu_type) == CPU_ARCH_PERFMON) {
00105 cpuid_data data;
00106 cpuid(0xa, &data);
00107 return (data.eax >> 8) & 0xff;
00108 }
00109 return -1;
00110 }
00111
00112 static inline unsigned arch_get_counter_mask(void)
00113 {
00114 cpuid_data data;
00115 cpuid(0xa, &data);
00116 return num_to_mask((data.eax >> 8) & 0xff);
00117 }
00118
00119 static inline op_cpu op_cpu_specific_type(op_cpu cpu_type)
00120 {
00121 if (cpu_type == CPU_ARCH_PERFMON) {
00122
00123 int model = cpu_model(cpuid_signature());
00124 switch(model) {
00125 case 0x0f:
00126 case 0x16:
00127 case 0x17:
00128 case 0x1d:
00129 return CPU_CORE_2;
00130 case 0x1a:
00131 case 0x1e:
00132 case 0x1f:
00133 case 0x2e:
00134 return CPU_CORE_I7;
00135 case 0x1c:
00136 return CPU_ATOM;
00137 case 0x25:
00138 case 0x2c:
00139 case 0x2f:
00140 return CPU_WESTMERE;
00141 case 0x2a:
00142 case 0x2d:
00143 return CPU_SANDYBRIDGE;
00144 case 0x3a:
00145 return CPU_IVYBRIDGE;
00146 }
00147 }
00148 return cpu_type;
00149 }
00150
00151 #else
00152
00153 static inline unsigned arch_get_filter(op_cpu cpu_type)
00154 {
00155
00156 if (cpu_type != CPU_NO_GOOD)
00157 return 0;
00158 return 0;
00159 }
00160
00161 static inline int arch_num_counters(op_cpu cpu_type)
00162 {
00163
00164 if (cpu_type != CPU_NO_GOOD)
00165 return -1;
00166 return -1;
00167 }
00168
00169 static inline unsigned arch_get_counter_mask(void)
00170 {
00171 return 0;
00172 }
00173
00174 static inline op_cpu op_cpu_specific_type(op_cpu cpu_type)
00175 {
00176 return cpu_type;
00177 }
00178 #endif