^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #define __SANE_USERSPACE_TYPES__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/hw_breakpoint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "../perf-sys.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "cloexec.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static volatile long the_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static noinline int test_function(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int __event(bool is_x, void *addr, struct perf_event_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) memset(attr, 0, sizeof(struct perf_event_attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) attr->type = PERF_TYPE_BREAKPOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) attr->size = sizeof(struct perf_event_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) attr->config = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) attr->bp_addr = (unsigned long) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) attr->bp_len = sizeof(long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) attr->sample_period = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) attr->sample_type = PERF_SAMPLE_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) attr->exclude_kernel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) attr->exclude_hv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) fd = sys_perf_event_open(attr, -1, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) perf_event_open_cloexec_flag());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) pr_debug("failed opening event %llx\n", attr->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return TEST_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int wp_event(void *addr, struct perf_event_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return __event(false, addr, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int bp_event(void *addr, struct perf_event_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return __event(true, addr, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int bp_accounting(int wp_cnt, int share)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct perf_event_attr attr, attr_mod, attr_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int i, fd[wp_cnt], fd_wp, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) for (i = 0; i < wp_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) fd[i] = wp_event((void *)&the_var, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_debug("wp %d created\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) attr_mod = attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) attr_mod.bp_type = HW_BREAKPOINT_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) attr_mod.bp_addr = (unsigned long) test_function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ret = ioctl(fd[0], PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr_mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) TEST_ASSERT_VAL("failed to modify wp\n", ret == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_debug("wp 0 modified to bp\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!share) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) fd_wp = wp_event((void *)&the_var, &attr_new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) TEST_ASSERT_VAL("failed to create max wp\n", fd_wp != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pr_debug("wp max created\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; i < wp_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) close(fd[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int detect_cnt(bool is_x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void *addr = is_x ? (void *)test_function : (void *)&the_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int fd[100], cnt = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (cnt == 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pr_debug("way too many debug registers, fix the test\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) fd[cnt] = __event(is_x, addr, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (fd[cnt] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (i = 0; i < cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) close(fd[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int detect_ioctl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int fd, ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) fd = wp_event((void *) &the_var, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (fd > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return ret ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static int detect_share(int wp_cnt, int bp_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int i, fd[wp_cnt + bp_cnt], ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) for (i = 0; i < wp_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fd[i] = wp_event((void *)&the_var, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for (; i < (bp_cnt + wp_cnt); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) fd[i] = bp_event((void *)test_function, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (fd[i] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ret = i != (bp_cnt + wp_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) close(fd[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * This test does following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * - detects the number of watch/break-points,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * skip test if any is missing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * - detects PERF_EVENT_IOC_MODIFY_ATTRIBUTES ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * skip test if it's missing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * - detects if watchpoints and breakpoints share
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * same slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * - create all possible watchpoints on cpu 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * - change one of it to breakpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * - in case wp and bp do not share slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * we create another watchpoint to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * the slot accounting is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int has_ioctl = detect_ioctl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int wp_cnt = detect_cnt(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int bp_cnt = detect_cnt(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int share = detect_share(wp_cnt, bp_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pr_debug("watchpoints count %d, breakpoints count %d, has_ioctl %d, share %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) wp_cnt, bp_cnt, has_ioctl, share);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!wp_cnt || !bp_cnt || !has_ioctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return TEST_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return bp_accounting(wp_cnt, share);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) bool test__bp_account_is_supported(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * PowerPC and S390 do not support creation of instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * breakpoints using the perf_event interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Just disable the test for these architectures until these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * issues are resolved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #if defined(__powerpc__) || defined(__s390x__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }