1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2014, Michael Ellerman, IBM Corp. 4 */ 5 6 #define _GNU_SOURCE 7 8 #include <elf.h> 9 #include <limits.h> 10 #include <stdio.h> 11 #include <stdbool.h> 12 #include <string.h> 13 #include <sys/prctl.h> 14 15 #include "event.h" 16 #include "lib.h" 17 #include "utils.h" 18 19 /* 20 * Test that per-event excludes work. 21 */ 22 23 static int per_event_excludes(void) 24 { 25 struct event *e, events[4]; 26 char *platform; 27 int i; 28 29 platform = (char *)get_auxv_entry(AT_BASE_PLATFORM); 30 FAIL_IF(!platform); 31 SKIP_IF(strcmp(platform, "power8") != 0); 32 33 /* 34 * We need to create the events disabled, otherwise the running/enabled 35 * counts don't match up. 36 */ 37 e = &events[0]; 38 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, 39 PERF_TYPE_HARDWARE, "instructions"); 40 e->attr.disabled = 1; 41 42 e = &events[1]; 43 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, 44 PERF_TYPE_HARDWARE, "instructions(k)"); 45 e->attr.disabled = 1; 46 e->attr.exclude_user = 1; 47 e->attr.exclude_hv = 1; 48 49 e = &events[2]; 50 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, 51 PERF_TYPE_HARDWARE, "instructions(h)"); 52 e->attr.disabled = 1; 53 e->attr.exclude_user = 1; 54 e->attr.exclude_kernel = 1; 55 56 e = &events[3]; 57 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, 58 PERF_TYPE_HARDWARE, "instructions(u)"); 59 e->attr.disabled = 1; 60 e->attr.exclude_hv = 1; 61 e->attr.exclude_kernel = 1; 62 63 FAIL_IF(event_open(&events[0])); 64 65 /* 66 * The open here will fail if we don't have per event exclude support, 67 * because the second event has an incompatible set of exclude settings 68 * and we're asking for the events to be in a group. 69 */ 70 for (i = 1; i < 4; i++) 71 FAIL_IF(event_open_with_group(&events[i], events[0].fd)); 72 73 /* 74 * Even though the above will fail without per-event excludes we keep 75 * testing in order to be thorough. 76 */ 77 prctl(PR_TASK_PERF_EVENTS_ENABLE); 78 79 /* Spin for a while */ 80 for (i = 0; i < INT_MAX; i++) 81 asm volatile("" : : : "memory"); 82 83 prctl(PR_TASK_PERF_EVENTS_DISABLE); 84 85 for (i = 0; i < 4; i++) { 86 FAIL_IF(event_read(&events[i])); 87 event_report(&events[i]); 88 } 89 90 /* 91 * We should see that all events have enabled == running. That 92 * shows that they were all on the PMU at once. 93 */ 94 for (i = 0; i < 4; i++) 95 FAIL_IF(events[i].result.running != events[i].result.enabled); 96 97 /* 98 * We can also check that the result for instructions is >= all the 99 * other counts. That's because it is counting all instructions while 100 * the others are counting a subset. 101 */ 102 for (i = 1; i < 4; i++) 103 FAIL_IF(events[0].result.value < events[i].result.value); 104 105 for (i = 0; i < 4; i++) 106 event_close(&events[i]); 107 108 return 0; 109 } 110 111 int main(void) 112 { 113 return test_harness(per_event_excludes, "per_event_excludes"); 114 } 115