~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/tests/bp_account.c

Version: ~ [ linux-6.0 ] ~ [ linux-5.19.12 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.71 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.146 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.215 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.260 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.295 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.330 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp