From 03c94fcf954d6bc5e23460e200d23a2c0fe5cd2e Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 17 Nov 2014 17:13:03 +0530 Subject: ARC: perf: make @arc_pmu static global Signed-off-by: Vineet Gupta --- arch/arc/kernel/perf_event.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/arc/kernel/perf_event.c') diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index ae1c485cbc68..64261c2711b1 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -25,6 +25,8 @@ struct arc_pmu { int ev_hw_idx[PERF_COUNT_ARC_HW_MAX]; }; +static struct arc_pmu *arc_pmu; + /* read counter #idx; note that counter# != event# on ARC! */ static uint64_t arc_pmu_read_counter(int idx) { @@ -47,7 +49,6 @@ static uint64_t arc_pmu_read_counter(int idx) static void arc_perf_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx) { - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); uint64_t prev_raw_count, new_raw_count; int64_t delta; @@ -95,7 +96,6 @@ static int arc_pmu_cache_event(u64 config) /* initializes hw_perf_event structure if event is supported */ static int arc_pmu_event_init(struct perf_event *event) { - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); struct hw_perf_event *hwc = &event->hw; int ret; @@ -183,8 +183,6 @@ static void arc_pmu_stop(struct perf_event *event, int flags) static void arc_pmu_del(struct perf_event *event, int flags) { - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); - arc_pmu_stop(event, PERF_EF_UPDATE); __clear_bit(event->hw.idx, arc_pmu->used_mask); @@ -194,7 +192,6 @@ static void arc_pmu_del(struct perf_event *event, int flags) /* allocate hardware counter and optionally start counting */ static int arc_pmu_add(struct perf_event *event, int flags) { - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx; -- cgit v1.2.3 From bde80c237e49983e2b26dfa9925325a070b71de7 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 15 Apr 2015 19:44:07 +0530 Subject: ARC: perf: Add some comments/debug stuff Signed-off-by: Vineet Gupta --- arch/arc/include/asm/perf_event.h | 53 ++++++++++++++++++--------------------- arch/arc/kernel/perf_event.c | 18 +++++++++---- 2 files changed, 37 insertions(+), 34 deletions(-) (limited to 'arch/arc/kernel/perf_event.c') diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h index cbf755e32a03..1c45667c1367 100644 --- a/arch/arc/include/asm/perf_event.h +++ b/arch/arc/include/asm/perf_event.h @@ -57,26 +57,7 @@ struct arc_reg_cc_build { #define PERF_COUNT_ARC_HW_MAX (PERF_COUNT_HW_MAX + 6) /* - * The "generalized" performance events seem to really be a copy - * of the available events on x86 processors; the mapping to ARC - * events is not always possible 1-to-1. Fortunately, there doesn't - * seem to be an exact definition for these events, so we can cheat - * a bit where necessary. - * - * In particular, the following PERF events may behave a bit differently - * compared to other architectures: - * - * PERF_COUNT_HW_CPU_CYCLES - * Cycles not in halted state - * - * PERF_COUNT_HW_REF_CPU_CYCLES - * Reference cycles not in halted state, same as PERF_COUNT_HW_CPU_CYCLES - * for now as we don't do Dynamic Voltage/Frequency Scaling (yet) - * - * PERF_COUNT_HW_BUS_CYCLES - * Unclear what this means, Intel uses 0x013c, which according to - * their datasheet means "unhalted reference cycles". It sounds similar - * to PERF_COUNT_HW_REF_CPU_CYCLES, and we use the same counter for it. + * Some ARC pct quirks: * * PERF_COUNT_HW_STALLED_CYCLES_BACKEND * PERF_COUNT_HW_STALLED_CYCLES_FRONTEND @@ -91,21 +72,35 @@ struct arc_reg_cc_build { * Note that I$ cache misses aren't counted by either of the two! */ +/* + * ARC PCT has hardware conditions with fixed "names" but variable "indexes" + * (based on a specific RTL build) + * Below is the static map between perf generic/arc specific event_id and + * h/w condition names. + * At the time of probe, we loop thru each index and find it's name to + * complete the mapping of perf event_id to h/w index as latter is needed + * to program the counter really + */ static const char * const arc_pmu_ev_hw_map[] = { + /* count cycles */ [PERF_COUNT_HW_CPU_CYCLES] = "crun", [PERF_COUNT_HW_REF_CPU_CYCLES] = "crun", [PERF_COUNT_HW_BUS_CYCLES] = "crun", - [PERF_COUNT_HW_INSTRUCTIONS] = "iall", - [PERF_COUNT_HW_BRANCH_MISSES] = "bpfail", - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = "bflush", [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = "bstall", - [PERF_COUNT_ARC_DCLM] = "dclm", - [PERF_COUNT_ARC_DCSM] = "dcsm", - [PERF_COUNT_ARC_ICM] = "icm", - [PERF_COUNT_ARC_BPOK] = "bpok", - [PERF_COUNT_ARC_EDTLB] = "edtlb", - [PERF_COUNT_ARC_EITLB] = "eitlb", + + /* counts condition */ + [PERF_COUNT_HW_INSTRUCTIONS] = "iall", + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", + [PERF_COUNT_ARC_BPOK] = "bpok", /* NP-NT, PT-T, PNT-NT */ + [PERF_COUNT_HW_BRANCH_MISSES] = "bpfail", /* NP-T, PT-NT, PNT-T */ + + [PERF_COUNT_ARC_DCLM] = "dclm", /* D-cache Load Miss */ + [PERF_COUNT_ARC_DCSM] = "dcsm", /* D-cache Store Miss */ + [PERF_COUNT_ARC_ICM] = "icm", /* I-cache Miss */ + [PERF_COUNT_ARC_EDTLB] = "edtlb", /* D-TLB Miss */ + [PERF_COUNT_ARC_EITLB] = "eitlb", /* I-TLB Miss */ }; #define C(_x) PERF_COUNT_HW_CACHE_##_x diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index 64261c2711b1..181baeed4495 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -90,6 +90,10 @@ static int arc_pmu_cache_event(u64 config) if (ret == CACHE_OP_UNSUPPORTED) return -ENOENT; + pr_debug("init cache event: type/op/result %d/%d/%d with h/w %d \'%s\'\n", + cache_type, cache_op, cache_result, ret, + arc_pmu_ev_hw_map[ret]); + return ret; } @@ -106,8 +110,9 @@ static int arc_pmu_event_init(struct perf_event *event) if (arc_pmu->ev_hw_idx[event->attr.config] < 0) return -ENOENT; hwc->config = arc_pmu->ev_hw_idx[event->attr.config]; - pr_debug("initializing event %d with cfg %d\n", - (int) event->attr.config, (int) hwc->config); + pr_debug("init event %d with h/w %d \'%s\'\n", + (int) event->attr.config, (int) hwc->config, + arc_pmu_ev_hw_map[event->attr.config]); return 0; case PERF_TYPE_HW_CACHE: ret = arc_pmu_cache_event(event->attr.config); @@ -260,19 +265,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev) arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c); cc_name.str[8] = 0; - for (i = 0; i < PERF_COUNT_HW_MAX; i++) + for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++) arc_pmu->ev_hw_idx[i] = -1; + /* loop thru all available h/w condition indexes */ for (j = 0; j < cc_bcr.c; j++) { write_aux_reg(ARC_REG_CC_INDEX, j); cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0); cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1); + + /* See if it has been mapped to a perf event_id */ for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) { if (arc_pmu_ev_hw_map[i] && !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) && strlen(arc_pmu_ev_hw_map[i])) { - pr_debug("mapping %d to idx %d with name %s\n", - i, j, cc_name.str); + pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n", + i, cc_name.str, j); arc_pmu->ev_hw_idx[i] = j; } } -- cgit v1.2.3 From 389e3160b9b0002f8e7c95e9c0af5da6da311892 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 12 Nov 2013 11:00:03 +0100 Subject: ARC: perf: Add kernel callchain support Signed-off-by: Mischa Jonker Signed-off-by: Vineet Gupta --- arch/arc/kernel/perf_event.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'arch/arc/kernel/perf_event.c') diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index 181baeed4495..a6ad1e09e4be 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -16,6 +16,7 @@ #include #include #include +#include struct arc_pmu { struct pmu pmu; @@ -25,6 +26,34 @@ struct arc_pmu { int ev_hw_idx[PERF_COUNT_ARC_HW_MAX]; }; +struct arc_callchain_trace { + int depth; + void *perf_stuff; +}; + +static int callchain_trace(unsigned int addr, void *data) +{ + struct arc_callchain_trace *ctrl = data; + struct perf_callchain_entry *entry = ctrl->perf_stuff; + perf_callchain_store(entry, addr); + + if (ctrl->depth++ < 3) + return 0; + + return -1; +} + +void +perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) +{ + struct arc_callchain_trace ctrl = { + .depth = 0, + .perf_stuff = entry, + }; + + arc_unwind_core(NULL, regs, callchain_trace, &ctrl); +} + static struct arc_pmu *arc_pmu; /* read counter #idx; note that counter# != event# on ARC! */ -- cgit v1.2.3 From 22f6b899125063c5dc955dd378c408b14d80b020 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 12 Jul 2013 15:55:54 +0200 Subject: ARC: perf: add user space attribution in callchains The actual user space unwinding is more involved, so simply capture the user space PC Signed-off-by: Vineet Gupta --- arch/arc/kernel/perf_event.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/arc/kernel/perf_event.c') diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index a6ad1e09e4be..109118a4245e 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -54,6 +54,16 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) arc_unwind_core(NULL, regs, callchain_trace, &ctrl); } +void +perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) +{ + /* + * User stack can't be unwound trivially with kernel dwarf unwinder + * So for now just record the user PC + */ + perf_callchain_store(entry, instruction_pointer(regs)); +} + static struct arc_pmu *arc_pmu; /* read counter #idx; note that counter# != event# on ARC! */ -- cgit v1.2.3 From 30fdd373f24cc50e250c71a6e2df89505e267804 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 15 Apr 2015 16:35:38 +0530 Subject: ARC: perf: Rename DT binding to not confuse with power mgmt Signed-off-by: Vineet Gupta --- Documentation/devicetree/bindings/arc/pct.txt | 20 ++++++++++++++++++++ Documentation/devicetree/bindings/arc/pmu.txt | 24 ------------------------ arch/arc/boot/dts/angel4.dts | 2 +- arch/arc/kernel/perf_event.c | 4 ++-- 4 files changed, 23 insertions(+), 27 deletions(-) create mode 100644 Documentation/devicetree/bindings/arc/pct.txt delete mode 100644 Documentation/devicetree/bindings/arc/pmu.txt (limited to 'arch/arc/kernel/perf_event.c') diff --git a/Documentation/devicetree/bindings/arc/pct.txt b/Documentation/devicetree/bindings/arc/pct.txt new file mode 100644 index 000000000000..7b9588444f20 --- /dev/null +++ b/Documentation/devicetree/bindings/arc/pct.txt @@ -0,0 +1,20 @@ +* ARC Performance Counters + +The ARC700 can be configured with a pipeline performance monitor for counting +CPU and cache events like cache misses and hits. Like conventional PCT there +are 100+ hardware conditions dynamically mapped to upto 32 counters + +Note that: + * The ARC 700 PCT does not support interrupts; although HW events may be + counted, the HW events themselves cannot serve as a trigger for a sample. + +Required properties: + +- compatible : should contain + "snps,arc700-pct" + +Example: + +pmu { + compatible = "snps,arc700-pct"; +}; diff --git a/Documentation/devicetree/bindings/arc/pmu.txt b/Documentation/devicetree/bindings/arc/pmu.txt deleted file mode 100644 index 49d517340de3..000000000000 --- a/Documentation/devicetree/bindings/arc/pmu.txt +++ /dev/null @@ -1,24 +0,0 @@ -* ARC Performance Monitor Unit - -The ARC 700 can be configured with a pipeline performance monitor for counting -CPU and cache events like cache misses and hits. - -Note that: - * ARC 700 refers to a family of ARC processor cores; - - There is only one type of PMU available for the whole family; - - The PMU may support different sets of events; supported events are probed - at boot time, as required by the reference manual. - - * The ARC 700 PMU does not support interrupts; although HW events may be - counted, the HW events themselves cannot serve as a trigger for a sample. - -Required properties: - -- compatible : should contain - "snps,arc700-pmu" - -Example: - -pmu { - compatible = "snps,arc700-pmu"; -}; diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts index 757e0c62c4f9..3b076fbd8366 100644 --- a/arch/arc/boot/dts/angel4.dts +++ b/arch/arc/boot/dts/angel4.dts @@ -64,7 +64,7 @@ }; arcpmu0: pmu { - compatible = "snps,arc700-pmu"; + compatible = "snps,arc700-pct"; }; }; }; diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index 109118a4245e..165e0b604167 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -346,7 +346,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id arc_pmu_match[] = { - { .compatible = "snps,arc700-pmu" }, + { .compatible = "snps,arc700-pct" }, {}, }; MODULE_DEVICE_TABLE(of, arc_pmu_match); @@ -354,7 +354,7 @@ MODULE_DEVICE_TABLE(of, arc_pmu_match); static struct platform_driver arc_pmu_driver = { .driver = { - .name = "arc700-pmu", + .name = "arc700-pct", .of_match_table = of_match_ptr(arc_pmu_match), }, .probe = arc_pmu_device_probe, -- cgit v1.2.3 From d8f6ad85cbb740b7e8ca5275b12838fab685540c Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 20 Apr 2015 16:49:30 +0530 Subject: ARC: perf: don't add code for impossible case Signed-off-by: Vineet Gupta --- arch/arc/kernel/perf_event.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/arc/kernel/perf_event.c') diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index 165e0b604167..fd2ec50102f2 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -288,10 +288,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev) BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS); READ_BCR(ARC_REG_CC_BUILD, cc_bcr); - if (!cc_bcr.v) { - pr_err("Performance counters exist, but no countable conditions?\n"); - return -ENODEV; - } + BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */ arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL); if (!arc_pmu) -- cgit v1.2.3