This source file includes following definitions.
- sys_perf_event_open
- breakpoint_test
- perf_breakpoint_supported
- dawr_supported
- runtestsingle
- runtest
- perf_hwbreak
- main
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 #include <unistd.h>
  21 #include <assert.h>
  22 #include <stdio.h>
  23 #include <stdlib.h>
  24 #include <string.h>
  25 #include <sys/ioctl.h>
  26 #include <elf.h>
  27 #include <pthread.h>
  28 #include <sys/syscall.h>
  29 #include <linux/perf_event.h>
  30 #include <linux/hw_breakpoint.h>
  31 #include "utils.h"
  32 
  33 #define MAX_LOOPS 10000
  34 
  35 #define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
  36 
  37 static inline int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid,
  38                                       int cpu, int group_fd,
  39                                       unsigned long flags)
  40 {
  41         attr->size = sizeof(*attr);
  42         return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
  43 }
  44 
  45 static inline bool breakpoint_test(int len)
  46 {
  47         struct perf_event_attr attr;
  48         int fd;
  49 
  50         
  51         memset(&attr, 0, sizeof(attr));
  52         attr.disabled = 1;
  53         attr.type = PERF_TYPE_BREAKPOINT;
  54         attr.bp_type = HW_BREAKPOINT_R;
  55         
  56         attr.bp_addr = (__u64)(&attr) & 0xfffffffffffff800;
  57         attr.bp_len = len;
  58         fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
  59         if (fd < 0)
  60                 return false;
  61         close(fd);
  62         return true;
  63 }
  64 
  65 static inline bool perf_breakpoint_supported(void)
  66 {
  67         return breakpoint_test(4);
  68 }
  69 
  70 static inline bool dawr_supported(void)
  71 {
  72         return breakpoint_test(DAWR_LENGTH_MAX);
  73 }
  74 
  75 static int runtestsingle(int readwriteflag, int exclude_user, int arraytest)
  76 {
  77         int i,j;
  78         struct perf_event_attr attr;
  79         size_t res;
  80         unsigned long long breaks, needed;
  81         int readint;
  82         int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
  83         int *readintalign;
  84         volatile int *ptr;
  85         int break_fd;
  86         int loop_num = MAX_LOOPS - (rand() % 100); 
  87         volatile int *k;
  88 
  89         
  90         readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) &
  91                                0xfffffffffffff800);
  92 
  93         ptr = &readint;
  94         if (arraytest)
  95                 ptr = &readintalign[0];
  96 
  97         
  98         memset(&attr, 0, sizeof(attr));
  99         attr.disabled = 1;
 100         attr.type = PERF_TYPE_BREAKPOINT;
 101         attr.bp_type = readwriteflag;
 102         attr.bp_addr = (__u64)ptr;
 103         attr.bp_len = sizeof(int);
 104         if (arraytest)
 105                 attr.bp_len = DAWR_LENGTH_MAX;
 106         attr.exclude_user = exclude_user;
 107         break_fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
 108         if (break_fd < 0) {
 109                 perror("sys_perf_event_open");
 110                 exit(1);
 111         }
 112 
 113         
 114         ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
 115 
 116         
 117         k = &readint;
 118         for (i = 0; i < loop_num; i++) {
 119                 if (arraytest)
 120                         k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
 121 
 122                 j = *k;
 123                 *k = j;
 124         }
 125 
 126         
 127         ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
 128 
 129         
 130         res = read(break_fd, &breaks, sizeof(unsigned long long));
 131         assert(res == sizeof(unsigned long long));
 132         
 133         needed = 0;
 134         if (readwriteflag & HW_BREAKPOINT_R)
 135                 needed += loop_num;
 136         if (readwriteflag & HW_BREAKPOINT_W)
 137                 needed += loop_num;
 138         needed = needed * (1 - exclude_user);
 139         printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n",
 140                (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest);
 141         if (breaks != needed) {
 142                 printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
 143                        (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
 144                 return 1;
 145         }
 146         close(break_fd);
 147 
 148         return 0;
 149 }
 150 
 151 static int runtest(void)
 152 {
 153         int rwflag;
 154         int exclude_user;
 155         int ret;
 156 
 157         
 158 
 159 
 160 
 161         for (rwflag = 1 ; rwflag < 4; rwflag++) {
 162                 for (exclude_user = 0 ; exclude_user < 2; exclude_user++) {
 163                         ret = runtestsingle(rwflag, exclude_user, 0);
 164                         if (ret)
 165                                 return ret;
 166 
 167                         
 168                         if (!dawr_supported())
 169                                 continue;
 170                         ret = runtestsingle(rwflag, exclude_user, 1);
 171                         if (ret)
 172                                 return ret;
 173                 }
 174         }
 175         return 0;
 176 }
 177 
 178 
 179 static int perf_hwbreak(void)
 180 {
 181         srand ( time(NULL) );
 182 
 183         SKIP_IF(!perf_breakpoint_supported());
 184 
 185         return runtest();
 186 }
 187 
 188 int main(int argc, char *argv[], char **envp)
 189 {
 190         return test_harness(perf_hwbreak, "perf_hwbreak");
 191 }