perf_counter: Separate out attr->type from attr->config
authorIngo Molnar <mingo@elte.hu>
Sat, 6 Jun 2009 07:58:57 +0000 (09:58 +0200)
committerIngo Molnar <mingo@elte.hu>
Sat, 6 Jun 2009 09:37:22 +0000 (11:37 +0200)
Counter type is a frequently used value and we do a lot of
bit juggling by encoding and decoding it from attr->config.

Clean this up by creating a separate attr->type field.

Also clean up the various similarly complex user-space bits
all around counter attribute management.

The net improvement is significant, and it will be easier
to add a new major type (which is what triggered this cleanup).

(This changes the ABI, all tools are adapted.)
(PowerPC build-tested.)

Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Documentation/perf_counter/builtin-record.c
Documentation/perf_counter/builtin-stat.c
Documentation/perf_counter/builtin-top.c
Documentation/perf_counter/perf.h
Documentation/perf_counter/util/parse-events.c
Documentation/perf_counter/util/parse-events.h
arch/powerpc/kernel/perf_counter.c
arch/x86/kernel/cpu/perf_counter.c
include/linux/perf_counter.h
kernel/perf_counter.c

index c22ea0c..130fd88 100644 (file)
 #define ALIGN(x, a)            __ALIGN_MASK(x, (typeof(x))(a)-1)
 #define __ALIGN_MASK(x, mask)  (((x)+(mask))&~(mask))
 
-static long                    default_interval = 100000;
-static long                    event_count[MAX_COUNTERS];
-
 static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
+
+static long                    default_interval                = 100000;
+
 static int                     nr_cpus                         = 0;
 static unsigned int            page_size;
 static unsigned int            mmap_pages                      = 128;
@@ -38,22 +38,44 @@ static int                  inherit                         = 1;
 static int                     force                           = 0;
 static int                     append_file                     = 0;
 
-const unsigned int default_count[] = {
-       1000000,
-       1000000,
-         10000,
-         10000,
-       1000000,
-         10000,
+static long                    samples;
+static struct timeval          last_read;
+static struct timeval          this_read;
+
+static __u64                   bytes_written;
+
+static struct pollfd           event_array[MAX_NR_CPUS * MAX_COUNTERS];
+
+static int                     nr_poll;
+static int                     nr_cpu;
+
+struct mmap_event {
+       struct perf_event_header        header;
+       __u32                           pid;
+       __u32                           tid;
+       __u64                           start;
+       __u64                           len;
+       __u64                           pgoff;
+       char                            filename[PATH_MAX];
+};
+
+struct comm_event {
+       struct perf_event_header        header;
+       __u32                           pid;
+       __u32                           tid;
+       char                            comm[16];
 };
 
+
 struct mmap_data {
-       int counter;
-       void *base;
-       unsigned int mask;
-       unsigned int prev;
+       int                     counter;
+       void                    *base;
+       unsigned int            mask;
+       unsigned int            prev;
 };
 
+static struct mmap_data                mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
+
 static unsigned int mmap_read_head(struct mmap_data *md)
 {
        struct perf_counter_mmap_page *pc = md->base;
@@ -65,11 +87,6 @@ static unsigned int mmap_read_head(struct mmap_data *md)
        return head;
 }
 
-static long samples;
-static struct timeval last_read, this_read;
-
-static __u64 bytes_written;
-
 static void mmap_read(struct mmap_data *md)
 {
        unsigned int head = mmap_read_head(md);
@@ -157,29 +174,6 @@ static void sig_handler(int sig)
        done = 1;
 }
 
-static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
-static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
-
-static int nr_poll;
-static int nr_cpu;
-
-struct mmap_event {
-       struct perf_event_header        header;
-       __u32                           pid;
-       __u32                           tid;
-       __u64                           start;
-       __u64                           len;
-       __u64                           pgoff;
-       char                            filename[PATH_MAX];
-};
-
-struct comm_event {
-       struct perf_event_header        header;
-       __u32                           pid;
-       __u32                           tid;
-       char                            comm[16];
-};
-
 static void pid_synthesize_comm_event(pid_t pid, int full)
 {
        struct comm_event comm_ev;
@@ -341,24 +335,21 @@ static int group_fd;
 
 static void create_counter(int counter, int cpu, pid_t pid)
 {
-       struct perf_counter_attr attr;
+       struct perf_counter_attr *attr = attrs + counter;
        int track = 1;
 
-       memset(&attr, 0, sizeof(attr));
-       attr.config             = event_id[counter];
-       attr.sample_period      = event_count[counter];
-       attr.sample_type        = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_PERIOD;
+       attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_PERIOD;
        if (freq) {
-               attr.freq               = 1;
-               attr.sample_freq        = freq;
+               attr->freq              = 1;
+               attr->sample_freq       = freq;
        }
-       attr.mmap               = track;
-       attr.comm               = track;
-       attr.inherit            = (cpu < 0) && inherit;
+       attr->mmap              = track;
+       attr->comm              = track;
+       attr->inherit           = (cpu < 0) && inherit;
 
        track = 0; /* only the first counter needs these */
 
-       fd[nr_cpu][counter] = sys_perf_counter_open(&attr, pid, cpu, group_fd, 0);
+       fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
 
        if (fd[nr_cpu][counter] < 0) {
                int err = errno;
@@ -542,16 +533,14 @@ int cmd_record(int argc, const char **argv, const char *prefix)
        if (!argc && target_pid == -1 && !system_wide)
                usage_with_options(record_usage, options);
 
-       if (!nr_counters) {
+       if (!nr_counters)
                nr_counters = 1;
-               event_id[0] = 0;
-       }
 
        for (counter = 0; counter < nr_counters; counter++) {
-               if (event_count[counter])
+               if (attrs[counter].sample_period)
                        continue;
 
-               event_count[counter] = default_interval;
+               attrs[counter].sample_period = default_interval;
        }
 
        return __cmd_record(argc, argv);
index 4fc0d80..9711e55 100644 (file)
 
 #include <sys/prctl.h>
 
-static int                     system_wide                     =  0;
-static int                     inherit                         =  1;
+static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
 
-static __u64                   default_event_id[MAX_COUNTERS]  = {
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS),
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_TASK_CLOCK                },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CONTEXT_SWITCHES  },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CPU_MIGRATIONS    },
+  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_PAGE_FAULTS       },
 
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES),
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CPU_CYCLES                },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_INSTRUCTIONS      },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_REFERENCES  },
+  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_MISSES      },
 };
 
-static int                     default_interval = 100000;
-static int                     event_count[MAX_COUNTERS];
+static int                     system_wide                     =  0;
+static int                     inherit                         =  1;
+
 static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
 
 static int                     target_pid                      = -1;
@@ -86,22 +85,16 @@ static __u64                        walltime_nsecs;
 
 static void create_perfstat_counter(int counter)
 {
-       struct perf_counter_attr attr;
-
-       memset(&attr, 0, sizeof(attr));
-       attr.config             = event_id[counter];
-       attr.sample_type        = 0;
-       attr.exclude_kernel = event_mask[counter] & EVENT_MASK_KERNEL;
-       attr.exclude_user   = event_mask[counter] & EVENT_MASK_USER;
+       struct perf_counter_attr *attr = attrs + counter;
 
        if (scale)
-               attr.read_format        = PERF_FORMAT_TOTAL_TIME_ENABLED |
-                                         PERF_FORMAT_TOTAL_TIME_RUNNING;
+               attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
+                                   PERF_FORMAT_TOTAL_TIME_RUNNING;
 
        if (system_wide) {
                int cpu;
                for (cpu = 0; cpu < nr_cpus; cpu ++) {
-                       fd[cpu][counter] = sys_perf_counter_open(&attr, -1, cpu, -1, 0);
+                       fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
                        if (fd[cpu][counter] < 0) {
                                printf("perfstat error: syscall returned with %d (%s)\n",
                                                fd[cpu][counter], strerror(errno));
@@ -109,10 +102,10 @@ static void create_perfstat_counter(int counter)
                        }
                }
        } else {
-               attr.inherit    = inherit;
-               attr.disabled   = 1;
+               attr->inherit   = inherit;
+               attr->disabled  = 1;
 
-               fd[0][counter] = sys_perf_counter_open(&attr, 0, -1, -1, 0);
+               fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0);
                if (fd[0][counter] < 0) {
                        printf("perfstat error: syscall returned with %d (%s)\n",
                                        fd[0][counter], strerror(errno));
@@ -126,9 +119,13 @@ static void create_perfstat_counter(int counter)
  */
 static inline int nsec_counter(int counter)
 {
-       if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK))
+       if (attrs[counter].type != PERF_TYPE_SOFTWARE)
+               return 0;
+
+       if (attrs[counter].config == PERF_COUNT_CPU_CLOCK)
                return 1;
-       if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK))
+
+       if (attrs[counter].config == PERF_COUNT_TASK_CLOCK)
                return 1;
 
        return 0;
