This patch adds support for PERF_SAMPLE_PHYS_ADDR to perf mem
and supporting code in the infrastructure.

Signed-off-by: Stephane Eranian <eran...@google.com>
---
 tools/perf/builtin-mem.c    | 116 +++++++++++++++++++++++++++++++++-----------
 tools/perf/builtin-report.c |   2 +-
 tools/perf/util/hist.c      |   4 +-
 tools/perf/util/hist.h      |   1 +
 tools/perf/util/machine.c   |   1 +
 tools/perf/util/sort.c      |  42 ++++++++++++++++
 tools/perf/util/sort.h      |   1 +
 tools/perf/util/symbol.h    |   1 +
 8 files changed, 139 insertions(+), 29 deletions(-)

diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index a8ff6d2..5946f6a 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -17,6 +17,7 @@ struct perf_mem {
        symbol_filter_t         annotate_init;
        bool                    hide_unresolved;
        bool                    dump_raw;
+       bool                    phys_addr;
        const char              *cpu_list;
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
@@ -26,14 +27,14 @@ static const char * const mem_usage[] = {
        NULL
 };
 
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
        char event[64];
        int ret;
 
-       rec_argc = argc + 4;
+       rec_argc = argc + 5;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        if (!rec_argv)
                return -1;
@@ -42,6 +43,10 @@ static int __cmd_record(int argc, const char **argv)
        if (!strcmp(mem_operation, MEM_OPERATION_LOAD))
                rec_argv[i++] = strdup("-W");
        rec_argv[i++] = strdup("-d");
+
+       if (mem->phys_addr)
+               rec_argv[i++] = strdup("--phys-addr");
+
        rec_argv[i++] = strdup("-e");
 
        if (strcmp(mem_operation, MEM_OPERATION_LOAD))
@@ -83,29 +88,62 @@ dump_raw_samples(struct perf_tool *tool,
                al.map->dso->hit = 1;
 
        if (symbol_conf.field_sep) {
-               fmt = "%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s%"PRIu64
-                     "%s0x%"PRIx64"%s%s:%s\n";
+               if (mem->phys_addr)
+                       fmt = "%d%s%d%s%d%s0x%"PRIx64"%s0x%"PRIx64"%s0x%"PRIx64
+                             "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
+               else
+                       fmt = "%d%s%d%s%d%s0x%"PRIx64"%s0x%"PRIx64
+                             "%s%"PRIu64"%s0x%"PRIx64"%s%s:%s\n";
        } else {
-               fmt = "%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
-                     "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
+               if (mem->phys_addr)
+                       fmt = "%5d%s%5d%s%5d%s0x%016"PRIx64"%s0x%016"PRIx64
+                             "%s0x016%"PRIx64"%s%5"PRIu64"%s0x%06"
+                             PRIx64"%s%s:%s\n";
+               else
+                       fmt = "%5d%s%5d%s%5d%s0x%016"PRIx64"%s0x016%"PRIx64
+                             "%s%5"PRIu64"%s0x%06"PRIx64"%s%s:%s\n";
                symbol_conf.field_sep = " ";
        }
-
-       printf(fmt,
-               sample->pid,
-               symbol_conf.field_sep,
-               sample->tid,
-               symbol_conf.field_sep,
-               event->ip.ip,
-               symbol_conf.field_sep,
-               sample->addr,
-               symbol_conf.field_sep,
-               sample->weight,
-               symbol_conf.field_sep,
-               sample->data_src,
-               symbol_conf.field_sep,
-               al.map ? (al.map->dso ? al.map->dso->long_name : "???") : "???",
-               al.sym ? al.sym->name : "???");
+       if (mem->phys_addr)
+               printf(fmt,
+                      sample->pid,
+                      symbol_conf.field_sep,
+                      sample->tid,
+                      symbol_conf.field_sep,
+                      sample->cpu,
+                      symbol_conf.field_sep,
+                      event->ip.ip,
+                      symbol_conf.field_sep,
+                      sample->addr,
+                      symbol_conf.field_sep,
+                      sample->paddr,
+                      symbol_conf.field_sep,
+                      sample->weight,
+                      symbol_conf.field_sep,
+                      sample->data_src,
+                      symbol_conf.field_sep,
+                      al.map ? (al.map->dso ?
+                                al.map->dso->long_name : "???") : "???",
+                      al.sym ? al.sym->name : "???");
+       else
+               printf(fmt,
+                      sample->pid,
+                      symbol_conf.field_sep,
+                      sample->tid,
+                      symbol_conf.field_sep,
+                      sample->cpu,
+                      symbol_conf.field_sep,
+                      event->ip.ip,
+                      symbol_conf.field_sep,
+                      sample->addr,
+                      symbol_conf.field_sep,
+                      sample->weight,
+                      symbol_conf.field_sep,
+                      sample->data_src,
+                      symbol_conf.field_sep,
+                      al.map ? (al.map->dso ?
+                                al.map->dso->long_name : "???") : "???",
+                      al.sym ? al.sym->name : "???");
 
        return 0;
 }
@@ -139,7 +177,10 @@ static int report_raw_events(struct perf_mem *mem)
        if (symbol__init() < 0)
                return -1;
 
-       printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
+       if (mem->phys_addr)
+               printf("# PID, TID, CPU, IP, ADDR, PADDR, LOCAL WEIGHT, DSRC, 
SYMBOL\n");
+       else
+               printf("# PID, TID, CPU, IP, ADDR, LOCAL WEIGHT, DSRC, 
SYMBOL\n");
 
        err = perf_session__process_events(session, &mem->tool);
        if (err)
@@ -152,15 +193,33 @@ out_delete:
        return err;
 }
 
+static const char *ld_sort_order = "--sort=mem,sym,dso,symbol_daddr,dso_daddr,"
+                                  "tlb,locked";
+static const char *st_sort_order = "--sort=local_weight,mem,sym,dso,"
+                                  "symbol_daddr,dso_daddr,snoop,tlb,locked";
+static const char *ld_sort_order_p = "--sort=mem,sym,dso,symbol_daddr,"
+                                    "symbol_paddr,dso_daddr,tlb,locked";
+static const char *st_sort_order_p = "--sort=local_weight,mem,sym,dso,"
+                                    
"symbol_daddr,symbol_paddr,dso_daddr,snoop,tlb,locked";
+
 static int report_events(int argc, const char **argv, struct perf_mem *mem)
 {
        const char **rep_argv;
+       const char *ld_sort, *st_sort;
        int ret, i = 0, j, rep_argc;
 
        if (mem->dump_raw)
                return report_raw_events(mem);
 
-       rep_argc = argc + 3;
+       if (mem->phys_addr) {
+               ld_sort = ld_sort_order_p;
+               st_sort = st_sort_order_p;
+       } else {
+               ld_sort = ld_sort_order;
+               st_sort = st_sort_order;
+       }
+
+       rep_argc = argc + 4;
        rep_argv = calloc(rep_argc + 1, sizeof(char *));
        if (!rep_argv)
                return -1;
@@ -174,8 +233,9 @@ static int report_events(int argc, const char **argv, 
struct perf_mem *mem)
         * the column
         */
        if (strcmp(mem_operation, MEM_OPERATION_LOAD))
-               rep_argv[i++] = strdup("--sort=mem,sym,dso,symbol_daddr,"
-                                      "dso_daddr,tlb,locked");
+               rep_argv[i++] = strdup(st_sort);
+       else
+               rep_argv[i++] = strdup(ld_sort);
 
        for (j = 1; j < argc; j++, i++)
                rep_argv[i] = argv[j];
@@ -207,6 +267,8 @@ int cmd_mem(int argc, const char **argv, const char *prefix 
__maybe_unused)
                    "dump raw samples in ASCII"),
        OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved,
                    "Only display entries resolved to a symbol"),
+       OPT_BOOLEAN(0, "phys-addr", &mem.phys_addr,
+                   "sample physical data addr"),
        OPT_STRING('i', "input", &input_name, "file",
                   "input file name"),
        OPT_STRING('C', "cpu", &mem.cpu_list, "cpu",
@@ -232,7 +294,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix 
__maybe_unused)
        }
 
        if (!strncmp(argv[0], "rec", 3))
