op_hw_specific.h

Go to the documentation of this file.
00001 /* 
00002  * @file architecture specific interfaces
00003  * @remark Copyright 2008 Intel Corporation
00004  * @remark Read the file COPYING
00005  * @author Andi Kleen
00006  */
00007 
00008 #if defined(__i386__) || defined(__x86_64__) 
00009 
00010 /* Assume we run on the same host as the profilee */
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 /* Work around Nehalem spec update AAJ79: CPUID incorrectly indicates
00076    unhalted reference cycle architectural event is supported. We assume
00077    steppings after C0 report correct data in CPUID. */
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);   /* disable unsupported event */
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         /* Already know is Intel family 6, so just check the model. */
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:  /* Westmere mobile/desktop/entry level server */
00138         case 0x2c:  /* Westmere-EP (Intel Xeon 5600 series) */
00139         case 0x2f:  /* Westmere-EX */
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     /* Do something with passed arg to shut up the compiler warning */
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     /* Do something with passed arg to shut up the compiler warning */
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

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1