• Thomas Richter's avatar
    perf jevent: fix core dump on software events on s390 · e47749f1
    Thomas Richter authored
    Running commands such as
     # ./perf stat -e cs -- true
     Segmentation fault (core dumped)
     # ./perf stat -e cpu-clock-- true
     Segmentation fault (core dumped)
     #
    
    dump core. This should not happen as these events are defined
    even when no hardware PMU is available.
    Debugging this reveals this call chain:
    
      perf_pmus__find_by_type(type=1)
      +--> pmu_read_sysfs(core_only=false)
           +--> perf_pmu__find2(dirfd=3, name=0x152a113 "software")
                +--> perf_pmu__lookup(pmus=0x14f0568 <other_pmus>, dirfd=3,
                                      lookup_name=0x152a113 "software")
                     +--> perf_pmu__find_events_table (pmu=0x1532130)
    
    Now the pmu is "software" and it tries to find a proper table
    generated by the pmu-event generation process for s390:
    
     # cd pmu-events/
     # ./jevents.py  s390 all /root/linux/tools/perf/pmu-events/arch |\
            grep -E '^const struct pmu_table_entry'
     const struct pmu_table_entry pmu_events__cf_z10[] = {
     const struct pmu_table_entry pmu_events__cf_z13[] = {
     const struct pmu_table_entry pmu_metrics__cf_z13[] = {
     const struct pmu_table_entry pmu_events__cf_z14[] = {
     const struct pmu_table_entry pmu_metrics__cf_z14[] = {
     const struct pmu_table_entry pmu_events__cf_z15[] = {
     const struct pmu_table_entry pmu_metrics__cf_z15[] = {
     const struct pmu_table_entry pmu_events__cf_z16[] = {
     const struct pmu_table_entry pmu_metrics__cf_z16[] = {
     const struct pmu_table_entry pmu_events__cf_z196[] = {
     const struct pmu_table_entry pmu_events__cf_zec12[] = {
     const struct pmu_table_entry pmu_metrics__cf_zec12[] = {
     const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
     const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
     const struct pmu_table_entry pmu_events__test_soc_sys[] = {
     #
    
    However event "software" is not listed, as can be seen in the
    generated const struct pmu_events_map pmu_events_map[].
    So in function perf_pmu__find_events_table(), the variable
    table is initialized to NULL, but never set to a proper
    value. The function scans all generated &pmu_events_map[]
    tables, but no table matches, because the tables are
    s390 CPU Measurement unit specific:
    
      i = 0;
      for (;;) {
          const struct pmu_events_map *map = &pmu_events_map[i++];
          if (!map->arch)
               break;
    
          --> the maps are there because the build generated them
    
               if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
                    table = &map->event_table;
                    break;
               }
          --> Since no matching CPU string the table var remains 0x0
          }
          free(cpuid);
          if (!pmu)
               return table;
    
          --> The pmu is "software" so it exists and no return
    
          --> and here perf dies because table is 0x0
          for (i = 0; i < table->num_pmus; i++) {
    	      ...
          }
          return NULL;
    
    Fix this and do not access the table variable. Instead return 0x0
    which is the same return code when the for-loop was not successful.
    
    Output after:
     # ./perf stat -e cs -- true
    
     Performance counter stats for 'true':
    
                     0      cs
    
           0.000853105 seconds time elapsed
    
           0.000061000 seconds user
           0.000827000 seconds sys
    
     # ./perf stat -e cpu-clock -- true
    
     Performance counter stats for 'true':
    
                  0.25 msec cpu-clock #    0.341 CPUs utilized
    
           0.000728383 seconds time elapsed
    
           0.000055000 seconds user
           0.000706000 seconds sys
    
     # ./perf stat -e cycles -- true
    
     Performance counter stats for 'true':
    
       <not supported>      cycles
    
           0.000767298 seconds time elapsed
    
           0.000055000 seconds user
           0.000739000 seconds sys
    
     #
    
    Fixes: 7c52f10c ("perf pmu: Cache JSON events table")
    Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
    Reviewed-by: default avatarIan Rogers <irogers@google.com>
    Cc: dengler@linux.ibm.com
    Cc: gor@linux.ibm.com
    Cc: hca@linux.ibm.com
    Cc: sumanthk@linux.ibm.com
    Cc: svens@linux.ibm.com
    Link: https://lore.kernel.org/r/20230913125157.2790375-1-tmricht@linux.ibm.comSigned-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
    e47749f1
jevents.py 41 KB