-               return __cmd_record(argc, argv);
+               return __cmd_record(argc, argv, &mem);
        else if (!strncmp(argv[0], "rep", 3))
                return report_events(argc, argv, &mem);
        else
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ca98d34..6b2531f 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -894,7 +894,7 @@ repeat:
                 * branch-mode specific order
                 */
                if (sort_order == default_sort_order)
-                       sort_order = 
"local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
+                       sort_order = 
"local_weight,mem,sym,dso,symbol_daddr,symbol_paddr,dso_daddr,snoop,tlb,locked";
        }
 
        if (setup_sorting() < 0)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b11a6cf..136a851 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -148,10 +148,12 @@ void hists__calc_col_len(struct hists *hists, struct 
hist_entry *h)
                        hists__set_unres_dso_col_len(hists, 
HISTC_MEM_DADDR_DSO);
                }
        } else {
-               symlen = unresolved_col_width + 4 + 2;
+               symlen = unresolved_col_width + 2 + 4;
                hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
                hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
        }
+       symlen = unresolved_col_width + 2;
+       hists__new_col_len(hists, HISTC_MEM_PADDR_SYMBOL, symlen);
 
        hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
        hists__new_col_len(hists, HISTC_MEM_TLB, 22);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2d3790f..9add9ae 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,7 @@ enum hist_column {
        HISTC_LOCAL_WEIGHT,
        HISTC_GLOBAL_WEIGHT,
        HISTC_MEM_DADDR_SYMBOL,
+       HISTC_MEM_PADDR_SYMBOL,
        HISTC_MEM_DADDR_DSO,
        HISTC_MEM_LOCKED,
        HISTC_MEM_TLB,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b2ecad6..7823460 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1133,6 +1133,7 @@ struct mem_info *machine__resolve_mem(struct machine 
*machine,
        ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip);
        ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr);
        mi->data_src.val = sample->data_src;