@@ -177,7 +174,8 @@ static void read_counter(int counter)
        /*
         * Save the full runtime - to allow normalization during printout:
         */
-       if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK))
+       if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
+               attrs[counter].config == PERF_COUNT_TASK_CLOCK)
                runtime_nsecs = count[0];
 }
 
@@ -203,8 +201,8 @@ static void print_counter(int counter)
 
                fprintf(stderr, " %14.6f  %-20s",
                        msecs, event_name(counter));
-               if (event_id[counter] ==
-                               EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) {
+               if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
+                       attrs[counter].config == PERF_COUNT_TASK_CLOCK) {
 
                        fprintf(stderr, " # %11.3f CPU utilization factor",
                                (double)count[0] / (double)walltime_nsecs);
@@ -300,8 +298,6 @@ static char events_help_msg[EVENTS_HELP_MAX];
 static const struct option options[] = {
        OPT_CALLBACK('e', "event", NULL, "event",
                     events_help_msg, parse_events),
-       OPT_INTEGER('c', "count", &default_interval,
-                   "event period to sample"),
        OPT_BOOLEAN('i', "inherit", &inherit,
                    "child tasks inherit counters"),
        OPT_INTEGER('p', "pid", &target_pid,
@@ -315,27 +311,19 @@ static const struct option options[] = {
 
 int cmd_stat(int argc, const char **argv, const char *prefix)
 {
-       int counter;
-
        page_size = sysconf(_SC_PAGE_SIZE);
 
        create_events_help(events_help_msg);
-       memcpy(event_id, default_event_id, sizeof(default_event_id));
+
+       memcpy(attrs, default_attrs, sizeof(attrs));
 
        argc = parse_options(argc, argv, options, stat_usage, 0);
        if (!argc)
                usage_with_options(stat_usage, options);
 
-       if (!nr_counters) {
+       if (!nr_counters)
                nr_counters = 8;
-       }
-
-       for (counter = 0; counter < nr_counters; counter++) {
-               if (event_count[counter])
-                       continue;
 
-               event_count[counter] = default_interval;
-       }
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        assert(nr_cpus <= MAX_NR_CPUS);
        assert(nr_cpus >= 0);
index b2f480b..98a6d53 100644 (file)
 #include <linux/unistd.h>
 #include <linux/types.h>
 
-static int                     system_wide                     =  0;
+static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
 
-static __u64                   default_event_id[MAX_COUNTERS]          = {
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS),
-       EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS),
+static int                     system_wide                     =  0;
 
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES),
-       EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES),
-};
-static int                     default_interval = 100000;
-static int                     event_count[MAX_COUNTERS];
-static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
+static int                     default_interval                = 100000;
 
 static __u64                   count_filter                    =  5;
 static int                     print_entries                   = 15;
@@ -85,15 +74,6 @@ static int                   delay_secs                      =  2;
 static int                     zero;
 static int                     dump_symtab;
 
-static const unsigned int default_count[] = {
-       1000000,
-       1000000,
-         10000,
-         10000,
-       1000000,
-         10000,
-};
-
 /*
  * Symbols
  */
@@ -112,7 +92,7 @@ struct sym_entry {
 
 struct sym_entry               *sym_filter_entry;
 
-struct dso *kernel_dso;
+struct dso                     *kernel_dso;
 
 /*
  * Symbols will be added here in record_ip and will get out
@@ -213,7 +193,7 @@ static void print_sym_table(void)
                100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
 
        if (nr_counters == 1) {
-               printf("%d", event_count[0]);
+               printf("%Ld", attrs[0].sample_period);
                if (freq)
                        printf("Hz ");
                else
@@ -421,10 +401,10 @@ static void process_event(uint64_t ip, int counter)
 }
 
 struct mmap_data {
-       int counter;
-       void *base;
-       unsigned int mask;
-       unsigned int prev;
+       int                     counter;
+       void                    *base;
+       unsigned int            mask;
+       unsigned int            prev;
 };
 
 static unsigned int mmap_read_head(struct mmap_data *md)
@@ -539,7 +519,7 @@ static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
 
 static int __cmd_top(void)
 {
-       struct perf_counter_attr attr;
+       struct perf_counter_attr *attr;
        pthread_t thread;
        int i, counter, group_fd, nr_poll = 0;
        unsigned int cpu;
@@ -553,13 +533,12 @@ static int __cmd_top(void)
                        if (target_pid == -1 && profile_cpu == -1)
                                cpu = i;
 
-                       memset(&attr, 0, sizeof(attr));
-                       attr.config             = event_id[counter];
-                       attr.sample_period      = event_count[counter];
-                       attr.sample_type        = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
-                       attr.freq               = freq;
+                       attr = attrs + counter;
 
-                       fd[i][counter] = sys_perf_counter_open(&attr, target_pid, cpu, group_fd, 0);
+                       attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+                       attr->freq              = freq;
+
+                       fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
                        if (fd[i][counter] < 0) {
                                int err = errno;
 
@@ -670,7 +649,6 @@ int cmd_top(int argc, const char **argv, const char *prefix)
        page_size = sysconf(_SC_PAGE_SIZE);
 
        create_events_help(events_help_msg);
-       memcpy(event_id, default_event_id, sizeof(default_event_id));
 
        argc = parse_options(argc, argv, options, top_usage, 0);
        if (argc)
@@ -688,19 +666,22 @@ int cmd_top(int argc, const char **argv, const char *prefix)
                profile_cpu = -1;
        }
 
-       if (!nr_counters) {
+       if (!nr_counters)
                nr_counters = 1;
-               event_id[0] = 0;
-       }
 
        if (delay_secs < 1)
                delay_secs = 1;
 
+       parse_symbols();
+
+       /*
+        * Fill in the ones not specifically initialized via -c:
+        */
        for (counter = 0; counter < nr_counters; counter++) {
-               if (event_count[counter])
+               if (attrs[counter].sample_period)
                        continue;
 
-               event_count[counter] = default_interval;
+               attrs[counter].sample_period = default_interval;
        }
 
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
@@ -710,7 +691,5 @@ int cmd_top(int argc, const char **argv, const char *prefix)
        if (target_pid != -1 || profile_cpu != -1)
                nr_cpus = 1;
 
-       parse_symbols();
-
        return __cmd_top();
 }
index 10622a4..af0a504 100644 (file)
@@ -64,6 +64,4 @@ sys_perf_counter_open(struct perf_counter_attr *attr_uptr,
 #define MAX_COUNTERS                   256
 #define MAX_NR_CPUS                    256
 
-#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
-
 #endif
index 2fdfd1d..eb56bd9 100644 (file)
@@ -6,37 +6,39 @@
 #include "exec_cmd.h"
 #include "string.h"
 
-int nr_counters;
+int                                    nr_counters;
 
-__u64                  event_id[MAX_COUNTERS]          = { };
-int                    event_mask[MAX_COUNTERS];
+struct perf_counter_attr               attrs[MAX_COUNTERS];
 
 struct event_symbol {
-       __u64 event;
-       char *symbol;
+       __u8    type;
+       __u64   config;
+       char    *symbol;
 };
 
+#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
+
 static struct event_symbol event_symbols[] = {
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES),                "cpu-cycles",           },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES),                "cycles",               },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS),              "instructions",         },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES),          "cache-references",     },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES),              "cache-misses",         },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS),       "branch-instructions",  },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS),       "branches",             },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES),             "branch-misses",        },
-       {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES),                "bus-cycles",           },
-
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK),                 "cpu-clock",            },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK),                "task-clock",           },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS),               "page-faults",          },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS),               "faults",               },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN),           "minor-faults",         },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ),           "major-faults",         },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES),          "context-switches",     },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES),          "cs",                   },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS),            "cpu-migrations",       },
-       {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS),            "migrations",           },
+  { C(HARDWARE, CPU_CYCLES),           "cpu-cycles",           },
+  { C(HARDWARE, CPU_CYCLES),           "cycles",               },
+  { C(HARDWARE, INSTRUCTIONS),         "instructions",         },
+  { C(HARDWARE, CACHE_REFERENCES),     "cache-references",     },
+  { C(HARDWARE, CACHE_MISSES),         "cache-misses",         },
+  { C(HARDWARE, BRANCH_INSTRUCTIONS),  "branch-instructions",  },
+  { C(HARDWARE, BRANCH_INSTRUCTIONS),  "branches",             },
+  { C(HARDWARE, BRANCH_MISSES),                "branch-misses",        },
+  { C(HARDWARE, BUS_CYCLES),           "bus-cycles",           },
+
+  { C(SOFTWARE, CPU_CLOCK),            "cpu-clock",            },
+  { C(SOFTWARE, TASK_CLOCK),           "task-clock",           },
+  { C(SOFTWARE, PAGE_FAULTS),          "page-faults",          },
+  { C(SOFTWARE, PAGE_FAULTS),          "faults",               },
+  { C(SOFTWARE, PAGE_FAULTS_MIN),      "minor-faults",         },
+  { C(SOFTWARE, PAGE_FAULTS_MAJ),      "major-faults",         },
+  { C(SOFTWARE, CONTEXT_SWITCHES),     "context-switches",     },
+  { C(SOFTWARE, CONTEXT_SWITCHES),     "cs",                   },
+  { C(SOFTWARE, CPU_MIGRATIONS),       "cpu-migrations",       },
+  { C(SOFTWARE, CPU_MIGRATIONS),       "migrations",           },
 };
 
 #define __PERF_COUNTER_FIELD(config, name) \
@@ -67,27 +69,26 @@ static char *sw_event_names[] = {
        "major faults",
 };
 
-char *event_name(int ctr)
+char *event_name(int counter)
 {
-       __u64 config = event_id[ctr];
-       int type = PERF_COUNTER_TYPE(config);
-       int id = PERF_COUNTER_ID(config);
+       __u64 config = attrs[counter].config;
+       int type = attrs[counter].type;
        static char buf[32];
 
-       if (PERF_COUNTER_RAW(config)) {
-               sprintf(buf, "raw 0x%llx", PERF_COUNTER_CONFIG(config));
+       if (attrs[counter].type == PERF_TYPE_RAW) {
+               sprintf(buf, "raw 0x%llx", config);
                return buf;
        }
 
        switch (type) {
        case PERF_TYPE_HARDWARE:
-               if (id < PERF_HW_EVENTS_MAX)
-                       return hw_event_names[id];
+               if (config < PERF_HW_EVENTS_MAX)
+                       return hw_event_names[config];
                return "unknown-hardware";
 
        case PERF_TYPE_SOFTWARE:
-               if (id < PERF_SW_EVENTS_MAX)
-                       return sw_event_names[id];
+               if (config < PERF_SW_EVENTS_MAX)
+                       return sw_event_names[config];
                return "unknown-software";
 
        default:
@@ -101,15 +102,19 @@ char *event_name(int ctr)
  * Each event can have multiple symbolic names.
  * Symbolic names are (almost) exactly matched.
  */
-static __u64 match_event_symbols(const char *str)
+static int match_event_symbols(const char *str, struct perf_counter_attr *attr)
 {
        __u64 config, id;
        int type;
        unsigned int i;
        const char *sep, *pstr;
 
-       if (str[0] == 'r' && hex2u64(str + 1, &config) > 0)
-               return config | PERF_COUNTER_RAW_MASK;
+       if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
+               attr->type = PERF_TYPE_RAW;
+               attr->config = config;
+
+               return 0;
+       }
 
        pstr = str;
        sep = strchr(pstr, ':');
@@ -121,35 +126,45 @@ static __u64 match_event_symbols(const char *str)
                if (sep) {
                        pstr = sep + 1;
                        if (strchr(pstr, 'k'))
-                               event_mask[nr_counters] |= EVENT_MASK_USER;
+                               attr->exclude_user = 1;
                        if (strchr(pstr, 'u'))
-                               event_mask[nr_counters] |= EVENT_MASK_KERNEL;
+                               attr->exclude_kernel = 1;
                }
-               return EID(type, id);
+               attr->type = type;
+               attr->config = id;
+
+               return 0;
        }
 
        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
                if (!strncmp(str, event_symbols[i].symbol,
-                            strlen(event_symbols[i].symbol)))
-                       return event_symbols[i].event;
+                            strlen(event_symbols[i].symbol))) {
+
+                       attr->type = event_symbols[i].type;
+                       attr->config = event_symbols[i].config;
+
+                       return 0;
+               }
        }
 
