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