+       mi->paddr = sample->paddr;
 
        return mi;
 }
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 313a5a7..1a0ea58 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -497,6 +497,39 @@ static int hist_entry__daddr_snprintf(struct hist_entry 
*self, char *bf,
 }
 
 static int64_t
+sort__paddr_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       uint64_t l = 0, r = 0;
+
+       if (left->mem_info)
+               l = left->mem_info->paddr;
+       if (right->mem_info)
+               r = right->mem_info->paddr;
+
+       return (int64_t)(r - l);
+}
+
+static int hist_entry__paddr_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width)
+{
+       uint64_t addr = 0;
+       size_t len = BITS_PER_LONG / 4;
+       int ret = 0;
+
+       if (!self->mem_info)
+               return 0;
+
+       addr = self->mem_info->paddr;
+
+       ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
+                              len, addr);
+       ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
+                              width - ret, "");
+       return ret;
+}
+
+
+static int64_t
 sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
 {
        struct map *map_l = NULL;
@@ -821,6 +854,14 @@ struct sort_entry sort_mem_daddr_sym = {
        .se_width_idx   = HISTC_MEM_DADDR_SYMBOL,
 };
 
+struct sort_entry sort_mem_paddr_sym = {
+       .se_header      = "Data Physical Addr",
+       .se_cmp         = sort__paddr_cmp,
+       .se_snprintf    = hist_entry__paddr_snprintf,
+       .se_width_idx   = HISTC_MEM_PADDR_SYMBOL,
+};
+
+
 struct sort_entry sort_mem_daddr_dso = {
        .se_header      = "Data Object",
        .se_cmp         = sort__dso_daddr_cmp,
@@ -894,6 +935,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
        DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
        DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
        DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
+       DIM(SORT_MEM_PADDR_SYMBOL, "symbol_paddr", sort_mem_paddr_sym),
        DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
        DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
        DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 45ac84c..4d4bdce 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -152,6 +152,7 @@ enum sort_type {
        SORT_LOCAL_WEIGHT = __SORT_MEMORY_MODE,
        SORT_GLOBAL_WEIGHT,
        SORT_MEM_DADDR_SYMBOL,
+       SORT_MEM_PADDR_SYMBOL,
        SORT_MEM_DADDR_DSO,
        SORT_MEM_LOCKED,
        SORT_MEM_TLB,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5f720dc..c2e933c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -159,6 +159,7 @@ struct branch_info {
 struct mem_info {
        struct addr_map_symbol iaddr;
        struct addr_map_symbol daddr;
+       u64                    paddr;
        union perf_mem_data_src data_src;
 };
 
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to