-       return ~0ULL;
+       return -EINVAL;
 }
 
 int parse_events(const struct option *opt, const char *str, int unset)
 {
-       __u64 config;
+       struct perf_counter_attr attr;
+       int ret;
 
+       memset(&attr, 0, sizeof(attr));
 again:
        if (nr_counters == MAX_COUNTERS)
                return -1;
 
-       config = match_event_symbols(str);
-       if (config == ~0ULL)
-               return -1;
+       ret = match_event_symbols(str, &attr);
+       if (ret < 0)
+               return ret;
 
-       event_id[nr_counters] = config;
+       attrs[nr_counters] = attr;
        nr_counters++;
 
        str = strstr(str, ",");
@@ -168,7 +183,6 @@ void create_events_help(char *events_help_msg)
 {
        unsigned int i;
        char *str;
-       __u64 e;
 
        str = events_help_msg;
 
@@ -178,9 +192,8 @@ void create_events_help(char *events_help_msg)
        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
                int type, id;
 
-               e = event_symbols[i].event;
-               type = PERF_COUNTER_TYPE(e);
-               id = PERF_COUNTER_ID(e);
+               type = event_symbols[i].type;
+               id = event_symbols[i].config;
 
                if (i)
                        str += sprintf(str, "|");
@@ -191,4 +204,3 @@ void create_events_help(char *events_help_msg)
 
        str += sprintf(str, "|rNNN]");
 }
-
index 0da306b..542971c 100644 (file)
@@ -3,12 +3,9 @@
  * Parse symbolic events/counts passed in as options:
  */
 
-extern int nr_counters;
-extern __u64                   event_id[MAX_COUNTERS];
-extern int                     event_mask[MAX_COUNTERS];
+extern int                     nr_counters;
 
-#define EVENT_MASK_KERNEL      1
-#define EVENT_MASK_USER                2
+extern struct perf_counter_attr attrs[MAX_COUNTERS];
 
 extern char *event_name(int ctr);
 
index 232b00a..4786ad9 100644 (file)
@@ -867,13 +867,13 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
 
        if (!ppmu)
                return ERR_PTR(-ENXIO);
-       if (!perf_event_raw(&counter->attr)) {
-               ev = perf_event_id(&counter->attr);
+       if (counter->attr.type != PERF_TYPE_RAW) {
+               ev = counter->attr.config;
                if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
                        return ERR_PTR(-EOPNOTSUPP);
                ev = ppmu->generic_events[ev];
        } else {
-               ev = perf_event_config(&counter->attr);
+               ev = counter->attr.config;
        }
        counter->hw.config_base = ev;
        counter->hw.idx = 0;
index 8f53f3a..430e048 100644 (file)
@@ -292,15 +292,15 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
        /*
         * Raw event type provide the config in the event structure
         */
-       if (perf_event_raw(attr)) {
-               hwc->config |= x86_pmu.raw_event(perf_event_config(attr));
+       if (attr->type == PERF_TYPE_RAW) {
+               hwc->config |= x86_pmu.raw_event(attr->config);
        } else {
-               if (perf_event_id(attr) >= x86_pmu.max_events)
+               if (attr->config >= x86_pmu.max_events)
                        return -EINVAL;
                /*
                 * The generic map:
                 */
-               hwc->config |= x86_pmu.event_map(perf_event_id(attr));
+               hwc->config |= x86_pmu.event_map(attr->config);
        }
 
        counter->destroy = hw_perf_counter_destroy;
index 4f9d39e..f794c69 100644 (file)
@@ -73,26 +73,6 @@ enum sw_event_ids {
        PERF_SW_EVENTS_MAX              = 7,
 };
 
-#define __PERF_COUNTER_MASK(name)                      \
-       (((1ULL << PERF_COUNTER_##name##_BITS) - 1) <<  \
-        PERF_COUNTER_##name##_SHIFT)
-
-#define PERF_COUNTER_RAW_BITS          1
-#define PERF_COUNTER_RAW_SHIFT         63
-#define PERF_COUNTER_RAW_MASK          __PERF_COUNTER_MASK(RAW)
-
-#define PERF_COUNTER_CONFIG_BITS       63
-#define PERF_COUNTER_CONFIG_SHIFT      0
-#define PERF_COUNTER_CONFIG_MASK       __PERF_COUNTER_MASK(CONFIG)
-
-#define PERF_COUNTER_TYPE_BITS         7
-#define PERF_COUNTER_TYPE_SHIFT                56
-#define PERF_COUNTER_TYPE_MASK         __PERF_COUNTER_MASK(TYPE)
-
-#define PERF_COUNTER_EVENT_BITS                56
-#define PERF_COUNTER_EVENT_SHIFT       0
-#define PERF_COUNTER_EVENT_MASK                __PERF_COUNTER_MASK(EVENT)
-
 /*
  * Bits that can be set in attr.sample_type to request information
  * in the overflow packets.
@@ -125,10 +105,13 @@ enum perf_counter_read_format {
  */
 struct perf_counter_attr {
        /*
-        * The MSB of the config word signifies if the rest contains cpu
-        * specific (raw) counter configuration data, if unset, the next
-        * 7 bits are an event type and the rest of the bits are the event
-        * identifier.
+        * Major type: hardware/software/tracepoint/etc.
+        */
+       __u32                   type;
+       __u32                   __reserved_1;
+
+       /*
+        * Type specific configuration information.
         */
        __u64                   config;
 
@@ -152,12 +135,11 @@ struct perf_counter_attr {
                                comm           :  1, /* include comm data     */
                                freq           :  1, /* use freq, not period  */
 
-                               __reserved_1   : 53;
+                               __reserved_2   : 53;
 
        __u32                   wakeup_events;  /* wakeup every n events */
-       __u32                   __reserved_2;
+       __u32                   __reserved_3;
 
-       __u64                   __reserved_3;
        __u64                   __reserved_4;
 };
 
@@ -278,8 +260,8 @@ enum perf_event_type {
 
        /*
         * struct {
-        *      struct perf_event_header        header;
-        *      u32                             pid, ppid;
+        *      struct perf_event_header        header;
+        *      u32                             pid, ppid;
         * };
         */
        PERF_EVENT_FORK                 = 7,
@@ -331,27 +313,6 @@ enum perf_event_type {
 
 struct task_struct;
 
-static inline u64 perf_event_raw(struct perf_counter_attr *attr)
-{
-       return attr->config & PERF_COUNTER_RAW_MASK;
-}
-
-static inline u64 perf_event_config(struct perf_counter_attr *attr)
-{
-       return attr->config & PERF_COUNTER_CONFIG_MASK;
-}
-
-static inline u64 perf_event_type(struct perf_counter_attr *attr)
-{
-       return (attr->config & PERF_COUNTER_TYPE_MASK) >>
-               PERF_COUNTER_TYPE_SHIFT;
-}
-
-static inline u64 perf_event_id(struct perf_counter_attr *attr)
-{
-       return attr->config & PERF_COUNTER_EVENT_MASK;
-}
-
 /**
  * struct hw_perf_counter - performance counter hardware details:
  */
@@ -616,8 +577,8 @@ extern int perf_counter_overflow(struct perf_counter *counter,
  */
 static inline int is_software_counter(struct perf_counter *counter)
 {
-       return !perf_event_raw(&counter->attr) &&
-               perf_event_type(&counter->attr) != PERF_TYPE_HARDWARE;
+       return (counter->attr.type != PERF_TYPE_RAW) &&
+               (counter->attr.type != PERF_TYPE_HARDWARE);
 }
 
 extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64);
index 47c92fb..75ae767 100644 (file)
@@ -3091,14 +3091,12 @@ static int perf_swcounter_match(struct perf_counter *counter,
                                enum perf_event_types type,
                                u32 event, struct pt_regs *regs)
 {
-       u64 event_config;
-
-       event_config = ((u64) type << PERF_COUNTER_TYPE_SHIFT) | event;
-
        if (!perf_swcounter_is_counting(counter))
                return 0;
 
-       if (counter->attr.config != event_config)
+       if (counter->attr.type != type)
+               return 0;
+       if (counter->attr.config != event)
                return 0;
 
        if (regs) {
@@ -3403,7 +3401,7 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
         * to be kernel events, and page faults are never hypervisor
         * events.
         */
-       switch (perf_event_id(&counter->attr)) {
+       switch (counter->attr.config) {
        case PERF_COUNT_CPU_CLOCK:
                pmu = &perf_ops_cpu_clock;
 
@@ -3496,12 +3494,12 @@ perf_counter_alloc(struct perf_counter_attr *attr,
        if (attr->inherit && (attr->sample_type & PERF_SAMPLE_GROUP))
                goto done;
 
-       if (perf_event_raw(attr)) {
+       if (attr->type == PERF_TYPE_RAW) {
                pmu = hw_perf_counter_init(counter);
                goto done;
        }
 
-       switch (perf_event_type(attr)) {
+       switch (attr->type) {
        case PERF_TYPE_HARDWARE:
                pmu = hw_perf_counter_init(counter);
                break;