1 /* 2 * Inspired by breakpoint overflow test done by 3 * Vince Weaver <vincent.weaver@maine.edu> for perf_event_tests 4 * (git://github.com/deater/perf_event_tests) 5 */ 6 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <unistd.h> 10 #include <string.h> 11 #include <sys/ioctl.h> 12 #include <time.h> 13 #include <fcntl.h> 14 #include <signal.h> 15 #include <sys/mman.h> 16 #include <linux/compiler.h> 17 #include <linux/hw_breakpoint.h> 18 19 #include "tests.h" 20 #include "debug.h" 21 #include "perf.h" 22 23 static int fd1; 24 static int fd2; 25 static int overflows; 26 27 __attribute__ ((noinline)) 28 static int test_function(void) 29 { 30 return time(NULL); 31 } 32 33 static void sig_handler(int signum __maybe_unused, 34 siginfo_t *oh __maybe_unused, 35 void *uc __maybe_unused) 36 { 37 overflows++; 38 39 if (overflows > 10) { 40 /* 41 * This should be executed only once during 42 * this test, if we are here for the 10th 43 * time, consider this the recursive issue. 44 * 45 * We can get out of here by disable events, 46 * so no new SIGIO is delivered. 47 */ 48 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); 49 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); 50 } 51 } 52 53 static int bp_event(void *fn, int setup_signal) 54 { 55 struct perf_event_attr pe; 56 int fd; 57 58 memset(&pe, 0, sizeof(struct perf_event_attr)); 59 pe.type = PERF_TYPE_BREAKPOINT; 60 pe.size = sizeof(struct perf_event_attr); 61 62 pe.config = 0; 63 pe.bp_type = HW_BREAKPOINT_X; 64 pe.bp_addr = (unsigned long) fn; 65 pe.bp_len = sizeof(long); 66 67 pe.sample_period = 1; 68 pe.sample_type = PERF_SAMPLE_IP; 69 pe.wakeup_events = 1; 70 71 pe.disabled = 1; 72 pe.exclude_kernel = 1; 73 pe.exclude_hv = 1; 74 75 fd = sys_perf_event_open(&pe, 0, -1, -1, 0); 76 if (fd < 0) { 77 pr_debug("failed opening event %llx\n", pe.config); 78 return TEST_FAIL; 79 } 80 81 if (setup_signal) { 82 fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); 83 fcntl(fd, F_SETSIG, SIGIO); 84 fcntl(fd, F_SETOWN, getpid()); 85 } 86 87 ioctl(fd, PERF_EVENT_IOC_RESET, 0); 88 89 return fd; 90 } 91 92 static long long bp_count(int fd) 93 { 94 long long count; 95 int ret; 96 97 ret = read(fd, &count, sizeof(long long)); 98 if (ret != sizeof(long long)) { 99 pr_debug("failed to read: %d\n", ret); 100 return TEST_FAIL; 101 } 102 103 return count; 104 } 105 106 int test__bp_signal(void) 107 { 108 struct sigaction sa; 109 long long count1, count2; 110 111 /* setup SIGIO signal handler */ 112 memset(&sa, 0, sizeof(struct sigaction)); 113 sa.sa_sigaction = (void *) sig_handler; 114 sa.sa_flags = SA_SIGINFO; 115 116 if (sigaction(SIGIO, &sa, NULL) < 0) { 117 pr_debug("failed setting up signal handler\n"); 118 return TEST_FAIL; 119 } 120 121 /* 122 * We create following events: 123 * 124 * fd1 - breakpoint event on test_function with SIGIO 125 * signal configured. We should get signal 126 * notification each time the breakpoint is hit 127 * 128 * fd2 - breakpoint event on sig_handler without SIGIO 129 * configured. 130 * 131 * Following processing should happen: 132 * - execute test_function 133 * - fd1 event breakpoint hit -> count1 == 1 134 * - SIGIO is delivered -> overflows == 1 135 * - fd2 event breakpoint hit -> count2 == 1 136 * 137 * The test case check following error conditions: 138 * - we get stuck in signal handler because of debug 139 * exception being triggered receursively due to 140 * the wrong RF EFLAG management 141 * 142 * - we never trigger the sig_handler breakpoint due 143 * to the rong RF EFLAG management 144 * 145 */ 146 147 fd1 = bp_event(test_function, 1); 148 fd2 = bp_event(sig_handler, 0); 149 150 ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); 151 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); 152 153 /* 154 * Kick off the test by trigering 'fd1' 155 * breakpoint. 156 */ 157 test_function(); 158 159 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); 160 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); 161 162 count1 = bp_count(fd1); 163 count2 = bp_count(fd2); 164 165 close(fd1); 166 close(fd2); 167 168 pr_debug("count1 %lld, count2 %lld, overflow %d\n", 169 count1, count2, overflows); 170 171 if (count1 != 1) { 172 if (count1 == 11) 173 pr_debug("failed: RF EFLAG recursion issue detected\n"); 174 else 175 pr_debug("failed: wrong count for bp1%lld\n", count1); 176 } 177 178 if (overflows != 1) 179 pr_debug("failed: wrong overflow hit\n"); 180 181 if (count2 != 1) 182 pr_debug("failed: wrong count for bp2\n"); 183 184 return count1 == 1 && overflows == 1 && count2 == 1 ? 185 TEST_OK : TEST_FAIL; 186 } 187