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
  65static noinline int test_function(void)
  66{
  67        __test_function(&the_var);
  68        the_var++;
  69        return time(NULL);
  70}
  71
  72static void sig_handler_2(int signum __maybe_unused,
  73                          siginfo_t *oh __maybe_unused,
  74                          void *uc __maybe_unused)
  75{
  76        overflows_2++;
  77        if (overflows_2 > 10) {
  78                ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
  79                ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
  80                ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
  81        }
  82}
  83
  84static void sig_handler(int signum __maybe_unused,
  85                        siginfo_t *oh __maybe_unused,
  86                        void *uc __maybe_unused)
  87{
  88        overflows++;
  89
  90        if (overflows > 10) {
  91                /*
  92                 * This should be executed only once during
  93                 * this test, if we are here for the 10th
  94                 * time, consider this the recursive issue.
  95                 *
  96                 * We can get out of here by disable events,
  97                 * so no new SIGIO is delivered.
  98                 */
  99                ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 100                ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
 101                ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 102        }
 103}
 104
 105static int __event(bool is_x, void *addr, int sig)
 106{
 107        struct perf_event_attr pe;
 108        int fd;
 109
 110        memset(&pe, 0, sizeof(struct perf_event_attr));
 111        pe.type = PERF_TYPE_BREAKPOINT;
 112        pe.size = sizeof(struct perf_event_attr);
 113
 114        pe.config = 0;
 115        pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
 116        pe.bp_addr = (unsigned long) addr;
 117        pe.bp_len = sizeof(long);
 118
 119        pe.sample_period = 1;
 120        pe.sample_type = PERF_SAMPLE_IP;
 121        pe.wakeup_events = 1;
 122
 123        pe.disabled = 1;
 124        pe.exclude_kernel = 1;
 125        pe.exclude_hv = 1;
 126
 127        fd = sys_perf_event_open(&pe, 0, -1, -1,
 128                                 perf_event_open_cloexec_flag());
 129        if (fd < 0) {
 130                pr_debug("failed opening event %llx\n", pe.config);
 131                return TEST_FAIL;
 132        }
 133
 134        fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
 135        fcntl(fd, F_SETSIG, sig);
 136        fcntl(fd, F_SETOWN, getpid());
 137
 138        ioctl(fd, PERF_EVENT_IOC_RESET, 0);
 139
 140        return fd;
 141}
 142
 143static int bp_event(void *addr, int sig)
 144{
 145        return __event(true, addr, sig);
 146}
 147
 148static int wp_event(void *addr, int sig)
 149{
 150        return __event(false, addr, sig);
 151}
 152
 153static long long bp_count(int fd)
 154{
 155        long long count;
 156        int ret;
 157
 158        ret = read(fd, &count, sizeof(long long));
 159        if (ret != sizeof(long long)) {
 160                pr_debug("failed to read: %d\n", ret);
 161                return TEST_FAIL;
 162        }
 163
 164        return count;
 165}
 166
 167int test__bp_signal(int subtest __maybe_unused)
 168{
 169        struct sigaction sa;
 170        long long count1, count2, count3;
 171
 172        /* setup SIGIO signal handler */
 173        memset(&sa, 0, sizeof(struct sigaction));
 174        sa.sa_sigaction = (void *) sig_handler;
 175        sa.sa_flags = SA_SIGINFO;
 176
 177        if (sigaction(SIGIO, &sa, NULL) < 0) {
 178                pr_debug("failed setting up signal handler\n");
 179                return TEST_FAIL;
 180        }
 181
 182        sa.sa_sigaction = (void *) sig_handler_2;
 183        if (sigaction(SIGUSR1, &sa, NULL) < 0) {
 184                pr_debug("failed setting up signal handler 2\n");
 185                return TEST_FAIL;
 186        }
 187
 188        /*
 189         * We create following events:
 190         *
 191         * fd1 - breakpoint event on __test_function with SIGIO
 192         *       signal configured. We should get signal
 193         *       notification each time the breakpoint is hit
 194         *
 195         * fd2 - breakpoint event on sig_handler with SIGUSR1
 196         *       configured. We should get SIGUSR1 each time when
 197         *       breakpoint is hit
 198         *
 199         * fd3 - watchpoint event on __test_function with SIGIO
 200         *       configured.
 201         *
 202         * Following processing should happen:
 203         *   Exec:               Action:                       Result:
 204         *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
 205         *                     - SIGIO is delivered
 206         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
 207         *                     - SIGUSR1 is delivered
 208         *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
 209         *   sys_rt_sigreturn  - return from sig_handler_2
 210         *   overflows++                                    -> overflows = 1
 211         *   sys_rt_sigreturn  - return from sig_handler
 212         *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
 213         *                     - SIGIO is delivered
 214         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
 215         *                     - SIGUSR1 is delivered
 216         *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
 217         *   sys_rt_sigreturn  - return from sig_handler_2
 218         *   overflows++                                    -> overflows = 2
 219         *   sys_rt_sigreturn  - return from sig_handler
 220         *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
 221         *                     - SIGIO is delivered
 222         *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
 223         *                     - SIGUSR1 is delivered
 224         *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
 225         *   sys_rt_sigreturn  - return from sig_handler_2
 226         *   overflows++                                    -> overflows == 3
 227         *   sys_rt_sigreturn  - return from sig_handler
 228         *
 229         * The test case check following error conditions:
 230         * - we get stuck in signal handler because of debug
 231         *   exception being triggered receursively due to
 232         *   the wrong RF EFLAG management
 233         *
 234         * - we never trigger the sig_handler breakpoint due
 235         *   to the rong RF EFLAG management
 236         *
 237         */
 238
 239        fd1 = bp_event(__test_function, SIGIO);
 240        fd2 = bp_event(sig_handler, SIGUSR1);
 241        fd3 = wp_event((void *)&the_var, SIGIO);
 242
 243        ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
 244        ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
 245        ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
 246
 247        /*
 248         * Kick off the test by trigering 'fd1'
 249         * breakpoint.
 250         */
 251        test_function();
 252
 253        ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 254        ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
 255        ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 256
 257        count1 = bp_count(fd1);
 258        count2 = bp_count(fd2);
 259        count3 = bp_count(fd3);
 260
 261        close(fd1);
 262        close(fd2);
 263        close(fd3);
 264
 265        pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
 266                 count1, count2, count3, overflows, overflows_2);
 267
 268        if (count1 != 1) {
 269                if (count1 == 11)
 270                        pr_debug("failed: RF EFLAG recursion issue detected\n");
 271                else
 272                        pr_debug("failed: wrong count for bp1%lld\n", count1);
 273        }
 274
 275        if (overflows != 3)
 276                pr_debug("failed: wrong overflow hit\n");
 277
 278        if (overflows_2 != 3)
 279                pr_debug("failed: wrong overflow_2 hit\n");
 280
 281        if (count2 != 3)
 282                pr_debug("failed: wrong count for bp2\n");
 283
 284        if (count3 != 2)
 285                pr_debug("failed: wrong count for bp3\n");
 286
 287        return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
 288                TEST_OK : TEST_FAIL;
 289}
 290
 291bool test__bp_signal_is_supported(void)
 292{
 293/*
 294 * The powerpc so far does not have support to even create
 295 * instruction breakpoint using the perf event interface.
 296 * Once it's there we can release this.
 297 */
 298#ifdef __powerpc__
 299        return false;
 300#else
 301        return true;
 302#endif
 303}
 304