.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * perf events self profiling example test case for hw breakpoints. |
---|
3 | 4 | * |
---|
.. | .. |
---|
14 | 15 | * http://ozlabs.org/~anton/junkcode/perf_events_example1.c |
---|
15 | 16 | * |
---|
16 | 17 | * Copyright (C) 2018 Michael Neuling, IBM Corporation. |
---|
17 | | - * |
---|
18 | | - * This program is free software; you can redistribute it and/or |
---|
19 | | - * modify it under the terms of the GNU General Public License |
---|
20 | | - * as published by the Free Software Foundation; either version |
---|
21 | | - * 2 of the License, or (at your option) any later version. |
---|
22 | 18 | */ |
---|
23 | 19 | |
---|
24 | 20 | #include <unistd.h> |
---|
.. | .. |
---|
152 | 148 | return 0; |
---|
153 | 149 | } |
---|
154 | 150 | |
---|
| 151 | +static int runtest_dar_outside(void) |
---|
| 152 | +{ |
---|
| 153 | + void *target; |
---|
| 154 | + volatile __u16 temp16; |
---|
| 155 | + volatile __u64 temp64; |
---|
| 156 | + struct perf_event_attr attr; |
---|
| 157 | + int break_fd; |
---|
| 158 | + unsigned long long breaks; |
---|
| 159 | + int fail = 0; |
---|
| 160 | + size_t res; |
---|
| 161 | + |
---|
| 162 | + target = malloc(8); |
---|
| 163 | + if (!target) { |
---|
| 164 | + perror("malloc failed"); |
---|
| 165 | + exit(EXIT_FAILURE); |
---|
| 166 | + } |
---|
| 167 | + |
---|
| 168 | + /* setup counters */ |
---|
| 169 | + memset(&attr, 0, sizeof(attr)); |
---|
| 170 | + attr.disabled = 1; |
---|
| 171 | + attr.type = PERF_TYPE_BREAKPOINT; |
---|
| 172 | + attr.exclude_kernel = 1; |
---|
| 173 | + attr.exclude_hv = 1; |
---|
| 174 | + attr.exclude_guest = 1; |
---|
| 175 | + attr.bp_type = HW_BREAKPOINT_RW; |
---|
| 176 | + /* watch middle half of target array */ |
---|
| 177 | + attr.bp_addr = (__u64)(target + 2); |
---|
| 178 | + attr.bp_len = 4; |
---|
| 179 | + break_fd = sys_perf_event_open(&attr, 0, -1, -1, 0); |
---|
| 180 | + if (break_fd < 0) { |
---|
| 181 | + free(target); |
---|
| 182 | + perror("sys_perf_event_open"); |
---|
| 183 | + exit(EXIT_FAILURE); |
---|
| 184 | + } |
---|
| 185 | + |
---|
| 186 | + /* Shouldn't hit. */ |
---|
| 187 | + ioctl(break_fd, PERF_EVENT_IOC_RESET); |
---|
| 188 | + ioctl(break_fd, PERF_EVENT_IOC_ENABLE); |
---|
| 189 | + temp16 = *((__u16 *)target); |
---|
| 190 | + *((__u16 *)target) = temp16; |
---|
| 191 | + ioctl(break_fd, PERF_EVENT_IOC_DISABLE); |
---|
| 192 | + res = read(break_fd, &breaks, sizeof(unsigned long long)); |
---|
| 193 | + assert(res == sizeof(unsigned long long)); |
---|
| 194 | + if (breaks == 0) { |
---|
| 195 | + printf("TESTED: No overlap\n"); |
---|
| 196 | + } else { |
---|
| 197 | + printf("FAILED: No overlap: %lld != 0\n", breaks); |
---|
| 198 | + fail = 1; |
---|
| 199 | + } |
---|
| 200 | + |
---|
| 201 | + /* Hit */ |
---|
| 202 | + ioctl(break_fd, PERF_EVENT_IOC_RESET); |
---|
| 203 | + ioctl(break_fd, PERF_EVENT_IOC_ENABLE); |
---|
| 204 | + temp16 = *((__u16 *)(target + 1)); |
---|
| 205 | + *((__u16 *)(target + 1)) = temp16; |
---|
| 206 | + ioctl(break_fd, PERF_EVENT_IOC_DISABLE); |
---|
| 207 | + res = read(break_fd, &breaks, sizeof(unsigned long long)); |
---|
| 208 | + assert(res == sizeof(unsigned long long)); |
---|
| 209 | + if (breaks == 2) { |
---|
| 210 | + printf("TESTED: Partial overlap\n"); |
---|
| 211 | + } else { |
---|
| 212 | + printf("FAILED: Partial overlap: %lld != 2\n", breaks); |
---|
| 213 | + fail = 1; |
---|
| 214 | + } |
---|
| 215 | + |
---|
| 216 | + /* Hit */ |
---|
| 217 | + ioctl(break_fd, PERF_EVENT_IOC_RESET); |
---|
| 218 | + ioctl(break_fd, PERF_EVENT_IOC_ENABLE); |
---|
| 219 | + temp16 = *((__u16 *)(target + 5)); |
---|
| 220 | + *((__u16 *)(target + 5)) = temp16; |
---|
| 221 | + ioctl(break_fd, PERF_EVENT_IOC_DISABLE); |
---|
| 222 | + res = read(break_fd, &breaks, sizeof(unsigned long long)); |
---|
| 223 | + assert(res == sizeof(unsigned long long)); |
---|
| 224 | + if (breaks == 2) { |
---|
| 225 | + printf("TESTED: Partial overlap\n"); |
---|
| 226 | + } else { |
---|
| 227 | + printf("FAILED: Partial overlap: %lld != 2\n", breaks); |
---|
| 228 | + fail = 1; |
---|
| 229 | + } |
---|
| 230 | + |
---|
| 231 | + /* Shouldn't Hit */ |
---|
| 232 | + ioctl(break_fd, PERF_EVENT_IOC_RESET); |
---|
| 233 | + ioctl(break_fd, PERF_EVENT_IOC_ENABLE); |
---|
| 234 | + temp16 = *((__u16 *)(target + 6)); |
---|
| 235 | + *((__u16 *)(target + 6)) = temp16; |
---|
| 236 | + ioctl(break_fd, PERF_EVENT_IOC_DISABLE); |
---|
| 237 | + res = read(break_fd, &breaks, sizeof(unsigned long long)); |
---|
| 238 | + assert(res == sizeof(unsigned long long)); |
---|
| 239 | + if (breaks == 0) { |
---|
| 240 | + printf("TESTED: No overlap\n"); |
---|
| 241 | + } else { |
---|
| 242 | + printf("FAILED: No overlap: %lld != 0\n", breaks); |
---|
| 243 | + fail = 1; |
---|
| 244 | + } |
---|
| 245 | + |
---|
| 246 | + /* Hit */ |
---|
| 247 | + ioctl(break_fd, PERF_EVENT_IOC_RESET); |
---|
| 248 | + ioctl(break_fd, PERF_EVENT_IOC_ENABLE); |
---|
| 249 | + temp64 = *((__u64 *)target); |
---|
| 250 | + *((__u64 *)target) = temp64; |
---|
| 251 | + ioctl(break_fd, PERF_EVENT_IOC_DISABLE); |
---|
| 252 | + res = read(break_fd, &breaks, sizeof(unsigned long long)); |
---|
| 253 | + assert(res == sizeof(unsigned long long)); |
---|
| 254 | + if (breaks == 2) { |
---|
| 255 | + printf("TESTED: Full overlap\n"); |
---|
| 256 | + } else { |
---|
| 257 | + printf("FAILED: Full overlap: %lld != 2\n", breaks); |
---|
| 258 | + fail = 1; |
---|
| 259 | + } |
---|
| 260 | + |
---|
| 261 | + free(target); |
---|
| 262 | + close(break_fd); |
---|
| 263 | + return fail; |
---|
| 264 | +} |
---|
| 265 | + |
---|
155 | 266 | static int runtest(void) |
---|
156 | 267 | { |
---|
157 | 268 | int rwflag; |
---|
.. | .. |
---|
176 | 287 | return ret; |
---|
177 | 288 | } |
---|
178 | 289 | } |
---|
179 | | - return 0; |
---|
| 290 | + |
---|
| 291 | + ret = runtest_dar_outside(); |
---|
| 292 | + return ret; |
---|
180 | 293 | } |
---|
181 | 294 | |
---|
182 | 295 | |
---|