linux/tools/perf/tests/bp_signal.c
<<
>>
Prefs
   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/*
   8 * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
   9 * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
  10 */
  11#define __SANE_USERSPACE_TYPES__
  12
  13#include <stdlib.h>
  14#include <stdio.h>
  15#include <unistd.h>
  16#include <string.h>
  17#include <sys/ioctl.h>
  18#include <time.h>
  19#include <fcntl.h>
  20#include <signal.h>
  21#include <sys/mman.h>
  22#include <linux/compiler.h>
  23#include <linux/hw_breakpoint.h>
  24
  25#include "tests.h"
  26#include "debug.h"
  27#include "perf.h"
  28#include "cloexec.h"
  29
  30static int fd1;
  31static int fd2;
  32static int fd3;
  33static int overflows;
  34static int overflows_2;
  35
  36volatile long the_var;
  37
  38
  39/*
  40 * Use ASM to ensure watchpoint and breakpoint can be triggered
  41 * at one instruction.
  42 */
  43#if defined (__x86_64__)
  44extern void __test_function(volatile long *ptr);
  45asm (
  46        ".globl __test_function\n"
  47        "__test_function:\n"
  48        "incq (%rdi)\n"
  49        "ret\n");
  50#elif defined (__aarch64__)
  51extern void __test_function(volatile long *ptr);
  52asm (
  53        ".globl __test_function\n"
  54        "__test_function:\n"
  55        "str x30, [x0]\n"
  56        "ret\n");
  57
  58#else
  59static void __test_function(volatile long *ptr)
  60{
  61        *ptr = 0x1234;
  62}
  63#endif
  64
  65__attribute__ ((noinline))
  66static int test_function(void)
  67{
  68        __test_function(&the_var);
  69        the_var++;
  70        return time(NULL);
  71}
  72
  73static void sig_handler_2(int signum __maybe_unused,
  74                          siginfo_t *oh __maybe_unused,
  75                          void *uc __maybe_unused)
  76{
  77        overflows_2++;
  78        if (overflows_2 > 10) {
  79                ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
  80                ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
  81                ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
  82        }
  83}
  84
  85static void sig_handler(int signum __maybe_unused,
  86                        siginfo_t *oh __maybe_unused,
  87                        void *uc __maybe_unused)
  88{
  89        overflows++;
  90
  91        if (overflows > 10) {
  92                /*
  93                 * This should be executed only once during
  94                 * this test, if we are here for the 10th
  95                 * time, consider this the recursive issue.
  96                 *
  97                 * We can get out of here by disable events,
  98                 * so no new SIGIO is delivered.
  99                 */
 100                ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 101                ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
 102                ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 103        }
 104}
 105
 106static int __event(bool is_x, void *addr, int sig)
 107{
 108        struct perf_event_attr pe;
 109        int fd;
 110
 111        memset(&pe, 0, sizeof(struct perf_event_attr));
 112        pe.type = PERF_TYPE_BREAKPOINT;
 113        pe.size = sizeof(struct perf_event_attr);
 114
 115        pe.config = 0;
 116        pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
 117        pe.bp_addr = (unsigned long) addr;
 118        pe.bp_len = sizeof(long);
 119
 120        pe.sample_period = 1;
 121        pe.sample_type = PERF_SAMPLE_IP;
 122        pe.wakeup_events = 1;
 123
 124        pe.disabled = 1;
 125        pe.exclude_kernel = 1;
 126        pe.exclude_hv = 1;
 127
 128        fd = sys_perf_event_open(&pe, 0, -1, -1,
 129                                 perf_event_open_cloexec_flag());
 130        if (fd < 0) {
 131                pr_debug("failed opening event %llx\n", pe.config);
 132                return TEST_FAIL;
 133        }
 134
 135        fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
 136        fcntl(fd, F_SETSIG, sig);
 137        fcntl(fd, F_SETOWN, getpid());
 138
 139        ioctl(fd, PERF_EVENT_IOC_RESET, 0);
 140
 141        return fd;
 142}
 143
 144static int bp_event(void *addr, int sig)
 145{
 146        return __event(true, addr, sig);
 147}
 148
 149static int wp_event(void *addr, int sig)
 150{
 151        return __event(false, addr, sig);
 152}
 153
 154static long long bp_count(int fd)
 155{
 156        long long count;
 157        int ret;
 158
 159        ret = read(fd, &count, sizeof(long long));
 160        if (ret != sizeof(long long)) {
 161                pr_debug("failed to read: %d\n", ret);
 162                return TEST_FAIL;
 163        }
 164
 165        return count;
 166}
 167
 168int test__bp_signal(int subtest __maybe_unused)
 169{
 170        struct sigaction sa;
 171        long long count1, count2, count3;
 172
 173        /* setup SIGIO signal handler */
 174        memset(&sa, 0, sizeof(struct sigaction));
 175        sa.sa_sigaction = (void *) sig_handler;
 176        sa.sa_flags = SA_SIGINFO;
 177
 178        if (sigaction(SIGIO, &sa, NULL) < 0) {
 179                pr_debug("failed setting up signal handler\n");
 180                return TEST_FAIL;
 181        }
 182
 183        sa.sa_sigaction = (void *) sig_handler_2;
 184        if (sigaction(SIGUSR1, &sa, NULL) < 0) {
 185                pr_debug("failed setting up signal handler 2\n");
 186                return TEST_FAIL;
 187        }
 188
 189        /*
 190         * We create following events:
 191         *
 192         * fd1 - breakpoint event on __test_function with SIGIO
 193         *       signal configured. We should get signal
 194         *       notification each time the breakpoint is hit
 195         *
 196         * fd2 - breakpoint event on sig_handler with SIGUSR1
 197         *       configured. We should get SIGUSR1 each time when
 198         *       breakpoint is hit
 199         *
 200         * fd3 - watchpoint event on __test_function with SIGIO
 201         *       configured.
 202         *
 203         * Following processing should happen:
 204         *   Exec:               Action:                       Result:
 205         *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
 206         *                     - SIGIO is delivered
 207         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
 208         *                     - SIGUSR1 is delivered
 209         *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
 210         *   sys_rt_sigreturn  - return from sig_handler_2
 211         *   overflows++                                    -> overflows = 1
 212         *   sys_rt_sigreturn  - return from sig_handler
 213         *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
 214         *                     - SIGIO is delivered
 215         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
 216         *                     - SIGUSR1 is delivered
 217         *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
 218         *   sys_rt_sigreturn  - return from sig_handler_2
 219         *   overflows++                                    -> overflows = 2
 220         *   sys_rt_sigreturn  - return from sig_handler
 221         *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
 222         *                     - SIGIO is delivered
 223         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
 224         *                     - SIGUSR1 is delivered
 225         *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
 226         *   sys_rt_sigreturn  - return from sig_handler_2
 227         *   overflows++                                    -> overflows == 3
 228         *   sys_rt_sigreturn  - return from sig_handler
 229         *
 230         * The test case check following error conditions:
 231         * - we get stuck in signal handler because of debug
 232         *   exception being triggered receursively due to
 233         *   the wrong RF EFLAG management
 234         *
 235         * - we never trigger the sig_handler breakpoint due
 236         *   to the rong RF EFLAG management
 237         *
 238         */
 239
 240        fd1 = bp_event(__test_function, SIGIO);
 241        fd2 = bp_event(sig_handler, SIGUSR1);
 242        fd3 = wp_event((void *)&the_var, SIGIO);
 243
 244        ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
 245        ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
 246        ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
 247
 248        /*
 249         * Kick off the test by trigering 'fd1'
 250         * breakpoint.
 251         */
 252        test_function();
 253
 254        ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 255        ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
 256        ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 257
 258        count1 = bp_count(fd1);
 259        count2 = bp_count(fd2);
 260        count3 = bp_count(fd3);
 261
 262        close(fd1);
 263        close(fd2);
 264        close(fd3);
 265
 266        pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
 267                 count1, count2, count3, overflows, overflows_2);
 268
 269        if (count1 != 1) {
 270                if (count1 == 11)
 271                        pr_debug("failed: RF EFLAG recursion issue detected\n");
 272                else
 273                        pr_debug("failed: wrong count for bp1%lld\n", count1);
 274        }
 275
 276        if (overflows != 3)
 277                pr_debug("failed: wrong overflow hit\n");
 278
 279        if (overflows_2 != 3)
 280                pr_debug("failed: wrong overflow_2 hit\n");
 281
 282        if (count2 != 3)
 283                pr_debug("failed: wrong count for bp2\n");
 284
 285        if (count3 != 2)
 286                pr_debug("failed: wrong count for bp3\n");
 287
 288        return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
 289                TEST_OK : TEST_FAIL;
 290}
 291