PAPI 7.1.0.0
Loading...
Searching...
No Matches
linux-sensors-ppc.c
Go to the documentation of this file.
1
10#include <stdio.h>
11#include <dirent.h>
12#include <unistd.h>
13#include <dirent.h>
14#include <fcntl.h>
15#include <string.h>
16#include <stdint.h>
17#include <errno.h>
18#include <unistd.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <pthread.h>
22#include <inttypes.h>
23
24#include "linux-sensors-ppc.h"
25
26// The following macro exit if a string function has an error. It should
27// never happen; but it is necessary to prevent compiler warnings. We print
28// something just in case there is programmer error in invoking the function.
29#define HANDLE_STRING_ERROR {fprintf(stderr,"%s:%i unexpected string function error.\n",__FILE__,__LINE__); exit(-1);}
30
32
33/***************************************************************************/
34/****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
35/***************************************************************************/
36
37/* Null terminated version of strncpy */
38static char *
39_local_strlcpy( char *dst, const char *src, size_t size )
40{
41 char *retval = strncpy( dst, src, size );
42 if ( size > 0 ) dst[size-1] = '\0';
43
44 return( retval );
45}
46
47#define DESC_LINE_SIZE_ALLOWED 66
48static void
49_space_padding(char *buf, size_t max)
50{
51 size_t len = strlen(buf);
52 /* 80 columns - 12 header - 2 footer*/
53 size_t nlines = 1+ len / DESC_LINE_SIZE_ALLOWED, c = len;
54 /* space_padding */
55 for (; c < nlines * DESC_LINE_SIZE_ALLOWED && c < max-1; ++c) buf[c] = ' ';
56 buf[c] = '\0';
57}
58
66static void
67refresh_data(int occ_id, int forced)
68{
69 long long now = PAPI_get_real_nsec();
70 if (forced || now > last_refresh[occ_id] + OCC_REFRESH_TIME) {
71 void *buf = double_ping[occ_id];
72
73 uint32_t ping_off = be32toh(occ_hdr[occ_id]->reading_ping_offset);
74 uint32_t pong_off = be32toh(occ_hdr[occ_id]->reading_pong_offset);
75
76 lseek (event_fd, occ_id * OCC_SENSOR_DATA_BLOCK_SIZE + ping_off, SEEK_SET);
77
78 /* To limit risks of begin desynchronized, we read one chunk */
79 /* In memory, ping and pong are 40kB, with a 4kB buffer
80 * of nothingness in between */
81 int to_read = pong_off - ping_off + OCC_PING_DATA_BLOCK_SIZE;
82
83 int rc, bytes;
84 /* copy memory iteratively until the full chunk is saved */
85 for (rc = bytes = 0; bytes < to_read; bytes += rc) {
86 rc = read(event_fd, buf + bytes, to_read - bytes);
87 if (!rc || rc < 0) /* done */ break;
88 }
89
91 double_ping[occ_id] = ping[occ_id];
92 ping[occ_id] = buf;
93 pong[occ_id] = ping[occ_id] + (pong_off - ping_off);
94 last_refresh[occ_id] = now;
96 }
97}
98static double
99_pow(int x, int y)
100{
101 if (0 == y) return 1.;
102 if (0 == x) return 0.;
103 if (0 > y) return 1. / _pow(x, -y);
104 if (1 == y) return 1. * x;
105 if (0 == y%2) return _pow(x, y/2) * _pow(x, y/2);
106 else return _pow(x, y/2) * _pow(x, y/2) * x;
107}
108
109#define TO_FP(f) ((f >> 8) * _pow(10, ((int8_t)(f & 0xFF))))
110
111static long long
112read_sensors_ppc_record(int s, int gidx, int midx)
113{
114 uint64_t value = 41;
115 uint32_t offset = be32toh(occ_names[s][gidx].reading_offset);
116 uint32_t scale = be32toh(occ_names[s][gidx].scale_factor);
117 uint32_t freq = be32toh(occ_names[s][gidx].freq);
118
119 occ_sensor_record_t *record = NULL;
120 /* Let's see if the data segment needs a refresh */
121 refresh_data(s, 0);
122
124 occ_sensor_record_t *sping = (occ_sensor_record_t *)((uint64_t)ping[s] + offset);
125 occ_sensor_record_t *spong = (occ_sensor_record_t *)((uint64_t)pong[s] + offset);
126
127 if (*ping && *pong) {
128 if (be64toh(sping->timestamp) > be64toh(spong->timestamp))
129 record = sping;
130 else
131 record = spong;
132 } else if (*ping && !*pong) {
133 record = sping;
134 } else if (!*ping && *pong) {
135 record = spong;
136 } else if (!*ping && !*pong) {
137 return value;
138 }
139
140 switch (midx) {
142 /* freq, per sensor, contains freq sampling for the last 500us of accumulation */
143 value = (uint64_t)(be64toh(record->accumulator) / TO_FP(freq));
144 break;
145 default:
146 /* That one might upset people
147 * All the entries below sample (including it) are uint16_t packed */
148 value = (uint64_t)(be16toh((&record->sample)[midx]) * TO_FP(scale));
149 break;
150 }
152
153 return value;
154}
155
156static long long
158{
159 uint32_t offset = be32toh(occ_names[s][gidx].reading_offset);
160 uint32_t scale = be32toh(occ_names[s][gidx].scale_factor);
161
162 occ_sensor_counter_t *counter = NULL;
163
164 refresh_data(s, 0);
165
167 occ_sensor_counter_t *sping = (occ_sensor_counter_t *)((uint64_t)ping[s] + offset);
168 occ_sensor_counter_t *spong = (occ_sensor_counter_t *)((uint64_t)pong[s] + offset);
169
170 if (*ping && *pong) {
171 if (be64toh(sping->timestamp) > be64toh(spong->timestamp))
172 counter = sping;
173 else
174 counter = spong;
175 } else if (*ping && !*pong) {
176 counter = sping;
177 } else if (!*ping && *pong) {
178 counter = spong;
179 } else if (!*ping && !*pong) {
180 return 40;
181 }
182
183 uint64_t value = be64toh(counter->accumulator) * TO_FP(scale);
185
186 return value;
187}
188
189static int
191{
192 int s = 0;
193 /* get OCC s from index */
194 for (; index > occ_num_events[s+1] && s < MAX_OCCS; ++s);
195
196 int ridx = index - occ_num_events[s];
197 int gidx = ridx / OCC_SENSORS_MASKS;
199}
200
201static long long
203{
204 int s = 0;
205 /* get OCC s from index */
206 for (; index > occ_num_events[s+1] && s < MAX_OCCS; ++s);
207
208 int ridx = index - occ_num_events[s];
209 int gidx = ridx / OCC_SENSORS_MASKS;
210 int midx = ridx % OCC_SENSORS_MASKS;
211 uint8_t structure_type = occ_names[s][gidx].structure_type;
212
213 switch (structure_type) {
215 return read_sensors_ppc_record(s, gidx, midx);
217 if (OCC_SENSORS_ACCUMULATOR_TAG == midx)
218 return read_sensors_ppc_counter(s, gidx);
219 /* fall through */
220 /* counters only return the accumulator */
221 default:
222 return 42;
223 }
224}
225
226
227/************************* PAPI Functions **********************************/
228
229/*
230 * This is called whenever a thread is initialized
231 */
232static int
234{
235 (void) ctx;
236
237 return PAPI_OK;
238}
239
240/*
241 * Called when PAPI process is initialized (i.e. PAPI_library_init)
242 */
243static int
245{
246 int retval = PAPI_OK;
247 int s = -1;
248 int strErr;
249 char events_dir[128];
250 char event_path[128];
251 char *strCpy;
252 DIR *events;
253
254 const PAPI_hw_info_t *hw_info;
256
257 if ( PAPI_VENDOR_IBM != hw_info->vendor ) {
258 strCpy=strncpy(_sensors_ppc_vector.cmp_info.disabled_reason, "Not an IBM processor", PAPI_MAX_STR_LEN);
260 if (strCpy == NULL) HANDLE_STRING_ERROR;
262 goto fn_fail;
263 }
264
265 int ret = snprintf(events_dir, sizeof(events_dir), "/sys/firmware/opal/exports/");
266 if (ret <= 0 || (int)(sizeof(events_dir)) <= ret) HANDLE_STRING_ERROR;
267 if (NULL == (events = opendir(events_dir))) {
269 "%s:%i Could not open events_dir='%s'.", __FILE__, __LINE__, events_dir);
273 goto fn_fail;
274 }
275
276 ret = snprintf(event_path, sizeof(event_path), "%s%s", events_dir, pkg_sys_name);
277 if (ret <= 0 || (int)(sizeof(event_path)) <= ret) HANDLE_STRING_ERROR;
278 if (-1 == access(event_path, F_OK)) {
280 "%s:%i Could not access event_path='%s'.", __FILE__, __LINE__, event_path);
284 goto fn_fail;
285 }
286
287 event_fd = open(event_path, pkg_sys_flag);
288 if (event_fd < 0) {
290 "%s:%i Could not open event_path='%s'.", __FILE__, __LINE__, event_path);
294 goto fn_fail;
295 }
296
297 memset(occ_num_events, 0, (MAX_OCCS+1)*sizeof(int));
298 num_events = 0;
299 for ( s = 0; s < MAX_OCCS; ++s ) {
300 void *buf = NULL;
301 if (NULL == (buf = malloc(OCC_SENSOR_DATA_BLOCK_SIZE))) {
303 "%s:%i Failed to alloc %i bytes for buf.", __FILE__, __LINE__, OCC_SENSOR_DATA_BLOCK_SIZE);
307 goto fn_fail;
308 }
309
311
313
314 int rc, bytes;
315 /* copy memory iteratively until the full chunk is saved */
316 for (rc = bytes = 0; bytes < OCC_SENSOR_DATA_BLOCK_SIZE; bytes += rc) {
317 rc = read(event_fd, buf + bytes, OCC_SENSOR_DATA_BLOCK_SIZE - bytes);
318 if (!rc || rc < 0) /* done */ break;
319 }
320
321 if (OCC_SENSOR_DATA_BLOCK_SIZE != bytes) {
322 /* We are running out of OCCs, let's stop there */
323 free(buf);
324 num_occs = s;
325 s = MAX_OCCS;
326 continue;
327 }
328
329 occ_sensor_name_t *names = (occ_sensor_name_t*)((uint64_t)buf + be32toh(occ_hdr[s]->names_offset));
330 int n_sensors = be16toh(occ_hdr[s]->nr_sensors);
331
332 /* Prepare the double buffering for the ping/pong buffers */
333 int ping_off = be32toh(occ_hdr[s]->reading_ping_offset);
334 int pong_off = be32toh(occ_hdr[s]->reading_pong_offset);
335 /* Ping and pong are both 40kB, and we have a 4kB separator.
336 * In theory, the distance between the beginnings of ping and pong is (40+4) kB.
337 * But they expose an offset for the pong buffer.
338 * So I won't trust the 4kB distance between buffers, and compute the buffer size
339 * based on on both offsets ans the size of pong */
340 int buff_size = pong_off - ping_off + OCC_PING_DATA_BLOCK_SIZE;
341
342 ping[s] = (uint32_t*)malloc(buff_size);
343 if (ping[s] == NULL) {
345 "%s:%i Failed to alloc %i bytes for ping[%i].", __FILE__, __LINE__, buff_size, s);
349 goto fn_fail;
350 }
351
352 double_ping[s] = (uint32_t*)malloc(buff_size);
353 if (double_ping[s] == NULL) {
355 "%s:%i Failed to alloc %i bytes for double_ping[%i].", __FILE__, __LINE__, buff_size, s);
359 goto fn_fail;
360 }
361
363
364 refresh_data(s, 1);
365
366 /* Not all events will exist, counter-based evens only have an accumulator to report */
367 occ_num_events[s+1] = occ_num_events[s] + (n_sensors * OCC_SENSORS_MASKS);
368
369 num_events += (n_sensors * OCC_SENSORS_MASKS);
370
371 /* occ_names map to read-only information that change only after reboot */
372 occ_names[s] = names;
373 }
374
375 /* Export the total number of events available */
379
380 /* 0 active events */
381 num_events = 0;
382
383 /* Export the component id */
385
386 fn_exit:
387 _papi_hwd[cidx]->cmp_info.disabled = retval;
388 return retval;
389 fn_fail:
390 goto fn_exit;
391}
392
393
394/*
395 * Control of counters (Reading/Writing/Starting/Stopping/Setup)
396 * functions
397 */
398static int
400{
402
403 memset( control, 0, sizeof ( _sensors_ppc_control_state_t ) );
404
405 return PAPI_OK;
406}
407
408static int
410{
411 SUBDBG("Enter _sensors_ppc_start\n");
412
415
416 memset( context->start_value, 0, sizeof(long long) * SENSORS_PPC_MAX_COUNTERS);
417
418 int c, i;
419 for( c = 0; c < num_events; c++ ) {
420 i = control->which_counter[c];
423 }
424
425 /* At the end, ctx->start if full of 0s, except for counter-type sensors */
426 return PAPI_OK;
427}
428
429static int
431{
432 (void) ctx;
433 (void) ctl;
434
435 /* not sure what the side effect of stop is supposed to be, do a read? */
436 return PAPI_OK;
437}
438
439/* Shutdown a thread */
440static int
442{
443 (void) ctx;
444
445 return PAPI_OK;
446}
447
448
449static int
451 long long **events, int flags )
452{
453 SUBDBG("Enter _sensors_ppc_read\n");
454
455 (void) flags;
458
459 long long start_val = 0;
460 long long curr_val = 0;
461 int c, i;
462
463 /* c is the index in the dense array of selected counters */
464 /* using control->which_counters[c], fetch actual indices in i */
465 /* all subsequent methods use "global" indices i */
466 for ( c = 0; c < num_events; c++ ) {
467 i = control->which_counter[c];
468 start_val = context->start_value[c];
469 curr_val = read_sensors_ppc_value(i);
470
471 if (start_val) {
472 /* Make sure an event is a counter. */
474 /* Wraparound. */
475 if(start_val > curr_val) {
476 curr_val += (0x100000000 - start_val);
477 }
478 /* Normal subtraction. */
479 else if (start_val < curr_val) {
480 curr_val -= start_val;
481 }
482 }
483 }
484 control->count[c]=curr_val;
485 }
486
487 *events = ( ( _sensors_ppc_control_state_t* ) ctl )->count;
488 return PAPI_OK;
489}
490
491/*
492 * Clean up what was setup in sensors_ppc_init_component().
493 */
494static int
496{
498
499 int s;
501 for (s = 0; s < num_occs; ++s) {
502 free(occ_hdr[s]);
503 if (ping[s] != NULL) free(ping[s]);
504 if (double_ping[s] != NULL) free(double_ping[s]);
505 }
507 return PAPI_OK;
508}
509
510/* This function sets various options in the component. The valid
511 * codes being passed in are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN,
512 * PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT
513 */
514static int
516{
517 SUBDBG( "Enter: ctx: %p\n", ctx );
518 (void) ctx;
519 (void) code;
520 (void) option;
521
522 return PAPI_OK;
523}
524
525
526static int
529 hwd_context_t *ctx )
530{
531 (void) ctx;
532 int i, index;
535 if (count == 0) return PAPI_OK;
536
537 /* control contains a dense array of unsorted events */
538 for ( i = 0; i < count; i++ ) {
539 index = native[i].ni_event;
540 control->which_counter[i]=index;
541 native[i].ni_position = i;
542 }
543
544 return PAPI_OK;
545}
546
547static int
549{
550 (void) ctl;
551 if ( PAPI_DOM_ALL != domain )
552 return PAPI_EINVAL;
553 return PAPI_OK;
554}
555
556static int
558{
559 (void) ctx;
560 (void) ctl;
561
562 return PAPI_OK;
563}
564
565/*
566 * Iterator function. Given an Eventcode, returns the next valid Eventcode to consider
567 * returning anything but PAPI_OK will stop lookups and ignore next events.
568 */
569static int
570_sensors_ppc_ntv_enum_events( unsigned int *EventCode, int modifier )
571{
572 int index;
573 switch (modifier) {
574
575 case PAPI_ENUM_FIRST:
576 *EventCode = 0;
577 return PAPI_OK;
578
579 case PAPI_ENUM_EVENTS:
580 index = *EventCode & PAPI_NATIVE_AND_MASK;
581 if (index < occ_num_events[num_occs] - 1) {
582 if (_sensors_ppc_is_counter(index+1))
583 /* For counters, exposing only the accumulator,
584 * skips ghost events from _sample to _job_sched_max */
585 *EventCode = *EventCode + OCC_SENSORS_MASKS;
586 else
587 *EventCode = *EventCode + 1;
588 return PAPI_OK;
589 } else {
590 return PAPI_ENOEVNT;
591 }
592
593 default:
594 return PAPI_EINVAL;
595 }
596}
597
598/*
599 *
600 */
601static int
602_sensors_ppc_ntv_code_to_name( unsigned int EventCode, char *name, int len )
603{
604 int index = EventCode & PAPI_NATIVE_AND_MASK;
605
606 if ( index < 0 && index >= occ_num_events[num_occs] )
607 return PAPI_ENOEVNT;
608
609 int s = 0;
610 /* get OCC s from index */
611 for (; index > occ_num_events[s+1] && s < MAX_OCCS; ++s);
612
613 int ridx = index - occ_num_events[s];
614 int gidx = ridx / OCC_SENSORS_MASKS;
615 int midx = ridx % OCC_SENSORS_MASKS;
616
617 /* EventCode maps to a counter */
618 /* Counters only expose their accumulator */
620 return PAPI_ENOEVNT;
621
622 char buf[512];
623 int ret = snprintf(buf, 512, "%s:occ=%d%s", occ_names[s][gidx].name, s, sensors_ppc_fake_qualifiers[midx]);
624 if (ret <= 0 || 512 <= ret)
625 return PAPI_ENOSUPP;
626 _local_strlcpy( name, buf, len);
627
628 return PAPI_OK;
629}
630
631/* This is the optional function used by utils/papi_*_avail.
632 * Not providing it will force the tools to forge a description using
633 * ntv_code_to_desc, ntv_code_to_*.
634 */
635static int
636_sensors_ppc_ntv_code_to_info( unsigned int EventCode, PAPI_event_info_t *info )
637{
638 int index = EventCode;
639
640 if ( index < 0 || index >= occ_num_events[num_occs])
641 return PAPI_ENOEVNT;
642
643 int s = 0;
644 /* get OCC s from index */
645 for (; index > occ_num_events[s+1] && s < MAX_OCCS; ++s);
646
647 int ridx = index - occ_num_events[s];
648 int gidx = ridx / OCC_SENSORS_MASKS;
649 int midx = ridx % OCC_SENSORS_MASKS;
650
651 /* EventCode maps to a counter */
652 /* Counters only expose their accumulator */
654 return PAPI_ENOEVNT;
655
656 char buf[512];
657 int ret = snprintf(buf, 512, "%s:occ=%d%s", occ_names[s][gidx].name, s, sensors_ppc_fake_qualifiers[midx]);
658 if (ret <= 0 || 512 <= ret)
659 return PAPI_ENOSUPP;
660 _local_strlcpy( info->symbol, buf, sizeof( info->symbol ));
661 _local_strlcpy( info->units, occ_names[s][gidx].units, sizeof( info->units ) );
662 /* If it ends with:
663 * Qw: w-th Quad unit [0-5]
664 * Cxx: xx-th core [0-23]
665 * My: y-th memory channel [0-8]
666 * CHvv: vv-th memory module [0-15]
667 * or starts with:
668 * GPUz: z-th GPU [0-2]
669 * TEMPGPUz: z-th GPU [0-2]
670 * */
671 uint16_t type = be16toh(occ_names[s][gidx].type);
672 char *name = strdup(occ_names[s][gidx].name);
673 uint32_t freq = be32toh(occ_names[s][gidx].freq);
674 int tgt = -1;
675 switch(type) {
676 /* IPS, STOPDEEPACTCxx, STOPDEEPREQCxx, IPSCxx, NOTBZECxx, NOTFINCxx,
677 * MRDMy, MWRMy, PROCPWRTHROT, PROCOTTHROT, MEMPWRTHROT, MEMOTTHROT,
678 * GPUzHWTHROT, GPUzSWTHROT, GPUzSWOTTHROT, GPUzSWPWRTHROT */
680 if (!strncmp(name, "GPU", 3)) {
681 char z[] = {name[3], '\0'};
682 tgt = atoi(z);
683 name[3] = 'z';
684 if (!strncmp(name, "GPUzHWTHROT", 11))
685 ret = snprintf(buf, 512, "Total time GPU %d has been throttled by hardware (thermal or power brake)", tgt);
686 else if (!strncmp(name, "GPUzSWTHROT", 11))
687 ret = snprintf(buf, 512, "Total time GPU %d has been throttled by software for any reason", tgt);
688 else if (!strncmp(name, "GPUzSWOTTHROT", 13))
689 ret = snprintf(buf, 512, "Total time GPU %d has been throttled by software due to thermal", tgt);
690 else if (!strncmp(name, "GPUzSWPWRTHROT", 14))
691 ret = snprintf(buf, 512, "Total time GPU %d has been throttled by software due to power", tgt);
692 else
693 ret = snprintf(buf, 512, "[PERFORMANCE] Unexpected: GPU-%d %s", tgt, name);
694 }
695 else if (!strncmp(name, "IPSCxx", 4)) {
696 tgt = atoi(name+4);
697 ret = snprintf(buf, 512, "Instructions per second for core %d on this Processor", tgt);
698 }
699 else if (!strncmp(name, "IPS", 3))
700 ret = snprintf(buf, 512, "Vector sensor that takes the average of all the cores this Processor");
701 else if (!strncmp(name, "STOPDEEPACTCxx", 12)) {
702 tgt = atoi(name+12);
703 ret = snprintf(buf, 512, "Deepest actual stop state that was fully entered during sample time for core %d", tgt);
704 }
705 else if (!strncmp(name, "STOPDEEPREQCxx", 12)) {
706 tgt = atoi(name+12);
707 ret = snprintf(buf, 512, "Deepest stop state that has been requested during sample time for core %d", tgt);
708 }
709 else if (!strncmp(name, "MEMPWRTHROT", 11))
710 ret = snprintf(buf, 512, "Count of memory throttled due to power");
711 else if (!strncmp(name, "MEMOTTHROT", 10))
712 ret = snprintf(buf, 512, "Count of memory throttled due to memory Over temperature");
713 else if (!strncmp(name, "PROCOTTHROT", 11))
714 ret = snprintf(buf, 512, "Count of processor throttled for temperature");
715 else if (!strncmp(name, "PROCPWRTHROT", 12))
716 ret = snprintf(buf, 512, "Count of processor throttled due to power");
717 else if (!strncmp(name, "MWRM", 4)) {
718 tgt = atoi(name+4);
719 ret = snprintf(buf, 512, "Memory write requests per sec for MC %d", tgt);
720 }
721 else if (!strncmp(name, "MRDM", 4)) {
722 tgt = atoi(name+4);
723 ret = snprintf(buf, 512, "Memory read requests per sec for MC %d", tgt);
724 }
725 else
726 ret = snprintf(buf, 512, "[PERFORMANCE] Unexpected: %s", name);
727 break;
728
729 /* PWRSYS, PWRGPU, PWRAPSSCHvv, PWRPROC, PWRVDD, PWRVDN, PWRMEM */
731 if (!strncmp(name, "PWRSYS", 6))
732 ret = snprintf(buf, 512, "Bulk power of the system/node");
733 else if (!strncmp(name, "PWRGPU", 6))
734 ret = snprintf(buf, 512, "Power consumption for GPUs per socket (OCC) read from APSS");
735 else if (!strncmp(name, "PWRPROC", 7))
736 ret = snprintf(buf, 512, "Power consumption for this Processor");
737 else if (!strncmp(name, "PWRVDD", 6))
738 ret = snprintf(buf, 512, "Power consumption for this Processor's Vdd (calculated from AVSBus readings)");
739 else if (!strncmp(name, "PWRVDN", 6))
740 ret = snprintf(buf, 512, "Power consumption for this Processor's Vdn (nest) (calculated from AVSBus readings)");
741 else if (!strncmp(name, "PWRMEM", 6))
742 ret = snprintf(buf, 512, "Power consumption for Memory for this Processor read from APSS");
743 else if (!strncmp(name, "PWRAPSSCH", 9)) {
744 tgt = atoi(name+9);
745 ret = snprintf(buf, 512, "Power Provided by APSS channel %d", tgt);
746 }
747 else
748 ret = snprintf(buf, 512, "[POWER] Unexpected: %s", name);
749 break;
750
751 /* FREQA, FREQACxx */
753 if (!strncmp(name, "FREQACxx", 6)) {
754 tgt = atoi(name+6);
755 ret = snprintf(buf, 512, "Average/actual frequency for this processor, Core %d based on OCA data", tgt);
756 }
757 else if (!strncmp(name, "FREQA", 5))
758 ret = snprintf(buf, 512, "Average of all core frequencies for Processor");
759 else
760 ret = snprintf(buf, 512, "[FREQUENCY] Unexpected: %s", name);
761 break;
762
764 ret = snprintf(buf, 512, "[TIME] Unexpected: %s", name);
765 break;
766
767 /* UTILCxx, UTIL, NUTILCxx, MEMSPSTATMy, MEMSPMy */
769 if (!strncmp(name, "MEMSPSTATM", 10)) {
770 tgt = atoi(name+10);
771 ret = snprintf(buf, 512, "Static Memory throttle level setting for MCA %d when not in a memory throttle condition", tgt);
772 }
773 else if (!strncmp(name, "MEMSPM", 6)) {
774 tgt = atoi(name+6);
775 ret = snprintf(buf, 512, "Current Memory throttle level setting for MCA %d", tgt);
776 }
777 else if (!strncmp(name, "NUTILC", 6)) {
778 tgt = atoi(name+6);
779 ret = snprintf(buf, 512, "Normalized average utilization, rolling average of this Processor's Core %d", tgt);
780 }
781 else if (!strncmp(name, "UTILC", 5)) {
782 tgt = atoi(name+5);
783 ret = snprintf(buf, 512, "Utilization of this Processor's Core %d (where 100%% means fully utilized): NOTE: per thread HW counters are combined as appropriate to give this core level utilization sensor", tgt);
784 }
785 else if (!strncmp(name, "UTIL", 4))
786 ret = snprintf(buf, 512, "Average of all Cores UTILC[yy] sensor");
787 else
788 ret = snprintf(buf, 512, "[UTILIZATION] Unexpected: %s", name);
789 break;
790
791 /* TEMPNEST, TEMPPROCTHRMCxx, TEMPVDD, TEMPDIMMvv, TEMPGPUz, TEMPGPUzMEM*/
793 if (!strncmp(name, "TEMPNEST", 8))
794 ret = snprintf(buf, 512, "Average temperature of nest DTS sensors");
795 else if (!strncmp(name, "TEMPVDD", 7))
796 ret = snprintf(buf, 512, "VRM Vdd temperature");
797 else if (!strncmp(name, "TEMPPROCTHRMCxx", 13)) {
798 tgt = atoi(name+13);
799 ret = snprintf(buf, 512, "The combined weighted core/quad temperature for processor core %d", tgt);
800 }
801 else if (!strncmp(name, "TEMPDIMMvv", 8)) {
802 tgt = atoi(name+8);
803 ret = snprintf(buf, 512, "DIMM temperature for DIMM %d", tgt);
804 }
805 else if (!strncmp(name, "TEMPGPUz", 7)) {
806 char z[] = {name[7], '\0'};
807 tgt = atoi(z);
808 name[7] = 'z';
809 if (!strncmp(name, "TEMPGPUzMEM", 11))
810 ret = snprintf(buf, 512, "GPU %d hottest HBM temperature (individual memory temperatures are not available)", tgt);
811 else if (!strncmp(name, "TEMPGPUz", 8))
812 ret = snprintf(buf, 512, "GPU %d board temperature", tgt);
813 else
814 ret = snprintf(buf, 512, "[TEMPERATURE] Unexpected: GPU-%d %s", tgt, name);
815 }
816 else
817 ret = snprintf(buf, 512, "[TEMPERATURE] Unexpected: %s", name);
818 break;
819
820 /* VOLTVDD, VOLTVDDSENSE, VOLTVDN, VOLTVDNSENSE, VOLTDROOPCNTCx, VOLTDROOPCNTQw */
822 if (!strncmp(name, "VOLTVDDS", 8))
823 ret = snprintf(buf, 512, "Vdn Voltage at the remote sense. (AVS reading adjusted for loadline)");
824 else if (!strncmp(name, "VOLTVDNS", 8))
825 ret = snprintf(buf, 512, "Vdd Voltage at the remote sense. (AVS reading adjusted for loadline)");
826 else if (!strncmp(name, "VOLTVDD", 7))
827 ret = snprintf(buf, 512, "Processor Vdd Voltage (read from AVSBus)");
828 else if (!strncmp(name, "VOLTVDN", 7))
829 ret = snprintf(buf, 512, "Processor Vdn Voltage (read from AVSBus)");
830 else if (!strncmp(name, "VOLTDROOPCNTC", 13)) {
831 tgt = atoi(name+13);
832 ret = snprintf(buf, 512, "Small voltage droop count for core %d", tgt);
833 }
834 else if (!strncmp(name, "VOLTDROOPCNTQ", 13)) {
835 tgt = atoi(name+13);
836 ret = snprintf(buf, 512, "Small voltage droop count for core %d", tgt);
837 }
838 else
839 ret = snprintf(buf, 512, "[VOLTAGE] Unexpected: %s", name);
840 break;
841
842 /* CURVDD, CURVDN */
844 if (!strncmp(name, "CURVDN", 6))
845 ret = snprintf(buf, 512, "Processor Vdn Current (read from AVSBus)");
846 else if (!strncmp(name, "CURVDD", 6))
847 ret = snprintf(buf, 512, "Processor Vdd Current (read from AVSBus)");
848 else
849 ret = snprintf(buf, 512, "[CURRENT] Unexpected: %s", name);
850 break;
851
853 default:
854 ret = snprintf(buf, 512, "[GENERIC] Unexpected: %s", name);
855 break;
856 }
857
858 if (ret <= 0 || 512 <= ret)
859 return PAPI_ENOSUPP;
860 _space_padding(buf, sizeof(buf));
861 ret = snprintf(buf+strlen(buf), 512, "%s", sensors_ppc_fake_qualif_desc[midx]);
862 if (ret <= 0 || 512 <= ret)
863 return PAPI_ENOSUPP;
864 _space_padding(buf, sizeof(buf));
865 ret = snprintf(buf+strlen(buf), 512, "Sampling period: %lfs", 1./freq);
866 if (ret <= 0 || 512 <= ret)
867 return PAPI_ENOSUPP;
868
869 _local_strlcpy( info->long_descr, buf, sizeof(info->long_descr));
871
872 return PAPI_OK;
873}
874
876 .cmp_info = { /* (unspecified values are initialized to 0) */
877 .name = "sensors_ppc",
878 .short_name = "sensors_ppc",
879 .description = "Linux sensors_ppc energy measurements",
880 .version = "5.3.0",
881 .default_domain = PAPI_DOM_ALL,
882 .default_granularity = PAPI_GRN_SYS,
883 .available_granularities = PAPI_GRN_SYS,
884 .hardware_intr_sig = PAPI_INT_SIGNAL,
885 .available_domains = PAPI_DOM_ALL,
886 },
887
888 /* sizes of framework-opaque component-private structures */
889 .size = {
890 .context = sizeof ( _sensors_ppc_context_t ),
891 .control_state = sizeof ( _sensors_ppc_control_state_t ),
892 .reg_value = sizeof ( _sensors_ppc_register_t ),
893 .reg_alloc = sizeof ( _sensors_ppc_reg_alloc_t ),
894 },
895 /* function pointers in this component */
896 .init_thread = _sensors_ppc_init_thread,
897 .init_component = _sensors_ppc_init_component,
898 .init_control_state = _sensors_ppc_init_control_state,
899 .update_control_state = _sensors_ppc_update_control_state,
900 .start = _sensors_ppc_start,
901 .stop = _sensors_ppc_stop,
902 .read = _sensors_ppc_read,
903 .shutdown_thread = _sensors_ppc_shutdown_thread,
904 .shutdown_component = _sensors_ppc_shutdown_component,
905 .ctl = _sensors_ppc_ctl,
906
907 .set_domain = _sensors_ppc_set_domain,
908 .reset = _sensors_ppc_reset,
909
910 .ntv_enum_events = _sensors_ppc_ntv_enum_events,
911 .ntv_code_to_name = _sensors_ppc_ntv_code_to_name,
912 .ntv_code_to_info = _sensors_ppc_ntv_code_to_info,
913};
int i
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:188
off_t lseek(int fd, off_t offset, int whence)
Definition: appio.c:214
int close(int fd)
Definition: appio.c:179
ssize_t read(int fd, void *buf, size_t count)
Definition: appio.c:229
const char * names[NUM_EVENTS]
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:28
double s
Definition: byte_profile.c:36
static long count
Get real time counter value in nanoseconds.
struct papi_vectors * _papi_hwd[]
volatile int buf[CACHE_FLUSH_BUFFER_SIZE_INTS]
Definition: do_loops.c:12
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_VENDOR_IBM
Definition: f90papi.h:61
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_GRN_SYS
Definition: f90papi.h:43
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_DATATYPE_INT64
Definition: f90papi.h:227
#define PAPI_DOM_ALL
Definition: f90papi.h:261
char events[MAX_EVENTS][BUFSIZ]
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
static int num_events
static int _sensors_ppc_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
#define DESC_LINE_SIZE_ALLOWED
static int _sensors_ppc_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _sensors_ppc_set_domain(hwd_control_state_t *ctl, int domain)
static long long read_sensors_ppc_record(int s, int gidx, int midx)
static int _sensors_ppc_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
#define TO_FP(f)
static int _sensors_ppc_shutdown_component(void)
static int _sensors_ppc_ntv_code_to_name(unsigned int EventCode, char *name, int len)
static long long read_sensors_ppc_counter(int s, int gidx)
static int _sensors_ppc_init_component(int cidx)
static int _sensors_ppc_is_counter(int index)
static void refresh_data(int occ_id, int forced)
Refresh_data locks in write and update ping and pong at the same time for OCC occ_id....
static char * _local_strlcpy(char *dst, const char *src, size_t size)
static int _sensors_ppc_shutdown_thread(hwd_context_t *ctx)
static int _sensors_ppc_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int _sensors_ppc_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
static int _sensors_ppc_ntv_enum_events(unsigned int *EventCode, int modifier)
static double _pow(int x, int y)
static int _sensors_ppc_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _sensors_ppc_init_thread(hwd_context_t *ctx)
static int _sensors_ppc_init_control_state(hwd_control_state_t *ctl)
static int _sensors_ppc_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
static long long read_sensors_ppc_value(int index)
papi_vector_t _sensors_ppc_vector
static void _space_padding(char *buf, size_t max)
#define HANDLE_STRING_ERROR
OCC Inband Sensors component for PowerPC This file contains the source code for a component that enab...
static char * pkg_sys_name
#define MAX_OCCS
#define OCC_SENSOR_DATA_BLOCK_SIZE
static const char * sensors_ppc_fake_qualifiers[]
uint16_t nr_sensors
#define papi_sensors_ppc_lock()
#define OCC_REFRESH_TIME
uint32_t reading_pong_offset
#define OCC_SENSOR_READING_COUNTER
static mode_t pkg_sys_flag
static long long last_refresh[MAX_OCCS]
struct occ_sensor_data_header_s * occ_hdr[MAX_OCCS]
static int num_occs
@ OCC_SENSOR_TYPE_GENERIC
@ OCC_SENSOR_TYPE_TIME
@ OCC_SENSOR_TYPE_VOLTAGE
@ OCC_SENSOR_TYPE_FREQUENCY
@ OCC_SENSOR_TYPE_UTILIZATION
@ OCC_SENSOR_TYPE_TEMPERATURE
@ OCC_SENSOR_TYPE_CURRENT
@ OCC_SENSOR_TYPE_POWER
@ OCC_SENSOR_TYPE_PERFORMANCE
uint32_t reading_offset
uint32_t names_offset
uint32_t reading_ping_offset
static uint32_t * double_pong[MAX_OCCS]
#define SENSORS_PPC_MAX_COUNTERS
#define OCC_PING_DATA_BLOCK_SIZE
@ OCC_SENSORS_MASKS
@ OCC_SENSORS_ACCUMULATOR_TAG
static const char * sensors_ppc_fake_qualif_desc[]
static int occ_num_events[MAX_OCCS+1]
uint32_t freq
static int event_fd
#define OCC_SENSOR_READING_FULL
struct occ_sensor_name_s * occ_names[MAX_OCCS]
static uint32_t * pong[MAX_OCCS]
uint16_t type
uint32_t scale_factor
#define papi_sensors_ppc_unlock()
static uint32_t * ping[MAX_OCCS]
uint8_t structure_type
static uint32_t * double_ping[MAX_OCCS]
#define PAPI_NATIVE_AND_MASK
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
static int native
static int cidx
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
rc
Definition: pscanf.h:23
const char * name
Definition: rocs.c:225
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:969
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:960
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:963
Hardware info structure.
Definition: papi.h:774
int vendor
Definition: papi.h:781
long long start_value[SENSORS_PPC_MAX_COUNTERS]
long long count[SENSORS_PPC_MAX_COUNTERS]
long long which_counter[SENSORS_PPC_MAX_COUNTERS]
char units[MAX_CHARS_SENSOR_UNIT]
PAPI_hw_info_t hw_info
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
volatile double y
volatile double x
int retval
Definition: zero_fork.c:53