perf tools: Add machine__kernel_ip()
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 15 Aug 2014 19:08:39 +0000 (22:08 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 22 Aug 2014 16:12:12 +0000 (13:12 -0300)
Add a function to determine if an address is in the kernel.  This is
based on the kernel function kernel_ip().

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1408129739-17368-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/event.c
tools/perf/util/machine.c
tools/perf/util/machine.h

index 1398c83d896dffb170d5ca107bdb98e0d9630aaa..ed558191c0b3030ec9b7b259c9f12eaf8aa78041 100644 (file)
@@ -784,9 +784,9 @@ try_again:
                 * "[vdso]" dso, but for now lets use the old trick of looking
                 * in the whole kernel symbol list.
                 */
-               if ((long long)al->addr < 0 &&
-                   cpumode == PERF_RECORD_MISC_USER &&
-                   machine && mg != &machine->kmaps) {
+               if (cpumode == PERF_RECORD_MISC_USER && machine &&
+                   mg != &machine->kmaps &&
+                   machine__kernel_ip(machine, al->addr)) {
                        mg = &machine->kmaps;
                        load_map = true;
                        goto try_again;
index 37f8dc557ec027292fd7f937293caa287323d059..e00daf0d2bdecf09335d76a4b53d592f6abdc1ce 100644 (file)
@@ -32,6 +32,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
        machine->symbol_filter = NULL;
        machine->id_hdr_size = 0;
        machine->comm_exec = false;
+       machine->kernel_start = 0;
 
        machine->root_dir = strdup(root_dir);
        if (machine->root_dir == NULL)
@@ -1559,3 +1560,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
 
        return 0;
 }
+
+int machine__get_kernel_start(struct machine *machine)
+{
+       struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
+       int err = 0;
+
+       /*
+        * The only addresses above 2^63 are kernel addresses of a 64-bit
+        * kernel.  Note that addresses are unsigned so that on a 32-bit system
+        * all addresses including kernel addresses are less than 2^32.  In
+        * that case (32-bit system), if the kernel mapping is unknown, all
+        * addresses will be assumed to be in user space - see
+        * machine__kernel_ip().
+        */
+       machine->kernel_start = 1ULL << 63;
+       if (map) {
+               err = map__load(map, machine->symbol_filter);
+               if (map->start)
+                       machine->kernel_start = map->start;
+       }
+       return err;
+}
index 61216e028319b4a43003c705fa345d586615de8b..6a6bcc1cff54449db4f767d68d572b9e402d7f26 100644 (file)
@@ -36,6 +36,7 @@ struct machine {
        struct list_head  kernel_dsos;
        struct map_groups kmaps;
        struct map        *vmlinux_maps[MAP__NR_TYPES];
+       u64               kernel_start;
        symbol_filter_t   symbol_filter;
        pid_t             *current_tid;
 };
@@ -46,6 +47,22 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
        return machine->vmlinux_maps[type];
 }
 
+int machine__get_kernel_start(struct machine *machine);
+
+static inline u64 machine__kernel_start(struct machine *machine)
+{
+       if (!machine->kernel_start)
+               machine__get_kernel_start(machine);
+       return machine->kernel_start;
+}
+
+static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
+{
+       u64 kernel_start = machine__kernel_start(machine);
+
+       return ip >= kernel_start;
+}
+
 struct thread *machine__find_thread(struct machine *machine, pid_t pid,
                                    pid_t tid);
 struct comm *machine__thread_exec_comm(struct machine *machine,