1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/hw_breakpoint.h>
7 #include <linux/kernel.h>
12 #include "../perf-sys.h"
14 #define WP_TEST_ASSERT_VAL(fd, text, val) \
17 wp_read(fd, &count, sizeof(long long)); \
18 TEST_ASSERT_VAL(text, count == val); \
25 static int wp_read(int fd, long long *count, int size)
27 int ret = read(fd, count, size);
30 pr_debug("failed to read: %d\n", ret);
36 static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
37 void *wp_addr, unsigned long wp_len)
39 memset(attr, 0, sizeof(struct perf_event_attr));
40 attr->type = PERF_TYPE_BREAKPOINT;
41 attr->size = sizeof(struct perf_event_attr);
43 attr->bp_type = wp_type;
44 attr->bp_addr = (unsigned long)wp_addr;
45 attr->bp_len = wp_len;
46 attr->sample_period = 1;
47 attr->sample_type = PERF_SAMPLE_IP;
48 attr->exclude_kernel = 1;
52 static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
55 struct perf_event_attr attr;
57 get__perf_event_attr(&attr, wp_type, wp_addr, wp_len);
58 fd = sys_perf_event_open(&attr, 0, -1, -1,
59 perf_event_open_cloexec_flag());
61 pr_debug("failed opening event %x\n", attr.bp_type);
67 static int test__wp_ro(struct test_suite *test __maybe_unused,
68 int subtest __maybe_unused)
70 #if defined(__s390x__) || defined(__x86_64__) || defined(__i386__)
74 unsigned long tmp, tmp1 = rand();
76 fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1));
81 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
84 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
91 static int test__wp_wo(struct test_suite *test __maybe_unused,
92 int subtest __maybe_unused)
94 #if defined(__s390x__)
98 unsigned long tmp, tmp1 = rand();
100 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
105 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0);
108 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1);
115 static int test__wp_rw(struct test_suite *test __maybe_unused,
116 int subtest __maybe_unused)
118 #if defined(__s390x__)
122 unsigned long tmp, tmp1 = rand();
124 fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1,
130 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1);
133 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2);
140 static int test__wp_modify(struct test_suite *test __maybe_unused,
141 int subtest __maybe_unused)
143 #if defined(__s390x__)
147 unsigned long tmp = rand();
148 struct perf_event_attr new_attr;
150 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
155 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
157 /* Modify watchpoint with disabled = 1 */
158 get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0],
160 new_attr.disabled = 1;
161 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
163 pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
168 data2[1] = tmp; /* Not Counted */
169 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
171 /* Enable the event */
172 ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
174 pr_debug("Failed to enable event\n");
179 data2[1] = tmp; /* Counted */
180 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
182 data2[2] = tmp; /* Not Counted */
183 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
190 static struct test_case wp_tests[] = {
191 TEST_CASE_REASON("Read Only Watchpoint", wp_ro, "missing hardware support"),
192 TEST_CASE_REASON("Write Only Watchpoint", wp_wo, "missing hardware support"),
193 TEST_CASE_REASON("Read / Write Watchpoint", wp_rw, "missing hardware support"),
194 TEST_CASE_REASON("Modify Watchpoint", wp_modify, "missing hardware support"),
198 struct test_suite suite__wp = {
199 .desc = "Watchpoint",
200 .test_cases = wp_tests,