2

I'm currently using simpleperf, which is a ported version of perf for Android, in my Nexus 5. What I hope to do is to dynamically get native functions' execution sequence.

I guess there should be a way to dump a sample record once there is a branch event. So what I have to do is to execute simpleperf record -e branch-loads:u -p [pid].

Below I listed some relative events supported in my device. I tried branch-loads and branch-instructions for my purpose. But neither of them returned expected result. I believe this is due to branch includes functions as well as conditional jumps.

root@hammerhead:/data/local/tmp # ./simpleperf32 list                          
List of hw-cache events:
  ...
  branch-loads
  branch-load-misses
  branch-stores
  branch-store-misses
  node-loads
  node-load-misses
  node-stores
  node-store-misses
  node-prefetches
  node-prefetch-misses

List of hardware events:
  cpu-cycles
  instructions
  branch-instructions
  branch-misses
  bus-cycles
  stalled-cycles-frontend
  stalled-cycles-backend

So, how could I get function call events ONLY? Or if I'm on a wrong way, please point me the right one. Thanks.

colordancer
  • 162
  • 8
  • To get full "native functions' execution sequence" you should try tracing, not statistical profiling as does perf. – osgx Oct 08 '16 at 16:14

1 Answers1

2

perf list doesn't list actual hardware events, it is just a list of perf-predefined list, and it is not fully supported by any CPU. Some CPUs maps several events to perf's predefined, other map different event set.

You should check documentation of your CPU core (qualcomm krait 400) to find actual hardware performance monitoring events (counters) and use them as raw (encoding to perf stat -e rXXXX or to RAW in perf_attr is architecture specific too). Also you can try perf stat / perf stat -d to check which events are counted (supported) from some default lists.

Your nexus 5 is based on Krait 400 CPU core.

There were some problems reported in krait: How to get perf_event results for 2nd Nexus7 with Krait CPU and there was link to patch, defining standard events for krait:

http://www.serverphorums.com/read.php?12,850329

There are two sets of mapping from predefined perf to actual hw events. One with support of branch-instructions event and other without:

/*
+ * Krait HW events mapping
+ */
+static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};

According to selection code, this is feature of later versions of Krait CPU:

+static int krait_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ u32 id = read_cpuid_id() & 0xffffff00;
+
+ armv7pmu_init(cpu_pmu);
+ cpu_pmu->name = "ARMv7 Krait";
+ /* Some early versions of Krait don't support PC write events */
+ if (id == 0x511f0400 || id == 0x510f0600)
+ cpu_pmu->map_event = krait_map_event_no_branch;
+ else
+ cpu_pmu->map_event = krait_map_event;
+ cpu_pmu->num_events = armv7_read_num_pmnc_events();
+ cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+ return 0;
+}

As I can decode cpuid - Krait 400 and Krait 600 have no support of branch-instruction PMU event (PC write event).

Update: For your Nexus 5x if it use ARM Cortex A57 core, there is list of raw events, based on "Table 11-24 from the "Cortex A57 Technical Reference Manual""

https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h

Still no counter for all branches. There are BRANCH_MISPRED & BRANCH_PRED but I have no access to docs and don't know will they count all branches or not.

Community
  • 1
  • 1
osgx
  • 90,338
  • 53
  • 357
  • 513
  • not listed in libpfm4 too:https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_qcom_krait_events.h – osgx Oct 02 '16 at 09:34
  • Thanks. I gave up Nexus 5 due to Krait's bad support of ARM CoreSight. In stead, I tried Neuxs 5x which has Coretex A57 cpu. But same problem happened. Not sure whether I tested in the correct way. – colordancer Oct 04 '16 at 03:59
  • 1
    colordancer, A57 has no performance event for all branch count too: https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h But there are BRANCH_MISPRED and BRANCH_PRED events, you should check "Table 11-24 from the "Cortex A57 Technical Reference Manual"" and try to encode them as raw events for perf – osgx Oct 04 '16 at 22:48
  • I saw a event BRANCH_SPEC_EXEC_RET supported by A57. Does that mean function return event? As I said at the beginning, my request is to get all the functions executed. – colordancer Oct 08 '16 at 02:50
  • Where did you see it? In libpfm4/../events/arm_cortex_a57_events.h there is definition "Return branch speculatively executed" (what if it was executed without speculation, is it possible); and in "Cortex A57 Technical Reference Manual" there can be some real info. You can't get all executed functions with sampling profiling; you need some kind of tracing. – osgx Oct 08 '16 at 16:13