PAPI  5.3.0.0
linux-rapl.c
Go to the documentation of this file.
00001 
00016 #include <stdio.h>
00017 #include <unistd.h>
00018 #include <dirent.h>
00019 #include <fcntl.h>
00020 #include <string.h>
00021 #include <stdint.h>
00022 #include <errno.h>
00023 
00024 /* Headers required by PAPI */
00025 #include "papi.h"
00026 #include "papi_internal.h"
00027 #include "papi_vector.h"
00028 #include "papi_memory.h"
00029 
00030 
00031 /*
00032  * Platform specific RAPL Domains.
00033  * Note that PP1 RAPL Domain is supported on 062A only
00034  * And DRAM RAPL Domain is supported on 062D only
00035  */
00036 
00037 
00038 /* RAPL defines */
00039 #define MSR_RAPL_POWER_UNIT             0x606
00040 
00041 /* Package */
00042 #define MSR_PKG_RAPL_POWER_LIMIT        0x610
00043 #define MSR_PKG_ENERGY_STATUS           0x611
00044 #define MSR_PKG_PERF_STATUS             0x613
00045 #define MSR_PKG_POWER_INFO              0x614
00046 
00047 /* PP0 */
00048 #define MSR_PP0_POWER_LIMIT             0x638
00049 #define MSR_PP0_ENERGY_STATUS           0x639
00050 #define MSR_PP0_POLICY                  0x63A
00051 #define MSR_PP0_PERF_STATUS             0x63B
00052 
00053 /* PP1 */
00054 #define MSR_PP1_POWER_LIMIT             0x640
00055 #define MSR_PP1_ENERGY_STATUS           0x641
00056 #define MSR_PP1_POLICY                  0x642
00057 
00058 /* DRAM */
00059 #define MSR_DRAM_POWER_LIMIT            0x618
00060 #define MSR_DRAM_ENERGY_STATUS          0x619
00061 #define MSR_DRAM_PERF_STATUS            0x61B
00062 #define MSR_DRAM_POWER_INFO             0x61C
00063 
00064 /* RAPL bitsmasks */
00065 #define POWER_UNIT_OFFSET          0
00066 #define POWER_UNIT_MASK         0x0f
00067 
00068 #define ENERGY_UNIT_OFFSET      0x08
00069 #define ENERGY_UNIT_MASK        0x1f
00070 
00071 #define TIME_UNIT_OFFSET        0x10
00072 #define TIME_UNIT_MASK          0x0f
00073 
00074 /* RAPL POWER UNIT MASKS */
00075 #define POWER_INFO_UNIT_MASK     0x7fff
00076 #define THERMAL_SHIFT                 0
00077 #define MINIMUM_POWER_SHIFT          16
00078 #define MAXIMUM_POWER_SHIFT          32
00079 #define MAXIMUM_TIME_WINDOW_SHIFT    48
00080 
00081 
00082 typedef struct _rapl_register
00083 {
00084     unsigned int selector;
00085 } _rapl_register_t;
00086 
00087 typedef struct _rapl_native_event_entry
00088 {
00089   char name[PAPI_MAX_STR_LEN];
00090   char units[PAPI_MIN_STR_LEN];
00091   char description[PAPI_MAX_STR_LEN];
00092   int fd_offset;
00093   int msr;
00094   int type;
00095   int return_type;
00096   _rapl_register_t resources;
00097 } _rapl_native_event_entry_t;
00098 
00099 typedef struct _rapl_reg_alloc
00100 {
00101     _rapl_register_t ra_bits;
00102 } _rapl_reg_alloc_t;
00103 
00104 /* actually 32?  But setting this to be safe? */
00105 #define RAPL_MAX_COUNTERS 64
00106 
00107 typedef struct _rapl_control_state
00108 {
00109   int being_measured[RAPL_MAX_COUNTERS];
00110   long long count[RAPL_MAX_COUNTERS];
00111   int need_difference[RAPL_MAX_COUNTERS];
00112   long long lastupdate;
00113 } _rapl_control_state_t;
00114 
00115 
00116 typedef struct _rapl_context
00117 {
00118   long long start_value[RAPL_MAX_COUNTERS];
00119   _rapl_control_state_t state;
00120 } _rapl_context_t;
00121 
00122 
00123 papi_vector_t _rapl_vector;
00124 
00125 struct fd_array_t {
00126   int fd;
00127   int open;
00128 };
00129 
00130 static _rapl_native_event_entry_t * rapl_native_events=NULL;
00131 static int num_events       = 0;
00132 struct fd_array_t *fd_array=NULL;
00133 static int num_packages=0,num_cpus=0;
00134 
00135 int power_divisor,energy_divisor,time_divisor;
00136 
00137 
00138 #define PACKAGE_ENERGY          0
00139 #define PACKAGE_THERMAL         1
00140 #define PACKAGE_MINIMUM         2
00141 #define PACKAGE_MAXIMUM         3
00142 #define PACKAGE_TIME_WINDOW     4
00143 #define PACKAGE_ENERGY_CNT      5
00144 #define PACKAGE_THERMAL_CNT     6
00145 #define PACKAGE_MINIMUM_CNT     7
00146 #define PACKAGE_MAXIMUM_CNT     8
00147 #define PACKAGE_TIME_WINDOW_CNT 9
00148 
00149 
00150 /***************************************************************************/
00151 /******  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
00152 /***************************************************************************/
00153 
00154 
00155 static long long read_msr(int fd, int which) {
00156 
00157   uint64_t data;
00158 
00159   if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) {
00160     perror("rdmsr:pread");
00161     exit(127);
00162   }
00163 
00164   return (long long)data;
00165 }
00166 
00167 static int open_fd(int offset) {
00168   
00169   int fd=-1;
00170   char filename[BUFSIZ];
00171 
00172   if (fd_array[offset].open==0) {
00173      sprintf(filename,"/dev/cpu/%d/msr",offset);
00174      fd = open(filename, O_RDONLY);
00175      if (fd>=0) {
00176         fd_array[offset].fd=fd;
00177     fd_array[offset].open=1;
00178      }
00179   }
00180   else {
00181     fd=fd_array[offset].fd;
00182   }
00183 
00184   return fd;
00185 }
00186 
00187 static long long read_rapl_value(int index) {
00188 
00189    int fd;
00190 
00191    fd=open_fd(rapl_native_events[index].fd_offset);
00192    return read_msr(fd,rapl_native_events[index].msr);
00193    
00194 }
00195 
00196 static long long convert_rapl_energy(int index, long long value) {
00197 
00198    union {
00199       long long ll;
00200       double fp;
00201    } return_val;
00202 
00203    return_val.ll = value; /* default case: return raw input value */
00204 
00205    if (rapl_native_events[index].type==PACKAGE_ENERGY) {
00206       return_val.ll = (long long)(((double)value/energy_divisor)*1e9);
00207    }
00208 
00209    if (rapl_native_events[index].type==PACKAGE_THERMAL) {
00210       return_val.fp = (double)
00211                       ((value>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK) /
00212                        (double)power_divisor;
00213    }
00214 
00215    if (rapl_native_events[index].type==PACKAGE_MINIMUM) {
00216        return_val.fp = (double)
00217                        ((value>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/
00218                         (double)power_divisor;
00219    }
00220 
00221    if (rapl_native_events[index].type==PACKAGE_MAXIMUM) {
00222       return_val.fp = (double)
00223                       ((value>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/
00224                        (double)power_divisor;
00225    }
00226 
00227    if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW) {
00228       return_val.fp =  (double)
00229                     ((value>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK)/
00230                      (double)time_divisor;
00231    }
00232 
00233    if (rapl_native_events[index].type==PACKAGE_THERMAL_CNT) {
00234       return_val.ll = ((value>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK);
00235    }
00236 
00237    if (rapl_native_events[index].type==PACKAGE_MINIMUM_CNT) {
00238        return_val.ll = ((value>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
00239    }
00240 
00241    if (rapl_native_events[index].type==PACKAGE_MAXIMUM_CNT) {
00242       return_val.ll = ((value>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
00243    }
00244 
00245    if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW_CNT) {
00246       return_val.ll = ((value>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK);
00247    }
00248 
00249    return return_val.ll;
00250 }
00251 
00252 static int
00253 get_kernel_nr_cpus(void)
00254 {
00255   FILE *fff;
00256   int num_read, nr_cpus = 1;
00257   fff=fopen("/sys/devices/system/cpu/kernel_max","r");
00258   if (fff==NULL) return nr_cpus;
00259   num_read=fscanf(fff,"%d",&nr_cpus);
00260   fclose(fff);
00261   if (num_read==1) {
00262     nr_cpus++;
00263   } else {
00264     nr_cpus = 1;
00265   }
00266   return nr_cpus;
00267 }
00268 
00269 /************************* PAPI Functions **********************************/
00270 
00271 
00272 /*
00273  * This is called whenever a thread is initialized
00274  */
00275 int 
00276 _rapl_init_thread( hwd_context_t *ctx )
00277 {
00278   ( void ) ctx;
00279 
00280   return PAPI_OK;
00281 }
00282 
00283 
00284 
00285 /* 
00286  * Called when PAPI process is initialized (i.e. PAPI_library_init)
00287  */
00288 int 
00289 _rapl_init_component( int cidx )
00290 {
00291      int i,j,k,fd;
00292      FILE *fff;
00293      char filename[BUFSIZ];
00294 
00295      int package_avail, dram_avail, pp0_avail, pp1_avail;
00296 
00297      long long result;
00298      int package;
00299 
00300      const PAPI_hw_info_t *hw_info;
00301 
00302      int nr_cpus = get_kernel_nr_cpus();
00303      int packages[nr_cpus];
00304      int cpu_to_use[nr_cpus];
00305 
00306      /* Fill with sentinel values */
00307      for (i=0; i<nr_cpus; ++i) {
00308        packages[i] = -1;
00309        cpu_to_use[i] = -1;
00310      }
00311 
00312 
00313      /* check if Intel processor */
00314      hw_info=&(_papi_hwi_system_info.hw_info);
00315 
00316      /* Ugh can't use PAPI_get_hardware_info() if 
00317     PAPI library not done initializing yet */
00318 
00319      if (hw_info->vendor!=PAPI_VENDOR_INTEL) {
00320         strncpy(_rapl_vector.cmp_info.disabled_reason,
00321         "Not an Intel processor",PAPI_MAX_STR_LEN);
00322         return PAPI_ENOSUPP;
00323      }
00324 
00325      /* check if SandyBridge */
00326 
00327      if (hw_info->cpuid_family==6) {
00328        if (hw_info->cpuid_model==42) {
00329       /* SandyBridge */
00330           package_avail=1;
00331           pp0_avail=1;
00332           pp1_avail=1;
00333           dram_avail=0;
00334        }
00335        else if (hw_info->cpuid_model==45) {
00336       /* SandyBridge-EP */
00337           package_avail=1;
00338           pp0_avail=1;
00339           pp1_avail=0;
00340           dram_avail=1;
00341        }
00342        else if (hw_info->cpuid_model==58) {
00343       /* IvyBridge */
00344           package_avail=1;
00345           pp0_avail=1;
00346           pp1_avail=1;
00347           dram_avail=0;
00348        }    
00349        else if (hw_info->cpuid_model==62) {
00350       /* IvyBridge-EP */
00351           package_avail=1;
00352           pp0_avail=1;
00353           pp1_avail=0;
00354           dram_avail=1;
00355        }
00356        else if (hw_info->cpuid_model==60 || hw_info->cpuid_model==69 || hw_info->cpuid_model==70 ) {
00357       /* Haswell */
00358           package_avail=1;
00359           pp0_avail=1;
00360           pp1_avail=1;dram_avail=0;
00361        }
00362        else {
00363      /* not a supported model */
00364      strncpy(_rapl_vector.cmp_info.disabled_reason,
00365          "CPU model not supported",
00366          PAPI_MAX_STR_LEN);
00367      return PAPI_ENOIMPL;
00368        }
00369      }
00370      else {
00371        /* Not a family 6 machine */
00372        strncpy(_rapl_vector.cmp_info.disabled_reason,
00373            "CPU family not supported",PAPI_MAX_STR_LEN);
00374        return PAPI_ENOIMPL;
00375      }
00376 
00377 
00378      /* Detect how many packages */
00379      j=0;
00380      while(1) {
00381        int num_read;
00382 
00383        sprintf(filename,
00384            "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
00385        fff=fopen(filename,"r");
00386        if (fff==NULL) break;
00387        num_read=fscanf(fff,"%d",&package);
00388        fclose(fff);
00389        if (num_read!=1) {
00390       fprintf(stderr,"error reading %s\n",filename);
00391        }
00392 
00393        /* Check if a new package */
00394        if (package < nr_cpus) {
00395          if (packages[package] == -1) {
00396            SUBDBG("Found package %d out of total %d\n",package,num_packages);
00397        packages[package]=package;
00398        cpu_to_use[package]=j;
00399        num_packages++;
00400          }
00401        } else {
00402      SUBDBG("Package outside of allowed range\n");
00403      strncpy(_rapl_vector.cmp_info.disabled_reason,
00404         "Package outside of allowed range",PAPI_MAX_STR_LEN);
00405      return PAPI_ESYS;
00406        }
00407 
00408        j++;
00409      }
00410      num_cpus=j;
00411 
00412      if (num_packages==0) {
00413         SUBDBG("Can't access /dev/cpu/*/msr\n");
00414     strncpy(_rapl_vector.cmp_info.disabled_reason,
00415         "Can't access /dev/cpu/*/msr",PAPI_MAX_STR_LEN);
00416     return PAPI_ESYS;
00417      }
00418 
00419      SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
00420 
00421      /* Init fd_array */
00422 
00423      fd_array=papi_calloc(sizeof(struct fd_array_t),num_cpus);
00424      if (fd_array==NULL) return PAPI_ENOMEM;
00425 
00426      fd=open_fd(cpu_to_use[0]);
00427      if (fd<0) {
00428         sprintf(_rapl_vector.cmp_info.disabled_reason,
00429         "Can't open fd for cpu0: %s",strerror(errno));
00430         return PAPI_ESYS;
00431      }
00432 
00433      /* Calculate the units used */
00434      result=read_msr(fd,MSR_RAPL_POWER_UNIT);
00435   
00436      /* units are 0.5^UNIT_VALUE */
00437      /* which is the same as 1/(2^UNIT_VALUE) */
00438 
00439      power_divisor=1<<((result>>POWER_UNIT_OFFSET)&POWER_UNIT_MASK);
00440      energy_divisor=1<<((result>>ENERGY_UNIT_OFFSET)&ENERGY_UNIT_MASK);
00441      time_divisor=1<<((result>>TIME_UNIT_OFFSET)&TIME_UNIT_MASK);
00442 
00443      SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
00444      SUBDBG("Energy units = %.8fJ\n",1.0/energy_divisor);
00445      SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
00446 
00447      /* Allocate space for events */
00448      /* Include room for both counts and scaled values */
00449 
00450      num_events= ((package_avail*num_packages) +
00451                  (pp0_avail*num_packages) +
00452                  (pp1_avail*num_packages) +
00453                  (dram_avail*num_packages) + 
00454                  (4*num_packages)) * 2;
00455 
00456      rapl_native_events = (_rapl_native_event_entry_t*)
00457           papi_calloc(sizeof(_rapl_native_event_entry_t),num_events);
00458 
00459 
00460      i = 0;
00461      k = num_events/2;
00462      
00463      /* Create events for package power info */
00464 
00465      for(j=0;j<num_packages;j++) {
00466         sprintf(rapl_native_events[i].name,
00467             "THERMAL_SPEC_CNT:PACKAGE%d",j);
00468         sprintf(rapl_native_events[i].description,
00469            "Thermal specification in counts; package %d",j);
00470         rapl_native_events[i].fd_offset=cpu_to_use[j];
00471         rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00472         rapl_native_events[i].resources.selector = i + 1;
00473         rapl_native_events[i].type=PACKAGE_THERMAL_CNT;
00474         rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00475 
00476         sprintf(rapl_native_events[k].name,
00477             "THERMAL_SPEC:PACKAGE%d",j);
00478         strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
00479         sprintf(rapl_native_events[k].description,
00480            "Thermal specification for package %d",j);
00481         rapl_native_events[k].fd_offset=cpu_to_use[j];
00482         rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
00483         rapl_native_events[k].resources.selector = k + 1;
00484         rapl_native_events[k].type=PACKAGE_THERMAL;
00485         rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
00486 
00487         i++;
00488         k++;
00489      }
00490 
00491      for(j=0;j<num_packages;j++) {
00492         sprintf(rapl_native_events[i].name,
00493             "MINIMUM_POWER_CNT:PACKAGE%d",j);
00494         sprintf(rapl_native_events[i].description,
00495            "Minimum power in counts; package %d",j);
00496         rapl_native_events[i].fd_offset=cpu_to_use[j];
00497         rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00498         rapl_native_events[i].resources.selector = i + 1;
00499         rapl_native_events[i].type=PACKAGE_MINIMUM_CNT;
00500         rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00501 
00502         sprintf(rapl_native_events[k].name,
00503             "MINIMUM_POWER:PACKAGE%d",j);
00504         strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
00505         sprintf(rapl_native_events[k].description,
00506            "Minimum power for package %d",j);
00507         rapl_native_events[k].fd_offset=cpu_to_use[j];
00508         rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
00509         rapl_native_events[k].resources.selector = k + 1;
00510         rapl_native_events[k].type=PACKAGE_MINIMUM;
00511         rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
00512 
00513         i++;
00514         k++;
00515      }
00516 
00517      for(j=0;j<num_packages;j++) {
00518         sprintf(rapl_native_events[i].name,
00519             "MAXIMUM_POWER_CNT:PACKAGE%d",j);
00520         sprintf(rapl_native_events[i].description,
00521            "Maximum power in counts; package %d",j);
00522         rapl_native_events[i].fd_offset=cpu_to_use[j];
00523         rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00524         rapl_native_events[i].resources.selector = i + 1;
00525         rapl_native_events[i].type=PACKAGE_MAXIMUM_CNT;
00526         rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00527 
00528         sprintf(rapl_native_events[k].name,
00529             "MAXIMUM_POWER:PACKAGE%d",j);
00530         strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
00531         sprintf(rapl_native_events[k].description,
00532            "Maximum power for package %d",j);
00533         rapl_native_events[k].fd_offset=cpu_to_use[j];
00534         rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
00535         rapl_native_events[k].resources.selector = k + 1;
00536         rapl_native_events[k].type=PACKAGE_MAXIMUM;
00537         rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
00538 
00539         i++;
00540         k++;
00541      }
00542 
00543      for(j=0;j<num_packages;j++) {
00544         sprintf(rapl_native_events[i].name,
00545             "MAXIMUM_TIME_WINDOW_CNT:PACKAGE%d",j);
00546         sprintf(rapl_native_events[i].description,
00547            "Maximum time window in counts; package %d",j);
00548         rapl_native_events[i].fd_offset=cpu_to_use[j];
00549         rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00550         rapl_native_events[i].resources.selector = i + 1;
00551         rapl_native_events[i].type=PACKAGE_TIME_WINDOW_CNT;
00552         rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00553 
00554         sprintf(rapl_native_events[k].name,
00555             "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
00556         strncpy(rapl_native_events[k].units,"s",PAPI_MIN_STR_LEN);
00557         sprintf(rapl_native_events[k].description,
00558            "Maximum time window for package %d",j);
00559         rapl_native_events[k].fd_offset=cpu_to_use[j];
00560         rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
00561         rapl_native_events[k].resources.selector = k + 1;
00562         rapl_native_events[k].type=PACKAGE_TIME_WINDOW;
00563         rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
00564 
00565         i++;
00566         k++;
00567      }
00568 
00569      /* Create Events for energy measurements */
00570 
00571      if (package_avail) {
00572         for(j=0;j<num_packages;j++) {
00573             sprintf(rapl_native_events[i].name,
00574                 "PACKAGE_ENERGY_CNT:PACKAGE%d",j);
00575             sprintf(rapl_native_events[i].description,
00576                 "Energy used in counts by chip package %d",j);
00577             rapl_native_events[i].fd_offset=cpu_to_use[j];
00578             rapl_native_events[i].msr=MSR_PKG_ENERGY_STATUS;
00579             rapl_native_events[i].resources.selector = i + 1;
00580             rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
00581             rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00582 
00583             sprintf(rapl_native_events[k].name,
00584                 "PACKAGE_ENERGY:PACKAGE%d",j);
00585             strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
00586             sprintf(rapl_native_events[k].description,
00587                 "Energy used by chip package %d",j);
00588             rapl_native_events[k].fd_offset=cpu_to_use[j];
00589             rapl_native_events[k].msr=MSR_PKG_ENERGY_STATUS;
00590             rapl_native_events[k].resources.selector = k + 1;
00591             rapl_native_events[k].type=PACKAGE_ENERGY;
00592             rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
00593 
00594             i++;
00595             k++;
00596         }
00597      }
00598 
00599      if (pp1_avail) {
00600         for(j=0;j<num_packages;j++) {
00601             sprintf(rapl_native_events[i].name,
00602                 "PP1_ENERGY_CNT:PACKAGE%d",j);
00603             sprintf(rapl_native_events[i].description,
00604                 "Energy used in counts by Power Plane 1 (Often GPU) on package %d",j);
00605             rapl_native_events[i].fd_offset=cpu_to_use[j];
00606             rapl_native_events[i].msr=MSR_PP1_ENERGY_STATUS;
00607             rapl_native_events[i].resources.selector = i + 1;
00608             rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
00609             rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00610 
00611             sprintf(rapl_native_events[k].name,
00612                 "PP1_ENERGY:PACKAGE%d",j);
00613             strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
00614             sprintf(rapl_native_events[k].description,
00615                 "Energy used by Power Plane 1 (Often GPU) on package %d",j);
00616             rapl_native_events[k].fd_offset=cpu_to_use[j];
00617             rapl_native_events[k].msr=MSR_PP1_ENERGY_STATUS;
00618             rapl_native_events[k].resources.selector = k + 1;
00619             rapl_native_events[k].type=PACKAGE_ENERGY;
00620             rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
00621 
00622             i++;
00623             k++;
00624         }
00625      }
00626 
00627      if (dram_avail) {
00628         for(j=0;j<num_packages;j++) {
00629             sprintf(rapl_native_events[i].name,
00630                 "DRAM_ENERGY_CNT:PACKAGE%d",j);
00631             sprintf(rapl_native_events[i].description,
00632                 "Energy used in counts by DRAM on package %d",j);
00633             rapl_native_events[i].fd_offset=cpu_to_use[j];
00634             rapl_native_events[i].msr=MSR_DRAM_ENERGY_STATUS;
00635             rapl_native_events[i].resources.selector = i + 1;
00636             rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
00637             rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00638 
00639             sprintf(rapl_native_events[k].name,
00640                 "DRAM_ENERGY:PACKAGE%d",j);
00641             strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
00642             sprintf(rapl_native_events[k].description,
00643                 "Energy used by DRAM on package %d",j);
00644             rapl_native_events[k].fd_offset=cpu_to_use[j];
00645             rapl_native_events[k].msr=MSR_DRAM_ENERGY_STATUS;
00646             rapl_native_events[k].resources.selector = k + 1;
00647             rapl_native_events[k].type=PACKAGE_ENERGY;
00648             rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
00649 
00650             i++;
00651             k++;
00652         }
00653      }
00654 
00655      if (pp0_avail) {
00656         for(j=0;j<num_packages;j++) {
00657             sprintf(rapl_native_events[i].name,
00658                 "PP0_ENERGY_CNT:PACKAGE%d",j);
00659             sprintf(rapl_native_events[i].description,
00660                 "Energy used in counts by all cores in package %d",j);
00661             rapl_native_events[i].fd_offset=cpu_to_use[j];
00662             rapl_native_events[i].msr=MSR_PP0_ENERGY_STATUS;
00663             rapl_native_events[i].resources.selector = i + 1;
00664             rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
00665             rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00666 
00667             sprintf(rapl_native_events[k].name,
00668                 "PP0_ENERGY:PACKAGE%d",j);
00669             strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
00670             sprintf(rapl_native_events[k].description,
00671                 "Energy used by all cores in package %d",j);
00672             rapl_native_events[k].fd_offset=cpu_to_use[j];
00673             rapl_native_events[k].msr=MSR_PP0_ENERGY_STATUS;
00674             rapl_native_events[k].resources.selector = k + 1;
00675             rapl_native_events[k].type=PACKAGE_ENERGY;
00676             rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
00677 
00678             i++;
00679             k++;
00680         }
00681      }
00682 
00683      /* Export the total number of events available */
00684      _rapl_vector.cmp_info.num_native_events = num_events;
00685 
00686      _rapl_vector.cmp_info.num_cntrs = num_events;
00687      _rapl_vector.cmp_info.num_mpx_cntrs = num_events;
00688 
00689 
00690      /* Export the component id */
00691      _rapl_vector.cmp_info.CmpIdx = cidx;
00692 
00693      return PAPI_OK;
00694 }
00695 
00696 
00697 /*
00698  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00699  * functions
00700  */
00701 int 
00702 _rapl_init_control_state( hwd_control_state_t *ctl)
00703 {
00704 
00705   _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00706   int i;
00707   
00708   for(i=0;i<RAPL_MAX_COUNTERS;i++) {
00709      control->being_measured[i]=0;
00710   }
00711 
00712   return PAPI_OK;
00713 }
00714 
00715 int 
00716 _rapl_start( hwd_context_t *ctx, hwd_control_state_t *ctl)
00717 {
00718   _rapl_context_t* context = (_rapl_context_t*) ctx;
00719   _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00720   long long now = PAPI_get_real_usec();
00721   int i;
00722 
00723   for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
00724      if ((control->being_measured[i]) && (control->need_difference[i])) {
00725         context->start_value[i]=read_rapl_value(i);
00726      }
00727   }
00728 
00729   control->lastupdate = now;
00730 
00731   return PAPI_OK;
00732 }
00733 
00734 int 
00735 _rapl_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00736 {
00737 
00738     /* read values */
00739     _rapl_context_t* context = (_rapl_context_t*) ctx;
00740     _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00741     long long now = PAPI_get_real_usec();
00742     int i;
00743     long long temp;
00744 
00745     for ( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
00746         if (control->being_measured[i]) {
00747             temp = read_rapl_value(i);
00748             if (context->start_value[i])
00749             if (control->need_difference[i]) {
00750                 /* test for wrap around */
00751                 if (temp < context->start_value[i] ) {
00752                     SUBDBG("Wraparound!\nstart:\t0x%016x\ttemp:\t0x%016x",
00753                         (unsigned)context->start_value[i], (unsigned)temp);
00754                     temp += (0x100000000 - context->start_value[i]);
00755                     SUBDBG("\tresult:\t0x%016x\n", (unsigned)temp);
00756                 } else {
00757                     temp -= context->start_value[i];
00758                 }
00759             }
00760             control->count[i] = convert_rapl_energy( i, temp );
00761         }
00762     }
00763     control->lastupdate = now;
00764     return PAPI_OK;
00765 }
00766 
00767 /* Shutdown a thread */
00768 int
00769 _rapl_shutdown_thread( hwd_context_t *ctx )
00770 {
00771   ( void ) ctx;
00772   return PAPI_OK;
00773 }
00774 
00775 int 
00776 _rapl_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00777         long long **events, int flags)
00778 {
00779     (void) flags;
00780 
00781     _rapl_stop( ctx, ctl );
00782 
00783     /* Pass back a pointer to our results */
00784     *events = ((_rapl_control_state_t*) ctl)->count;
00785 
00786     return PAPI_OK;
00787 }
00788 
00789 
00790 /*
00791  * Clean up what was setup in  rapl_init_component().
00792  */
00793 int 
00794 _rapl_shutdown_component( void ) 
00795 {
00796     int i;
00797 
00798     if (rapl_native_events) papi_free(rapl_native_events);
00799     if (fd_array) {
00800        for(i=0;i<num_cpus;i++) {
00801       if (fd_array[i].open) close(fd_array[i].fd);
00802        }
00803        papi_free(fd_array);
00804     }
00805 
00806     return PAPI_OK;
00807 }
00808 
00809 
00810 /* This function sets various options in the component
00811  * The valid codes being passed in are PAPI_SET_DEFDOM,
00812  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00813  */
00814 int
00815 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
00816 {
00817     ( void ) ctx;
00818     ( void ) code;
00819     ( void ) option;
00820 
00821     return PAPI_OK;
00822 }
00823 
00824 
00825 int
00826 _rapl_update_control_state( hwd_control_state_t *ctl,
00827                 NativeInfo_t *native, int count,
00828                 hwd_context_t *ctx )
00829 {
00830   int i, index;
00831     ( void ) ctx;
00832 
00833     _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00834 
00835     /* Ugh, what is this native[] stuff all about ?*/
00836     /* Mostly remap stuff in papi_internal */
00837 
00838     for(i=0;i<RAPL_MAX_COUNTERS;i++) {
00839        control->being_measured[i]=0;
00840     }
00841 
00842     for( i = 0; i < count; i++ ) {
00843        index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
00844        native[i].ni_position=rapl_native_events[index].resources.selector - 1;
00845        control->being_measured[index]=1;
00846 
00847        /* Only need to subtract if it's a PACKAGE_ENERGY or ENERGY_CNT type */
00848        control->need_difference[index]=
00849         (rapl_native_events[index].type==PACKAGE_ENERGY 
00850         || rapl_native_events[index].type==PACKAGE_ENERGY_CNT);
00851     }
00852 
00853     return PAPI_OK;
00854 }
00855 
00856 
00857 /*
00858  * This function has to set the bits needed to count different domains
00859  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00860  * By default return PAPI_EINVAL if none of those are specified
00861  * and PAPI_OK with success
00862  * PAPI_DOM_USER is only user context is counted
00863  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00864  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00865  * PAPI_DOM_ALL   is all of the domains
00866  */
00867 int
00868 _rapl_set_domain( hwd_control_state_t *ctl, int domain )
00869 {
00870     ( void ) ctl;
00871     (void) domain;
00872     
00873     /* In theory we only support system-wide mode */
00874     /* How to best handle that? */
00875 
00876     return PAPI_OK;
00877 }
00878 
00879 
00880 int
00881 _rapl_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
00882 {
00883     ( void ) ctx;
00884     ( void ) ctl;
00885     
00886     return PAPI_OK;
00887 }
00888 
00889 
00890 /*
00891  * Native Event functions
00892  */
00893 int
00894 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
00895 {
00896 
00897      int index;
00898 
00899      switch ( modifier ) {
00900 
00901     case PAPI_ENUM_FIRST:
00902 
00903        if (num_events==0) {
00904           return PAPI_ENOEVNT;
00905        }
00906        *EventCode = 0;
00907 
00908        return PAPI_OK;
00909         
00910 
00911     case PAPI_ENUM_EVENTS:
00912     
00913        index = *EventCode & PAPI_NATIVE_AND_MASK;
00914 
00915        if ( index < num_events - 1 ) {
00916           *EventCode = *EventCode + 1;
00917           return PAPI_OK;
00918        } else {
00919           return PAPI_ENOEVNT;
00920        }
00921        break;
00922     
00923     default:
00924         return PAPI_EINVAL;
00925     }
00926 
00927     return PAPI_EINVAL;
00928 }
00929 
00930 /*
00931  *
00932  */
00933 int
00934 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00935 {
00936 
00937      int index = EventCode & PAPI_NATIVE_AND_MASK;
00938 
00939      if ( index >= 0 && index < num_events ) {
00940     strncpy( name, rapl_native_events[index].name, len );
00941     return PAPI_OK;
00942      }
00943 
00944      return PAPI_ENOEVNT;
00945 }
00946 
00947 /*
00948  *
00949  */
00950 int
00951 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00952 {
00953      int index = EventCode;
00954 
00955      if ( index >= 0 && index < num_events ) {
00956     strncpy( name, rapl_native_events[index].description, len );
00957     return PAPI_OK;
00958      }
00959      return PAPI_ENOEVNT;
00960 }
00961 
00962 int
00963 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 
00964 {
00965 
00966   int index = EventCode;
00967 
00968   if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
00969 
00970   strncpy( info->symbol, rapl_native_events[index].name, 
00971        sizeof(info->symbol));
00972 
00973   strncpy( info->long_descr, rapl_native_events[index].description, 
00974        sizeof(info->symbol));
00975 
00976   strncpy( info->units, rapl_native_events[index].units, 
00977        sizeof(info->units));
00978 
00979   info->data_type = rapl_native_events[index].return_type;
00980 
00981   return PAPI_OK;
00982 }
00983 
00984 
00985 
00986 papi_vector_t _rapl_vector = {
00987     .cmp_info = { /* (unspecified values are initialized to 0) */
00988        .name = "rapl",
00989        .short_name = "rapl",
00990        .description = "Linux SandyBridge RAPL energy measurements",
00991        .version = "5.3.0",
00992        .default_domain = PAPI_DOM_USER,
00993        .default_granularity = PAPI_GRN_THR,
00994        .available_granularities = PAPI_GRN_THR,
00995        .hardware_intr_sig = PAPI_INT_SIGNAL,
00996        .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00997     },
00998 
00999     /* sizes of framework-opaque component-private structures */
01000     .size = {
01001     .context = sizeof ( _rapl_context_t ),
01002     .control_state = sizeof ( _rapl_control_state_t ),
01003     .reg_value = sizeof ( _rapl_register_t ),
01004     .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
01005     },
01006     /* function pointers in this component */
01007     .init_thread =          _rapl_init_thread,
01008     .init_component =       _rapl_init_component,
01009     .init_control_state =   _rapl_init_control_state,
01010     .start =                _rapl_start,
01011     .stop =                 _rapl_stop,
01012     .read =                 _rapl_read,
01013     .shutdown_thread =      _rapl_shutdown_thread,
01014     .shutdown_component =   _rapl_shutdown_component,
01015     .ctl =                  _rapl_ctl,
01016 
01017     .update_control_state = _rapl_update_control_state,
01018     .set_domain =           _rapl_set_domain,
01019     .reset =                _rapl_reset,
01020 
01021     .ntv_enum_events =      _rapl_ntv_enum_events,
01022     .ntv_code_to_name =     _rapl_ntv_code_to_name,
01023     .ntv_code_to_descr =    _rapl_ntv_code_to_descr,
01024     .ntv_code_to_info =     _rapl_ntv_code_to_info,
01025 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines