Message ID | 20241106085441.3945502-1-xu.yang_2@nxp.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | perf jevents: fix breakage when do perf stat on system metric | expand |
On Wed, Nov 6, 2024 at 12:55 AM Xu Yang <xu.yang_2@nxp.com> wrote: > > When do perf stat on sys metric, perf tool output nothing now: > $ perf stat -a -M imx95_ddr_read.all -I 1000 > $ > > This command runs on an arm64 machine and the Soc has one DDR hw pmu > except one armv8_cortex_a55 pmu. Their maps show as follows: > > const struct pmu_events_map pmu_events_map[] = { > { > .arch = "arm64", > .cpuid = "0x00000000410fd050", > .event_table = { > .pmus = pmu_events__arm_cortex_a55, > .num_pmus = ARRAY_SIZE(pmu_events__arm_cortex_a55) > }, > .metric_table = { > .pmus = NULL, > .num_pmus = 0 > } > }, > > static const struct pmu_sys_events pmu_sys_event_tables[] = { > { > .event_table = { > .pmus = pmu_events__freescale_imx95_sys, > .num_pmus = ARRAY_SIZE(pmu_events__freescale_imx95_sys) > }, > .metric_table = { > .pmus = pmu_metrics__freescale_imx95_sys, > .num_pmus = ARRAY_SIZE(pmu_metrics__freescale_imx95_sys) > }, > .name = "pmu_events__freescale_imx95_sys", > }, > > Currently, pmu_metrics_table__find() will return NULL when only do perf > stat on sys metric. Then parse_groups() will never be called to parse > sys metric_name, finally perf tool will exit directly. This should be a > common problem. To fix the issue, this will keep the logic before commit > f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > to return a empty metric table rather than a NULL pointer. This should > be fine since the removed part just check if the table match provided > metric_name. Without these code, the code in parse_groups() will also > check the validity of metrci_name too. So we carry this code for ARM: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/arch/arm64/util/pmu.c?h=perf-tools-next#n21 On x86 and other architectures the PMU is always passed as NULL (the effect of this change): https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n843 The blame shows me as the author, but that's because I factored event and metric tables to be separate things. When I did that I brought over ARM's event table logic to the metric table. Why do we pass a PMU to this code anyway? So on x86 the cpuid will give a different string for heterogeneous/hybrid/BIG.little parts. On ARM you get a different CPUID depending on which logical CPU you ask the question of. The CPUs associated with a PMU are used to look up the CPUID string. This whole thing is spaghetti code (fwiw, I dislike the whole arch directory plus weak symbols thing that is a by design breakage of at least cross platform work - hopefully the maintainers will review [1] so we can delete a sizeable chunk of it) and the ARM situation looks sub-optimal. We really need to scan a plurality of metric tables for the heterogeneous parts on ARM. We're passing a PMU rather than just a CPU, I think passing a CPU would be more intention revealing. Then there's the pleasure of system metrics, which are only loosely in my mental model of things as John Garry did the heavy lifting for these. So the problems I see: 1) ARM needs multiple metric tables to be parsed in the metric group logic as the invariant of 1 CPUID 1 table doesn't hold on ARM. 2) The lack of a metric table causes an early exit from the metric parsing code: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1700 However, the system metrics pattern conceptually match PMU names and aren't tied to CPUIDs. The iteration logic still uses the metric table though: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1283 3) Crufty spaghetti from the use of arch/weak that means we aren't testing the same code paths leading to divergence and rot. I'll try to pull something together. But for the sake of expediently addressing your issue: Acked-by: Ian Rogers <irogers@google.com> Thanks, Ian [1] https://lore.kernel.org/lkml/20241017002520.59124-1-irogers@google.com/ > Fixes: f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > Cc: stable@vger.kernel.org > Signed-off-by: Xu Yang <xu.yang_2@nxp.com> > --- > tools/perf/pmu-events/empty-pmu-events.c | 12 +----------- > tools/perf/pmu-events/jevents.py | 12 +----------- > 2 files changed, 2 insertions(+), 22 deletions(-) > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c > index 2b7516946ded..b8719dab264d 100644 > --- a/tools/perf/pmu-events/empty-pmu-events.c > +++ b/tools/perf/pmu-events/empty-pmu-events.c > @@ -585,17 +585,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > if (!map) > return NULL; > > - if (!pmu) > - return &map->metric_table; > - > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > - > - if (pmu__name_match(pmu, pmu_name)) > - return &map->metric_table; > - } > - return NULL; > + return &map->metric_table; > } > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py > index 6e71b09dbc2a..70f4fd5395fb 100755 > --- a/tools/perf/pmu-events/jevents.py > +++ b/tools/perf/pmu-events/jevents.py > @@ -1101,17 +1101,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > if (!map) > return NULL; > > - if (!pmu) > - return &map->metric_table; > - > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > - > - if (pmu__name_match(pmu, pmu_name)) > - return &map->metric_table; > - } > - return NULL; > + return &map->metric_table; > } > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > -- > 2.34.1 >
On Wed, Nov 06, 2024 at 10:06:24AM -0800, Ian Rogers wrote: > On Wed, Nov 6, 2024 at 12:55 AM Xu Yang <xu.yang_2@nxp.com> wrote: > > > > When do perf stat on sys metric, perf tool output nothing now: > > $ perf stat -a -M imx95_ddr_read.all -I 1000 > > $ > > > > This command runs on an arm64 machine and the Soc has one DDR hw pmu > > except one armv8_cortex_a55 pmu. Their maps show as follows: > > > > const struct pmu_events_map pmu_events_map[] = { > > { > > .arch = "arm64", > > .cpuid = "0x00000000410fd050", > > .event_table = { > > .pmus = pmu_events__arm_cortex_a55, > > .num_pmus = ARRAY_SIZE(pmu_events__arm_cortex_a55) > > }, > > .metric_table = { > > .pmus = NULL, > > .num_pmus = 0 > > } > > }, > > > > static const struct pmu_sys_events pmu_sys_event_tables[] = { > > { > > .event_table = { > > .pmus = pmu_events__freescale_imx95_sys, > > .num_pmus = ARRAY_SIZE(pmu_events__freescale_imx95_sys) > > }, > > .metric_table = { > > .pmus = pmu_metrics__freescale_imx95_sys, > > .num_pmus = ARRAY_SIZE(pmu_metrics__freescale_imx95_sys) > > }, > > .name = "pmu_events__freescale_imx95_sys", > > }, > > > > Currently, pmu_metrics_table__find() will return NULL when only do perf > > stat on sys metric. Then parse_groups() will never be called to parse > > sys metric_name, finally perf tool will exit directly. This should be a > > common problem. To fix the issue, this will keep the logic before commit > > f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > > to return a empty metric table rather than a NULL pointer. This should > > be fine since the removed part just check if the table match provided > > metric_name. Without these code, the code in parse_groups() will also > > check the validity of metrci_name too. > > So we carry this code for ARM: > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/arch/arm64/util/pmu.c?h=perf-tools-next#n21 > > On x86 and other architectures the PMU is always passed as NULL (the > effect of this change): > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n843 > > The blame shows me as the author, but that's because I factored event > and metric tables to be separate things. When I did that I brought > over ARM's event table logic to the metric table. > > Why do we pass a PMU to this code anyway? > So on x86 the cpuid will give a different string for > heterogeneous/hybrid/BIG.little parts. On ARM you get a different > CPUID depending on which logical CPU you ask the question of. The CPUs > associated with a PMU are used to look up the CPUID string. > > This whole thing is spaghetti code (fwiw, I dislike the whole arch > directory plus weak symbols thing that is a by design breakage of at > least cross platform work - hopefully the maintainers will review [1] > so we can delete a sizeable chunk of it) and the ARM situation looks Yes, the logic seems like a little mess when parsing metrics because some system metrics don't bind to any core pmu. But I'm not familiar with the whole code, so I unable to make big changes on perf tool. > sub-optimal. We really need to scan a plurality of metric tables for > the heterogeneous parts on ARM. We're passing a PMU rather than just a > CPU, I think passing a CPU would be more intention revealing. > > Then there's the pleasure of system metrics, which are only loosely in > my mental model of things as John Garry did the heavy lifting for > these. > > So the problems I see: > 1) ARM needs multiple metric tables to be parsed in the metric group > logic as the invariant of 1 CPUID 1 table doesn't hold on ARM. > 2) The lack of a metric table causes an early exit from the metric parsing code: > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1700 > However, the system metrics pattern conceptually match PMU names and > aren't tied to CPUIDs. The iteration logic still uses the metric table > though: > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1283 > 3) Crufty spaghetti from the use of arch/weak that means we aren't > testing the same code paths leading to divergence and rot. > > I'll try to pull something together. But for the sake of expediently > addressing your issue: > Acked-by: Ian Rogers <irogers@google.com> Okay, Thanks for your input! Thanks, Xu Yang > > Thanks, > Ian > > > [1] https://lore.kernel.org/lkml/20241017002520.59124-1-irogers@google.com/ > > > > > Fixes: f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > > Cc: stable@vger.kernel.org > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com> > > --- > > tools/perf/pmu-events/empty-pmu-events.c | 12 +----------- > > tools/perf/pmu-events/jevents.py | 12 +----------- > > 2 files changed, 2 insertions(+), 22 deletions(-) > > > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c > > index 2b7516946ded..b8719dab264d 100644 > > --- a/tools/perf/pmu-events/empty-pmu-events.c > > +++ b/tools/perf/pmu-events/empty-pmu-events.c > > @@ -585,17 +585,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > > if (!map) > > return NULL; > > > > - if (!pmu) > > - return &map->metric_table; > > - > > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > > - > > - if (pmu__name_match(pmu, pmu_name)) > > - return &map->metric_table; > > - } > > - return NULL; > > + return &map->metric_table; > > } > > > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py > > index 6e71b09dbc2a..70f4fd5395fb 100755 > > --- a/tools/perf/pmu-events/jevents.py > > +++ b/tools/perf/pmu-events/jevents.py > > @@ -1101,17 +1101,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > > if (!map) > > return NULL; > > > > - if (!pmu) > > - return &map->metric_table; > > - > > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > > - > > - if (pmu__name_match(pmu, pmu_name)) > > - return &map->metric_table; > > - } > > - return NULL; > > + return &map->metric_table; > > } > > > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > > -- > > 2.34.1 > >
On Wed, Nov 6, 2024 at 7:41 PM Xu Yang <xu.yang_2@nxp.com> wrote: > > On Wed, Nov 06, 2024 at 10:06:24AM -0800, Ian Rogers wrote: > > On Wed, Nov 6, 2024 at 12:55 AM Xu Yang <xu.yang_2@nxp.com> wrote: > > > > > > When do perf stat on sys metric, perf tool output nothing now: > > > $ perf stat -a -M imx95_ddr_read.all -I 1000 > > > $ > > > > > > This command runs on an arm64 machine and the Soc has one DDR hw pmu > > > except one armv8_cortex_a55 pmu. Their maps show as follows: > > > > > > const struct pmu_events_map pmu_events_map[] = { > > > { > > > .arch = "arm64", > > > .cpuid = "0x00000000410fd050", > > > .event_table = { > > > .pmus = pmu_events__arm_cortex_a55, > > > .num_pmus = ARRAY_SIZE(pmu_events__arm_cortex_a55) > > > }, > > > .metric_table = { > > > .pmus = NULL, > > > .num_pmus = 0 > > > } > > > }, > > > > > > static const struct pmu_sys_events pmu_sys_event_tables[] = { > > > { > > > .event_table = { > > > .pmus = pmu_events__freescale_imx95_sys, > > > .num_pmus = ARRAY_SIZE(pmu_events__freescale_imx95_sys) > > > }, > > > .metric_table = { > > > .pmus = pmu_metrics__freescale_imx95_sys, > > > .num_pmus = ARRAY_SIZE(pmu_metrics__freescale_imx95_sys) > > > }, > > > .name = "pmu_events__freescale_imx95_sys", > > > }, > > > > > > Currently, pmu_metrics_table__find() will return NULL when only do perf > > > stat on sys metric. Then parse_groups() will never be called to parse > > > sys metric_name, finally perf tool will exit directly. This should be a > > > common problem. To fix the issue, this will keep the logic before commit > > > f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > > > to return a empty metric table rather than a NULL pointer. This should > > > be fine since the removed part just check if the table match provided > > > metric_name. Without these code, the code in parse_groups() will also > > > check the validity of metrci_name too. > > > > So we carry this code for ARM: > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/arch/arm64/util/pmu.c?h=perf-tools-next#n21 > > > > On x86 and other architectures the PMU is always passed as NULL (the > > effect of this change): > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n843 > > > > The blame shows me as the author, but that's because I factored event > > and metric tables to be separate things. When I did that I brought > > over ARM's event table logic to the metric table. > > > > Why do we pass a PMU to this code anyway? > > So on x86 the cpuid will give a different string for > > heterogeneous/hybrid/BIG.little parts. On ARM you get a different > > CPUID depending on which logical CPU you ask the question of. The CPUs > > associated with a PMU are used to look up the CPUID string. > > > > This whole thing is spaghetti code (fwiw, I dislike the whole arch > > directory plus weak symbols thing that is a by design breakage of at > > least cross platform work - hopefully the maintainers will review [1] > > so we can delete a sizeable chunk of it) and the ARM situation looks > > Yes, the logic seems like a little mess when parsing metrics because some > system metrics don't bind to any core pmu. But I'm not familiar with the > whole code, so I unable to make big changes on perf tool. > > > sub-optimal. We really need to scan a plurality of metric tables for > > the heterogeneous parts on ARM. We're passing a PMU rather than just a > > CPU, I think passing a CPU would be more intention revealing. > > > > Then there's the pleasure of system metrics, which are only loosely in > > my mental model of things as John Garry did the heavy lifting for > > these. > > > > So the problems I see: > > 1) ARM needs multiple metric tables to be parsed in the metric group > > logic as the invariant of 1 CPUID 1 table doesn't hold on ARM. > > 2) The lack of a metric table causes an early exit from the metric parsing code: > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1700 > > However, the system metrics pattern conceptually match PMU names and > > aren't tied to CPUIDs. The iteration logic still uses the metric table > > though: > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/metricgroup.c?h=perf-tools-next#n1283 > > 3) Crufty spaghetti from the use of arch/weak that means we aren't > > testing the same code paths leading to divergence and rot. > > > > I'll try to pull something together. But for the sake of expediently > > addressing your issue: > > Acked-by: Ian Rogers <irogers@google.com> > > Okay, Thanks for your input! I sent: https://lore.kernel.org/linux-perf-users/20241107071600.9082-1-irogers@google.com/ but didn't get to my point about ignore the no table case and also the >1 table case on heterogeneous systems. I didn't try to reproduce your situation, if you could test the patches it would be appreciated. Thanks, Ian > Thanks, > Xu Yang > > > > > Thanks, > > Ian > > > > > > [1] https://lore.kernel.org/lkml/20241017002520.59124-1-irogers@google.com/ > > > > > > > > > Fixes: f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") > > > Cc: stable@vger.kernel.org > > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com> > > > --- > > > tools/perf/pmu-events/empty-pmu-events.c | 12 +----------- > > > tools/perf/pmu-events/jevents.py | 12 +----------- > > > 2 files changed, 2 insertions(+), 22 deletions(-) > > > > > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c > > > index 2b7516946ded..b8719dab264d 100644 > > > --- a/tools/perf/pmu-events/empty-pmu-events.c > > > +++ b/tools/perf/pmu-events/empty-pmu-events.c > > > @@ -585,17 +585,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > > > if (!map) > > > return NULL; > > > > > > - if (!pmu) > > > - return &map->metric_table; > > > - > > > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > > > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > > > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > > > - > > > - if (pmu__name_match(pmu, pmu_name)) > > > - return &map->metric_table; > > > - } > > > - return NULL; > > > + return &map->metric_table; > > > } > > > > > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py > > > index 6e71b09dbc2a..70f4fd5395fb 100755 > > > --- a/tools/perf/pmu-events/jevents.py > > > +++ b/tools/perf/pmu-events/jevents.py > > > @@ -1101,17 +1101,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm > > > if (!map) > > > return NULL; > > > > > > - if (!pmu) > > > - return &map->metric_table; > > > - > > > - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { > > > - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; > > > - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; > > > - > > > - if (pmu__name_match(pmu, pmu_name)) > > > - return &map->metric_table; > > > - } > > > - return NULL; > > > + return &map->metric_table; > > > } > > > > > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) > > > -- > > > 2.34.1 > > >
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 2b7516946ded..b8719dab264d 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -585,17 +585,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm if (!map) return NULL; - if (!pmu) - return &map->metric_table; - - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - - if (pmu__name_match(pmu, pmu_name)) - return &map->metric_table; - } - return NULL; + return &map->metric_table; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 6e71b09dbc2a..70f4fd5395fb 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -1101,17 +1101,7 @@ const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pm if (!map) return NULL; - if (!pmu) - return &map->metric_table; - - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - - if (pmu__name_match(pmu, pmu_name)) - return &map->metric_table; - } - return NULL; + return &map->metric_table; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
When do perf stat on sys metric, perf tool output nothing now: $ perf stat -a -M imx95_ddr_read.all -I 1000 $ This command runs on an arm64 machine and the Soc has one DDR hw pmu except one armv8_cortex_a55 pmu. Their maps show as follows: const struct pmu_events_map pmu_events_map[] = { { .arch = "arm64", .cpuid = "0x00000000410fd050", .event_table = { .pmus = pmu_events__arm_cortex_a55, .num_pmus = ARRAY_SIZE(pmu_events__arm_cortex_a55) }, .metric_table = { .pmus = NULL, .num_pmus = 0 } }, static const struct pmu_sys_events pmu_sys_event_tables[] = { { .event_table = { .pmus = pmu_events__freescale_imx95_sys, .num_pmus = ARRAY_SIZE(pmu_events__freescale_imx95_sys) }, .metric_table = { .pmus = pmu_metrics__freescale_imx95_sys, .num_pmus = ARRAY_SIZE(pmu_metrics__freescale_imx95_sys) }, .name = "pmu_events__freescale_imx95_sys", }, Currently, pmu_metrics_table__find() will return NULL when only do perf stat on sys metric. Then parse_groups() will never be called to parse sys metric_name, finally perf tool will exit directly. This should be a common problem. To fix the issue, this will keep the logic before commit f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") to return a empty metric table rather than a NULL pointer. This should be fine since the removed part just check if the table match provided metric_name. Without these code, the code in parse_groups() will also check the validity of metrci_name too. Fixes: f20c15d13f01 ("perf pmu-events: Remember the perf_events_map for a PMU") Cc: stable@vger.kernel.org Signed-off-by: Xu Yang <xu.yang_2@nxp.com> --- tools/perf/pmu-events/empty-pmu-events.c | 12 +----------- tools/perf/pmu-events/jevents.py | 12 +----------- 2 files changed, 2 insertions(+), 22 deletions(-)