From a7fbfa09c795eb32e60489cb2c4a88f38fe9bc86 Mon Sep 17 00:00:00 2001 From: hongrongxuan Date: Fri, 10 Nov 2023 14:47:39 +0800 Subject: [PATCH] Perf tool: perf tool add Hip09 json support --- kernel.spec | 207 ++++- ...ntroduce-perf_evlist__print_counters.patch | 88 ++ ...TAT_RECORD-out-of-perf_evlist__print.patch | 62 ++ ...ruct-perf_stat_config-argument-to-pe.patch | 96 ++ ...truct-perf_stat_config-argument-to-l.patch | 471 ++++++++++ ...-struct-perf_stat_config-argument-to.patch | 772 ++++++++++++++++ ...etric_events-to-struct-perf_stat_con.patch | 117 +++ ...y-metric-expressions-for-details-opt.patch | 145 +++ ...egacy-events-symbol-separator-parsin.patch | 112 +++ ...stat-Revert-checks-for-duration_time.patch | 105 +++ ...ment-duration_time-as-a-proper-event.patch | 343 ++++++++ ...rt-printing-evsel-name-for-duration_.patch | 59 ++ .../0129-perf-list-Output-tool-events.patch | 148 ++++ ...able-non-thread-safe-internal-hashma.patch | 476 ++++++++++ ...-perf-stat-Fix-metrics-with-no-merge.patch | 82 ++ ...-perf-jevents-Remove-unused-variable.patch | 54 ++ ...-nonlocal-include-statements-in-pmu-.patch | 60 ++ ...erf-list-Avoid-extra-for-raw-metrics.patch | 43 + ...c-Don-t-include-duration_time-in-gro.patch | 76 ++ ...-Add-missing-list_del_init-when-flus.patch | 48 + ...-Remove-needless-includes-from-metri.patch | 89 ++ ...-convert_scale-from-static-to-global.patch | 86 ++ ...-metricgroup-Scale-the-metric-result.patch | 186 ++++ ...-Support-multiple-events-for-metricg.patch | 316 +++++++ ...port-more-complex-PMU-event-aliasing.patch | 124 +++ ...-support-for-Hisi-hip08-DDRC-PMU-ali.patch | 153 ++++ ...-support-for-Hisi-hip08-HHA-PMU-alia.patch | 117 +++ ...-support-for-Hisi-hip08-L3C-PMU-alia.patch | 103 +++ ...ts-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch | 52 ++ ...ts-arm64-Add-some-missing-events-for.patch | 60 ++ ...ts-arm64-Add-some-missing-events-for.patch | 102 +++ ...ts-arm64-Add-some-missing-events-for.patch | 85 ++ ...ee-memory-access-memory-leaks-in-met.patch | 124 +++ ...ools-Move-ALLOC_LIST-into-a-function.patch | 236 +++++ ...st-Hide-deprecated-events-by-default.patch | 393 +++++++++ ...-Fix-printing-event-names-of-metric-.patch | 151 ++++ ...lement-bitmap_equal-operation-at-bit.patch | 118 +++ ...-Fix-printing-event-names-of-metric-.patch | 212 +++++ ...-events-Fix-an-old-style-declaration.patch | 47 + ...pf-fix-missing-__WORDSIZE-definition.patch | 54 ++ ...libbpf-hashmap-Remove-unused-include.patch | 44 + ...f-Define-__WORDSIZE-if-not-available.patch | 54 ++ ...bbpf-hashmap-on-I-LP32-architectures.patch | 60 ++ ...-Fix-undefined-behavior-in-hash_bits.patch | 75 ++ ...ools-Grab-a-copy-of-libbpf-s-hashmap.patch | 530 +++++++++++ ...f-tools-Sync-hashmap.h-with-libbpf-s.patch | 71 ++ ...ls-Update-copy-of-libbpf-s-hashmap.c.patch | 81 ++ ...rf-jevents-Support-metric-constraint.patch | 163 ++++ ...-Factor-out-metricgroup__add_metric_.patch | 125 +++ ...tor-out-sysctl__nmi_watchdog_enabled.patch | 112 +++ ...etricgroup-Support-metric-constraint.patch | 138 +++ ...ts-intel-Add-NO_NMI_WATCHDOG-metric-.patch | 187 ++++ .../0169-perf-expr-Add-expr.c-object.patch | 108 +++ ...70-perf-expr-Move-expr-lexer-to-flex.patch | 562 ++++++++++++ ...se-EXPR_MAX_OTHER-to-support-metrics.patch | 56 ++ ...hten-expr__parse-expr__find_other-in.patch | 132 +++ ...r-Make-expr__parse-return-1-on-error.patch | 70 ++ ...xpr-Fix-memory-leaks-in-metric-bison.patch | 60 ++ ...175-perf-expr-Fix-copy-paste-mistake.patch | 52 ++ ...pr_-prefix-for-parse_ctx-and-parse_i.patch | 199 +++++ ...erf-expr-Add-expr_scanner_ctx-object.patch | 119 +++ ...-Split-the-metricgroup__add_metric-f.patch | 133 +++ ...s-Enhance-JSON-metric-infrastructure.patch | 450 ++++++++++ ...Added-test-for-runtime-param-in-metr.patch | 69 ++ ...81-perf-jevents-Add-some-test-events.patch | 122 +++ ...f-jevents-Support-test-events-folder.patch | 169 ++++ ...erf-pmu-Refactor-pmu_add_cpu_aliases.patch | 114 +++ .../0184-perf-test-Add-pmu-events-test.patch | 343 ++++++++ patches/0185-perf-pmu-Add-is_pmu_core.patch | 67 ++ ...u-Make-pmu_uncore_alias_match-public.patch | 65 ++ ...87-perf-test-Test-pmu-events-aliases.patch | 313 +++++++ ...for-unlimited-escaped-characters-in-.patch | 61 ++ ...perf-expr-Allow-to-be-an-other-token.patch | 58 ++ .../0190-perf-expr-Increase-max-other.patch | 59 ++ ...1-perf-expr-Parse-numbers-as-doubles.patch | 100 +++ ...est-Improve-pmu-event-metric-testing.patch | 311 +++++++ ...e-a-subtest-callback-to-ask-for-the-.patch | 80 ++ ...-Migrate-expr-ids-table-to-a-hashmap.patch | 825 ++++++++++++++++++ ...-Make-evlist_used-variable-a-bitmap-.patch | 110 +++ ...roup-Always-place-duration_time-last.patch | 93 ++ ...group-Use-early-return-in-add_metric.patch | 110 +++ ...icgroup-Delay-events-string-creation.patch | 144 +++ ...tricgroup-Order-event-groups-by-size.patch | 80 ++ ...oup-Remove-duped-metric-group-events.patch | 254 ++++++ ...up-Add-options-to-not-group-or-merge.patch | 365 ++++++++ ...group-Remove-unnecessary-from-events.patch | 70 ++ ...support-to-specify-rXXX-event-with-p.patch | 190 ++++ ...erf-tools-Allow-r0x-HEX-event-syntax.patch | 86 ++ ...at-Do-not-pass-avg-to-generic_metric.patch | 78 ++ ...truct-parse_events_state-pointer-to-.patch | 136 +++ ...ools-Fix-term-parsing-for-raw-syntax.patch | 217 +++++ ...0208-perf-tools-Add-fake-pmu-support.patch | 188 ++++ ...tests-Factor-check_parse_id-function.patch | 99 +++ ...de-a-way-to-pass-a-fake_pmu-to-parse.patch | 110 +++ ...erf_pmu__fake-object-to-use-with-__p.patch | 63 ++ ...ests-Add-another-metric-parsing-test.patch | 252 ++++++ ...rse-Factor-out-parse_groups-function.patch | 78 ++ ...Add-fake_pmu-to-parse_group-function.patch | 74 ++ ...ols-Add-map-to-parse_groups-function.patch | 116 +++ ...etricgroup__parse_groups_test-functi.patch | 89 ++ ...s-Factor-out-prepare_metric-function.patch | 123 +++ ...f-tools-Release-metric_events-rblist.patch | 95 ++ ...ols-Add-test_generic_metric-function.patch | 76 ++ ...rnel-supplied-event-aliases-for-arm6.patch | 66 ++ ...-CPU-core-PMU-HW-event-list-ordering.patch | 194 ++++ ...Rename-expr__add_id-to-expr__add_val.patch | 138 +++ ...struct-expr_id_data-to-keep-expr-val.patch | 146 ++++ ...memory-leak-in-expr__add_id-function.patch | 53 ++ ...erf-metric-Add-expr__add_id-function.patch | 115 +++ ...ge-expr__get_id-to-return-struct-exp.patch | 105 +++ ...erf-metric-Add-expr__del_id-function.patch | 93 ++ ...-Add-macros-for-iterating-map-events.patch | 148 ++++ ...-perf-metric-Add-add_metric-function.patch | 121 +++ ...me-__metricgroup__add_metric-to-__ad.patch | 82 ++ ...ect-referenced-metrics-in-struct-met.patch | 309 +++++++ ...ect-referenced-metrics-in-struct-met.patch | 128 +++ ...-Add-referenced-metrics-to-hash-data.patch | 245 ++++++ ...rf-metric-Compute-referenced-metrics.patch | 140 +++ ...tric-Add-events-for-the-current-list.patch | 87 ++ ...Add-parse-metric-test-for-ipc-metric.patch | 255 ++++++ ...arse-metric-test-for-frontend-metric.patch | 112 +++ ...cache_miss_cycles-to-metric-parse-te.patch | 99 +++ ...c-Add-DCache_L2-to-metric-parse-test.patch | 139 +++ ...recursion-check-when-processing-nest.patch | 442 ++++++++++ ...-compute_single-function-more-precis.patch | 91 ++ ...42-perf-metric-Add-metric-group-test.patch | 147 ++++ ...etric-Rename-struct-egroup-to-metric.patch | 448 ++++++++++ ...ric-Rename-group_list-to-metric_list.patch | 207 +++++ ...e-json_events-static-and-ditch-jeven.patch | 93 ++ ...dd-new-structure-to-pass-json-fields.patch | 402 +++++++++ ...-support-for-parsing-perchip-percore.patch | 154 ++++ ...-Pass-pmu_event-structure-as-a-param.patch | 113 +++ ...ot-print-Metric-Groups-unnecessarily.patch | 74 ++ ...perf-metricgroup-Fix-typo-in-comment.patch | 51 ++ ...liases-for-PMU-event-map-aliases-tes.patch | 103 +++ ...52-perf-metric-Fix-some-memory-leaks.patch | 76 ++ ...-metric-Fix-some-memory-leaks-part-2.patch | 59 ++ ...-perf-evlist-Fix-cpu-thread-map-leak.patch | 77 ++ ...-event-Fix-memory-leak-in-evsel-unit.patch | 74 ++ ...ix-memory-leaks-in-parse-metric-test.patch | 87 ++ ...Release-expr_parse_ctx-after-testing.patch | 84 ++ ...ree-metric-when-it-failed-to-resolve.patch | 109 +++ ...ot-free-metric-when-failed-to-resolv.patch | 77 ++ ...Free-formats-for-perf-pmu-parse-test.patch | 100 +++ ...cgroup-Fix-uncore-metric-expressions.patch | 204 +++++ ...-Make-find_metric-public-with-name-c.patch | 84 ++ ...-metric-reuse-in-pmu-events-parsing-.patch | 176 ++++ ..._events_map__find-function-to-find-t.patch | 174 ++++ ...ents-arm64-Add-Hisi-hip08-L1-metrics.patch | 82 ++ ...ents-arm64-Add-Hisi-hip08-L2-metrics.patch | 95 ++ ...ents-arm64-Add-Hisi-hip08-L3-metrics.patch | 214 +++++ ...-event-code-for-events-referencing-s.patch | 76 ++ ...ts-Fix-getting-maximum-number-of-fds.patch | 52 ++ ...-event-syntax-error-caused-by-ExtSel.patch | 70 ++ ...271-perf-jevents-Tidy-error-handling.patch | 168 ++++ ...-support-for-an-extra-directory-leve.patch | 93 ++ ...Add-support-for-system-events-tables.patch | 356 ++++++++ patches/0274-perf-pmu-Add-pmu_id.patch | 105 +++ ...275-perf-pmu-Add-pmu_add_sys_aliases.patch | 163 ++++ ...ge-evlist__splice_list_tail-ordering.patch | 85 ++ ...-Fix-metrics-using-aliases-covering-.patch | 106 +++ ...ricgroup-Split-up-metricgroup__print.patch | 202 +++++ ...-Support-printing-metric-groups-for-.patch | 146 ++++ ...-Support-adding-metrics-for-system-P.patch | 162 ++++ ...jevents-Add-test-for-arch-std-events.patch | 138 +++ ...attern-matching-for-same-substring-i.patch | 168 ++++ .../0283-perf-pmu-Fix-alias-matching.patch | 119 +++ ...as-match-method-to-fit-pmu_name-of-H.patch | 37 + ...y-arguments-of-__perf_pmu__new_alias.patch | 109 +++ patches/0286-perf-pmu-Save-pmu-name.patch | 100 +++ ...-Make-build-dependency-on-test-JSONs.patch | 59 ++ ...ctor-out-pmu-events-event-comparison.patch | 177 ++++ ...s-Relocate-test-events-to-cpu-folder.patch | 75 ++ ...re-pmu-events-test-events-separately.patch | 389 +++++++++ ...ctor-out-pmu-events-alias-comparison.patch | 137 +++ ...t-pmu-events-core-aliases-separately.patch | 151 ++++ ...is_uncore-field-in-pmu_add_cpu_alias.patch | 55 ++ ...-add-pmu-event-uncore-PMU-alias-test.patch | 206 +++++ ...t-Add-more-pmu-events-uncore-aliases.patch | 165 ++++ ...-pmu-Make-pmu_add_sys_aliases-public.patch | 67 ++ ...rint-SoC-name-per-system-event-table.patch | 65 ++ ...est-Add-pmu-events-sys-event-support.patch | 185 ++++ ...parse-events-Set-numeric-term-config.patch | 135 +++ ...0300-perf-jevents-Support-ConfigCode.patch | 97 ++ ...-more-event-members-in-pmu-events-te.patch | 144 +++ ...nts-arm64-Revise-hip08-uncore-events.patch | 435 +++++++++ ...u-events-test-for-aliases-of-hip09-d.patch | 89 ++ ...-support-for-HiSilicon-L3C-PMU-alias.patch | 157 ++++ ...-support-for-HiSilicon-DDRC-PMU-alia.patch | 149 ++++ ...-support-for-HiSilicon-HHA-PMU-alias.patch | 134 +++ ...-support-for-HiSilicon-SLLC-PMU-alia.patch | 182 ++++ ...-support-for-HiSilicon-PA-PMU-aliasi.patch | 118 +++ ...st-parsing-of-floating-point-numbers.patch | 55 ++ ...llow-numbers-to-be-followed-by-a-dot.patch | 69 ++ ...LL-sentinel-in-pmu_events-table-in-P.patch | 209 +++++ ...perf-test-Fix-msan-uninitialized-use.patch | 77 ++ ...13-perf-test-Fix-metric-parsing-test.patch | 84 ++ ...ts-arm64-Fix-incorrect-Hisi-hip08-L3.patch | 91 ++ ...-Return-error-code-from-metricgroup_.patch | 75 ++ ...f-metricgroup-Fix-system-PMU-metrics.patch | 86 ++ ...-Fix-for-metrics-containing-duration.patch | 134 +++ ...-Fix-find_evsel_group-event-selector.patch | 98 +++ series.conf | 201 +++++ 203 files changed, 29881 insertions(+), 1 deletion(-) create mode 100644 patches/0118-perf-stat-Introduce-perf_evlist__print_counters.patch create mode 100644 patches/0119-perf-stat-Move-STAT_RECORD-out-of-perf_evlist__print.patch create mode 100644 patches/0120-perf-stat-Add-struct-perf_stat_config-argument-to-pe.patch create mode 100644 patches/0121-perf-stat-Pass-struct-perf_stat_config-argument-to-l.patch create mode 100644 patches/0122-perf-stat-Pass-a-struct-perf_stat_config-argument-to.patch create mode 100644 patches/0123-perf-stat-Move-metric_events-to-struct-perf_stat_con.patch create mode 100644 patches/0124-perf-list-Display-metric-expressions-for-details-opt.patch create mode 100644 patches/0125-perf-tools-Fix-legacy-events-symbol-separator-parsin.patch create mode 100644 patches/0126-perf-stat-Revert-checks-for-duration_time.patch create mode 100644 patches/0127-perf-stat-Implement-duration_time-as-a-proper-event.patch create mode 100644 patches/0128-perf-evsel-Support-printing-evsel-name-for-duration_.patch create mode 100644 patches/0129-perf-list-Output-tool-events.patch create mode 100644 patches/0130-libbpf-add-resizable-non-thread-safe-internal-hashma.patch create mode 100644 patches/0131-perf-stat-Fix-metrics-with-no-merge.patch create mode 100644 patches/0132-perf-jevents-Remove-unused-variable.patch create mode 100644 patches/0133-perf-jevents-Use-nonlocal-include-statements-in-pmu-.patch create mode 100644 patches/0134-perf-list-Avoid-extra-for-raw-metrics.patch create mode 100644 patches/0135-perf-tools-metric-Don-t-include-duration_time-in-gro.patch create mode 100644 patches/0136-perf-metricgroup-Add-missing-list_del_init-when-flus.patch create mode 100644 patches/0137-perf-metricgroup-Remove-needless-includes-from-metri.patch create mode 100644 patches/0138-perf-pmu-Change-convert_scale-from-static-to-global.patch create mode 100644 patches/0139-perf-metricgroup-Scale-the-metric-result.patch create mode 100644 patches/0140-perf-metricgroup-Support-multiple-events-for-metricg.patch create mode 100644 patches/0141-perf-pmu-Support-more-complex-PMU-event-aliasing.patch create mode 100644 patches/0142-perf-jevents-Add-support-for-Hisi-hip08-DDRC-PMU-ali.patch create mode 100644 patches/0143-perf-jevents-Add-support-for-Hisi-hip08-HHA-PMU-alia.patch create mode 100644 patches/0144-perf-jevents-Add-support-for-Hisi-hip08-L3C-PMU-alia.patch create mode 100644 patches/0145-perf-vendor-events-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch create mode 100644 patches/0146-perf-vendor-events-arm64-Add-some-missing-events-for.patch create mode 100644 patches/0147-perf-vendor-events-arm64-Add-some-missing-events-for.patch create mode 100644 patches/0148-perf-vendor-events-arm64-Add-some-missing-events-for.patch create mode 100644 patches/0149-perf-stat-Fix-free-memory-access-memory-leaks-in-met.patch create mode 100644 patches/0150-perf-tools-Move-ALLOC_LIST-into-a-function.patch create mode 100644 patches/0151-perf-list-Hide-deprecated-events-by-default.patch create mode 100644 patches/0152-perf-metricgroup-Fix-printing-event-names-of-metric-.patch create mode 100644 patches/0153-tools-bitmap-Implement-bitmap_equal-operation-at-bit.patch create mode 100644 patches/0154-perf-metricgroup-Fix-printing-event-names-of-metric-.patch create mode 100644 patches/0155-perf-parse-events-Fix-an-old-style-declaration.patch create mode 100644 patches/0156-libbpf-fix-missing-__WORDSIZE-definition.patch create mode 100644 patches/0157-libbpf-hashmap-Remove-unused-include.patch create mode 100644 patches/0158-libbpf-Define-__WORDSIZE-if-not-available.patch create mode 100644 patches/0159-libbpf-Fix-libbpf-hashmap-on-I-LP32-architectures.patch create mode 100644 patches/0160-libbpf-hashmap-Fix-undefined-behavior-in-hash_bits.patch create mode 100644 patches/0161-perf-tools-Grab-a-copy-of-libbpf-s-hashmap.patch create mode 100644 patches/0162-perf-tools-Sync-hashmap.h-with-libbpf-s.patch create mode 100644 patches/0163-perf-tools-Update-copy-of-libbpf-s-hashmap.c.patch create mode 100644 patches/0164-perf-jevents-Support-metric-constraint.patch create mode 100644 patches/0165-perf-metricgroup-Factor-out-metricgroup__add_metric_.patch create mode 100644 patches/0166-perf-util-Factor-out-sysctl__nmi_watchdog_enabled.patch create mode 100644 patches/0167-perf-metricgroup-Support-metric-constraint.patch create mode 100644 patches/0168-perf-vendor-events-intel-Add-NO_NMI_WATCHDOG-metric-.patch create mode 100644 patches/0169-perf-expr-Add-expr.c-object.patch create mode 100644 patches/0170-perf-expr-Move-expr-lexer-to-flex.patch create mode 100644 patches/0171-perf-expr-Increase-EXPR_MAX_OTHER-to-support-metrics.patch create mode 100644 patches/0172-perf-expr-Straighten-expr__parse-expr__find_other-in.patch create mode 100644 patches/0173-perf-expr-Make-expr__parse-return-1-on-error.patch create mode 100644 patches/0174-perf-expr-Fix-memory-leaks-in-metric-bison.patch create mode 100644 patches/0175-perf-expr-Fix-copy-paste-mistake.patch create mode 100644 patches/0176-perf-expr-Add-expr_-prefix-for-parse_ctx-and-parse_i.patch create mode 100644 patches/0177-perf-expr-Add-expr_scanner_ctx-object.patch create mode 100644 patches/0178-perf-metrictroup-Split-the-metricgroup__add_metric-f.patch create mode 100644 patches/0179-perf-metricgroups-Enhance-JSON-metric-infrastructure.patch create mode 100644 patches/0180-perf-tests-expr-Added-test-for-runtime-param-in-metr.patch create mode 100644 patches/0181-perf-jevents-Add-some-test-events.patch create mode 100644 patches/0182-perf-jevents-Support-test-events-folder.patch create mode 100644 patches/0183-perf-pmu-Refactor-pmu_add_cpu_aliases.patch create mode 100644 patches/0184-perf-test-Add-pmu-events-test.patch create mode 100644 patches/0185-perf-pmu-Add-is_pmu_core.patch create mode 100644 patches/0186-perf-pmu-Make-pmu_uncore_alias_match-public.patch create mode 100644 patches/0187-perf-test-Test-pmu-events-aliases.patch create mode 100644 patches/0188-perf-expr-Allow-for-unlimited-escaped-characters-in-.patch create mode 100644 patches/0189-perf-expr-Allow-to-be-an-other-token.patch create mode 100644 patches/0190-perf-expr-Increase-max-other.patch create mode 100644 patches/0191-perf-expr-Parse-numbers-as-doubles.patch create mode 100644 patches/0192-perf-test-Improve-pmu-event-metric-testing.patch create mode 100644 patches/0193-perf-test-Provide-a-subtest-callback-to-ask-for-the-.patch create mode 100644 patches/0194-perf-expr-Migrate-expr-ids-table-to-a-hashmap.patch create mode 100644 patches/0195-perf-metricgroup-Make-evlist_used-variable-a-bitmap-.patch create mode 100644 patches/0196-perf-metricgroup-Always-place-duration_time-last.patch create mode 100644 patches/0197-perf-metricgroup-Use-early-return-in-add_metric.patch create mode 100644 patches/0198-perf-metricgroup-Delay-events-string-creation.patch create mode 100644 patches/0199-perf-metricgroup-Order-event-groups-by-size.patch create mode 100644 patches/0200-perf-metricgroup-Remove-duped-metric-group-events.patch create mode 100644 patches/0201-perf-metricgroup-Add-options-to-not-group-or-merge.patch create mode 100644 patches/0202-perf-metricgroup-Remove-unnecessary-from-events.patch create mode 100644 patches/0203-perf-parser-Add-support-to-specify-rXXX-event-with-p.patch create mode 100644 patches/0204-perf-tools-Allow-r0x-HEX-event-syntax.patch create mode 100644 patches/0205-perf-stat-Do-not-pass-avg-to-generic_metric.patch create mode 100644 patches/0206-perf-parse-Add-struct-parse_events_state-pointer-to-.patch create mode 100644 patches/0207-perf-tools-Fix-term-parsing-for-raw-syntax.patch create mode 100644 patches/0208-perf-tools-Add-fake-pmu-support.patch create mode 100644 patches/0209-perf-tests-Factor-check_parse_id-function.patch create mode 100644 patches/0210-perf-parse-Provide-a-way-to-pass-a-fake_pmu-to-parse.patch create mode 100644 patches/0211-perf-pmu-Add-a-perf_pmu__fake-object-to-use-with-__p.patch create mode 100644 patches/0212-perf-tests-Add-another-metric-parsing-test.patch create mode 100644 patches/0213-perf-parse-Factor-out-parse_groups-function.patch create mode 100644 patches/0214-perf-tools-Add-fake_pmu-to-parse_group-function.patch create mode 100644 patches/0215-perf-tools-Add-map-to-parse_groups-function.patch create mode 100644 patches/0216-perf-tools-Add-metricgroup__parse_groups_test-functi.patch create mode 100644 patches/0217-perf-tools-Factor-out-prepare_metric-function.patch create mode 100644 patches/0218-perf-tools-Release-metric_events-rblist.patch create mode 100644 patches/0219-perf-tools-Add-test_generic_metric-function.patch create mode 100644 patches/0220-perf-pmu-List-kernel-supplied-event-aliases-for-arm6.patch create mode 100644 patches/0221-perf-pmu-Improve-CPU-core-PMU-HW-event-list-ordering.patch create mode 100644 patches/0222-perf-metric-Rename-expr__add_id-to-expr__add_val.patch create mode 100644 patches/0223-perf-metric-Add-struct-expr_id_data-to-keep-expr-val.patch create mode 100644 patches/0224-perf-metric-Fix-memory-leak-in-expr__add_id-function.patch create mode 100644 patches/0225-perf-metric-Add-expr__add_id-function.patch create mode 100644 patches/0226-perf-metric-Change-expr__get_id-to-return-struct-exp.patch create mode 100644 patches/0227-perf-metric-Add-expr__del_id-function.patch create mode 100644 patches/0228-perf-metric-Add-macros-for-iterating-map-events.patch create mode 100644 patches/0229-perf-metric-Add-add_metric-function.patch create mode 100644 patches/0230-perf-metric-Rename-__metricgroup__add_metric-to-__ad.patch create mode 100644 patches/0231-perf-metric-Collect-referenced-metrics-in-struct-met.patch create mode 100644 patches/0232-perf-metric-Collect-referenced-metrics-in-struct-met.patch create mode 100644 patches/0233-perf-metric-Add-referenced-metrics-to-hash-data.patch create mode 100644 patches/0234-perf-metric-Compute-referenced-metrics.patch create mode 100644 patches/0235-perf-metric-Add-events-for-the-current-list.patch create mode 100644 patches/0236-perf-tests-Add-parse-metric-test-for-ipc-metric.patch create mode 100644 patches/0237-perf-tests-Add-parse-metric-test-for-frontend-metric.patch create mode 100644 patches/0238-perf-metric-Add-cache_miss_cycles-to-metric-parse-te.patch create mode 100644 patches/0239-perf-metric-Add-DCache_L2-to-metric-parse-test.patch create mode 100644 patches/0240-perf-metric-Add-recursion-check-when-processing-nest.patch create mode 100644 patches/0241-perf-metric-Make-compute_single-function-more-precis.patch create mode 100644 patches/0242-perf-metric-Add-metric-group-test.patch create mode 100644 patches/0243-perf-metric-Rename-struct-egroup-to-metric.patch create mode 100644 patches/0244-perf-metric-Rename-group_list-to-metric_list.patch create mode 100644 patches/0245-perf-jevents-Make-json_events-static-and-ditch-jeven.patch create mode 100644 patches/0246-perf-jevents-Add-new-structure-to-pass-json-fields.patch create mode 100644 patches/0247-perf-jevents-Add-support-for-parsing-perchip-percore.patch create mode 100644 patches/0248-perf-metricgroup-Pass-pmu_event-structure-as-a-param.patch create mode 100644 patches/0249-perf-list-Do-not-print-Metric-Groups-unnecessarily.patch create mode 100644 patches/0250-perf-metricgroup-Fix-typo-in-comment.patch create mode 100644 patches/0251-perf-test-Free-aliases-for-PMU-event-map-aliases-tes.patch create mode 100644 patches/0252-perf-metric-Fix-some-memory-leaks.patch create mode 100644 patches/0253-perf-metric-Fix-some-memory-leaks-part-2.patch create mode 100644 patches/0254-perf-evlist-Fix-cpu-thread-map-leak.patch create mode 100644 patches/0255-perf-parse-event-Fix-memory-leak-in-evsel-unit.patch create mode 100644 patches/0256-perf-test-Fix-memory-leaks-in-parse-metric-test.patch create mode 100644 patches/0257-perf-metric-Release-expr_parse_ctx-after-testing.patch create mode 100644 patches/0258-perf-metric-Free-metric-when-it-failed-to-resolve.patch create mode 100644 patches/0259-perf-metric-Do-not-free-metric-when-failed-to-resolv.patch create mode 100644 patches/0260-perf-test-Free-formats-for-perf-pmu-parse-test.patch create mode 100644 patches/0261-perf-metricgroup-Fix-uncore-metric-expressions.patch create mode 100644 patches/0262-perf-metricgroup-Make-find_metric-public-with-name-c.patch create mode 100644 patches/0263-perf-test-Handle-metric-reuse-in-pmu-events-parsing-.patch create mode 100644 patches/0264-perf-pmu-Add-pmu_events_map__find-function-to-find-t.patch create mode 100644 patches/0265-perf-vendor-events-arm64-Add-Hisi-hip08-L1-metrics.patch create mode 100644 patches/0266-perf-vendor-events-arm64-Add-Hisi-hip08-L2-metrics.patch create mode 100644 patches/0267-perf-vendor-events-arm64-Add-Hisi-hip08-L3-metrics.patch create mode 100644 patches/0268-perf-jevents-Fix-event-code-for-events-referencing-s.patch create mode 100644 patches/0269-perf-jevents-Fix-getting-maximum-number-of-fds.patch create mode 100644 patches/0270-perf-jevents-Fix-event-syntax-error-caused-by-ExtSel.patch create mode 100644 patches/0271-perf-jevents-Tidy-error-handling.patch create mode 100644 patches/0272-perf-jevents-Add-support-for-an-extra-directory-leve.patch create mode 100644 patches/0273-perf-jevents-Add-support-for-system-events-tables.patch create mode 100644 patches/0274-perf-pmu-Add-pmu_id.patch create mode 100644 patches/0275-perf-pmu-Add-pmu_add_sys_aliases.patch create mode 100644 patches/0276-perf-evlist-Change-evlist__splice_list_tail-ordering.patch create mode 100644 patches/0277-perf-metricgroup-Fix-metrics-using-aliases-covering-.patch create mode 100644 patches/0278-perf-metricgroup-Split-up-metricgroup__print.patch create mode 100644 patches/0279-perf-metricgroup-Support-printing-metric-groups-for-.patch create mode 100644 patches/0280-perf-metricgroup-Support-adding-metrics-for-system-P.patch create mode 100644 patches/0281-perf-jevents-Add-test-for-arch-std-events.patch create mode 100644 patches/0282-perf-tools-Fix-pattern-matching-for-same-substring-i.patch create mode 100644 patches/0283-perf-pmu-Fix-alias-matching.patch create mode 100644 patches/0284-perf-pmu-Add-alias-match-method-to-fit-pmu_name-of-H.patch create mode 100644 patches/0285-perf-pmu-Simplify-arguments-of-__perf_pmu__new_alias.patch create mode 100644 patches/0286-perf-pmu-Save-pmu-name.patch create mode 100644 patches/0287-perf-jevents-Make-build-dependency-on-test-JSONs.patch create mode 100644 patches/0288-perf-test-Factor-out-pmu-events-event-comparison.patch create mode 100644 patches/0289-perf-jevents-Relocate-test-events-to-cpu-folder.patch create mode 100644 patches/0290-perf-test-Declare-pmu-events-test-events-separately.patch create mode 100644 patches/0291-perf-test-Factor-out-pmu-events-alias-comparison.patch create mode 100644 patches/0292-perf-test-Test-pmu-events-core-aliases-separately.patch create mode 100644 patches/0293-perf-pmu-Check-.is_uncore-field-in-pmu_add_cpu_alias.patch create mode 100644 patches/0294-perf-test-Re-add-pmu-event-uncore-PMU-alias-test.patch create mode 100644 patches/0295-perf-test-Add-more-pmu-events-uncore-aliases.patch create mode 100644 patches/0296-perf-pmu-Make-pmu_add_sys_aliases-public.patch create mode 100644 patches/0297-perf-jevents-Print-SoC-name-per-system-event-table.patch create mode 100644 patches/0298-perf-test-Add-pmu-events-sys-event-support.patch create mode 100644 patches/0299-perf-parse-events-Set-numeric-term-config.patch create mode 100644 patches/0300-perf-jevents-Support-ConfigCode.patch create mode 100644 patches/0301-perf-test-Verify-more-event-members-in-pmu-events-te.patch create mode 100644 patches/0302-perf-vendor-events-arm64-Revise-hip08-uncore-events.patch create mode 100644 patches/0303-perf-test-Add-pmu-events-test-for-aliases-of-hip09-d.patch create mode 100644 patches/0304-perf-jevents-Add-support-for-HiSilicon-L3C-PMU-alias.patch create mode 100644 patches/0305-perf-jevents-Add-support-for-HiSilicon-DDRC-PMU-alia.patch create mode 100644 patches/0306-perf-jevents-Add-support-for-HiSilicon-HHA-PMU-alias.patch create mode 100644 patches/0307-perf-jevents-Add-support-for-HiSilicon-SLLC-PMU-alia.patch create mode 100644 patches/0308-perf-jevents-Add-support-for-HiSilicon-PA-PMU-aliasi.patch create mode 100644 patches/0309-perf-expr-Test-parsing-of-floating-point-numbers.patch create mode 100644 patches/0310-perf-expr-Allow-numbers-to-be-followed-by-a-dot.patch create mode 100644 patches/0311-perf-test-Set-NULL-sentinel-in-pmu_events-table-in-P.patch create mode 100644 patches/0312-perf-test-Fix-msan-uninitialized-use.patch create mode 100644 patches/0313-perf-test-Fix-metric-parsing-test.patch create mode 100644 patches/0314-perf-vendor-events-arm64-Fix-incorrect-Hisi-hip08-L3.patch create mode 100644 patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch create mode 100644 patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch create mode 100644 patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch create mode 100644 patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch diff --git a/kernel.spec b/kernel.spec index c359e30..36dd3b7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -32,7 +32,7 @@ Name: kernel Version: 4.19.90 -Release: %{hulkrelease}.0238 +Release: %{hulkrelease}.0239 Summary: Linux Kernel License: GPLv2 URL: http://www.kernel.org/ @@ -836,6 +836,211 @@ fi %endif %changelog + +* Fri Nov 10 2023 hongrongxuan - 4.19.90-2311.1.0.0239 +- perf metricgroup: Fix find_evsel_group() event selector +- perf metricgroup: Fix for metrics containing duration_time +- perf metricgroup: Fix system PMU metrics +- perf metricgroup: Return error code from metricgroup__add_metric_sys_event_iter() +- perf vendor events arm64: Fix incorrect Hisi hip08 L3 metrics +- perf test: Fix metric parsing test +- perf test: Fix msan uninitialized use. +- perf test: Set NULL sentinel in pmu_events table in "Parse and process metrics" test +- perf expr: Allow numbers to be followed by a dot +- perf expr: Test parsing of floating point numbers +- perf jevents: Add support for HiSilicon PA PMU aliasing +- perf jevents: Add support for HiSilicon SLLC PMU aliasing +- perf jevents: Add support for HiSilicon HHA PMU aliasing +- perf jevents: Add support for HiSilicon DDRC PMU aliasing +- perf jevents: Add support for HiSilicon L3C PMU aliasing +- perf test: Add pmu-events test for aliases of hip09 ddrc pmu +- perf vendor events arm64: Revise hip08 uncore events +- perf test: Verify more event members in pmu-events test +- perf jevents: Support ConfigCode +- perf parse-events: Set numeric term config +- perf test: Add pmu-events sys event support +- perf jevents: Print SoC name per system event table +- perf pmu: Make pmu_add_sys_aliases() public +- perf test: Add more pmu-events uncore aliases +- perf test: Re-add pmu-event uncore PMU alias test +- perf pmu: Check .is_uncore field in pmu_add_cpu_aliases_map() +- perf test: Test pmu-events core aliases separately +- perf test: Factor out pmu-events alias comparison +- perf test: Declare pmu-events test events separately +- perf jevents: Relocate test events to cpu folder +- perf test: Factor out pmu-events event comparison +- perf jevents: Make build dependency on test JSONs +- perf pmu: Save pmu name +- perf pmu: Simplify arguments of __perf_pmu__new_alias +- perf pmu: Add alias match method to fit pmu_name of HiSilicon DDRC +- perf pmu: Fix alias matching +- perf tools: Fix pattern matching for same substring in different PMU type +- perf jevents: Add test for arch std events +- perf metricgroup: Support adding metrics for system PMUs +- perf metricgroup: Support printing metric groups for system PMUs +- perf metricgroup: Split up metricgroup__print() +- perf metricgroup: Fix metrics using aliases covering multiple PMUs +- perf evlist: Change evlist__splice_list_tail() ordering +- perf pmu: Add pmu_add_sys_aliases() +- perf pmu: Add pmu_id() +- perf jevents: Add support for system events tables +- perf jevents: Add support for an extra directory level +- perf jevents: Tidy error handling +- perf jevents: Fix event syntax error caused by ExtSel +- perf jevents: Fix getting maximum number of fds +- perf jevents: Fix event code for events referencing std arch events +- perf vendor events arm64: Add Hisi hip08 L3 metrics +- perf vendor events arm64: Add Hisi hip08 L2 metrics +- perf vendor events arm64: Add Hisi hip08 L1 metrics +- perf pmu: Add pmu_events_map__find() function to find the common PMU map for the system +- perf test: Handle metric reuse in pmu-events parsing test +- perf metricgroup: Make find_metric() public with name change +- perf metricgroup: Fix uncore metric expressions +- perf test: Free formats for perf pmu parse test +- perf metric: Do not free metric when failed to resolve +- perf metric: Free metric when it failed to resolve +- perf metric: Release expr_parse_ctx after testing +- perf test: Fix memory leaks in parse-metric test +- perf parse-event: Fix memory leak in evsel->unit +- perf evlist: Fix cpu/thread map leak +- perf metric: Fix some memory leaks - part 2 +- perf metric: Fix some memory leaks +- perf test: Free aliases for PMU event map aliases test +- perf metricgroup: Fix typo in comment. +- perf list: Do not print 'Metric Groups:' unnecessarily +- perf metricgroup: Pass pmu_event structure as a parameter for arch_get_runtimeparam() +- perf jevents: Add support for parsing perchip/percore events +- perf jevents: Add new structure to pass json fields. +- perf jevents: Make json_events() static and ditch jevents.h file +- perf metric: Rename group_list to metric_list +- perf metric: Rename struct egroup to metric +- perf metric: Add metric group test +- perf metric: Make compute_single function more precise +- perf metric: Add recursion check when processing nested metrics +- perf metric: Add DCache_L2 to metric parse test +- perf metric: Add cache_miss_cycles to metric parse test +- perf tests: Add parse metric test for frontend metric +- perf tests: Add parse metric test for ipc metric +- perf metric: Add events for the current list +- perf metric: Compute referenced metrics +- perf metric: Add referenced metrics to hash data +- perf metric: Collect referenced metrics in struct metric_expr +- perf metric: Collect referenced metrics in struct metric_ref_node +- perf metric: Rename __metricgroup__add_metric to __add_metric +- perf metric: Add add_metric function +- perf metric: Add macros for iterating map events +- perf metric: Add expr__del_id function +- perf metric: Change expr__get_id to return struct expr_id_data +- perf metric: Add expr__add_id function +- perf metric: Fix memory leak in expr__add_id function +- perf metric: Add 'struct expr_id_data' to keep expr value +- perf metric: Rename expr__add_id() to expr__add_val() +- perf pmu: Improve CPU core PMU HW event list ordering +- perf pmu: List kernel supplied event aliases for arm64 +- perf tools: Add test_generic_metric function +- perf tools: Release metric_events rblist +- perf tools: Factor out prepare_metric function +- perf tools: Add metricgroup__parse_groups_test function +- perf tools: Add fake_pmu to parse_group() function +- perf parse: Factor out parse_groups() function +- perf tests: Add another metric parsing test +- perf pmu: Add a perf_pmu__fake object to use with __parse_events() +- perf parse: Provide a way to pass a fake_pmu to parse_events() +- perf tests: Factor check_parse_id function +- perf tools: Add fake pmu support +- perf tools: Fix term parsing for raw syntax +- perf parse: Add 'struct parse_events_state' pointer to scanner +- perf stat: Do not pass avg to generic_metric +- perf tools: Allow r0x event syntax +- perf parser: Add support to specify rXXX event with pmu +- perf metricgroup: Remove unnecessary ',' from events +- perf metricgroup: Add options to not group or merge +- perf metricgroup: Remove duped metric group events +- perf metricgroup: Order event groups by size +- perf metricgroup: Delay events string creation +- perf metricgroup: Use early return in add_metric +- perf metricgroup: Always place duration_time last +- perf metricgroup: Make 'evlist_used' variable a bitmap instead of array of bools +- perf expr: Migrate expr ids table to a hashmap +- perf test: Provide a subtest callback to ask for the reason for skipping a subtest +- perf test: Improve pmu event metric testing +- perf expr: Parse numbers as doubles +- perf expr: Increase max other +- perf expr: Allow ',' to be an other token +- perf expr: Allow for unlimited escaped characters in a symbol +- perf test: Test pmu-events aliases +- perf pmu: Make pmu_uncore_alias_match() public +- perf pmu: Add is_pmu_core() +- perf test: Add pmu-events test +- perf pmu: Refactor pmu_add_cpu_aliases() +- perf jevents: Support test events folder +- perf jevents: Add some test events +- perf tests expr: Added test for runtime param in metric expression +- perf metricgroups: Enhance JSON/metric infrastructure to handle "?" +- perf metrictroup: Split the metricgroup__add_metric function +- perf expr: Add expr_scanner_ctx object +- perf expr: Add expr_ prefix for parse_ctx and parse_id +- perf expr: Fix copy/paste mistake +- perf expr: Fix memory leaks in metric bison +- perf expr: Make expr__parse() return -1 on error +- perf expr: Straighten expr__parse()/expr__find_other() interface +- perf expr: Increase EXPR_MAX_OTHER to support metrics with more than 15 variables +- perf expr: Move expr lexer to flex +- perf expr: Add expr.c object +- perf vendor events intel: Add NO_NMI_WATCHDOG metric constraint +- perf metricgroup: Support metric constraint +- perf util: Factor out sysctl__nmi_watchdog_enabled() +- perf metricgroup: Factor out metricgroup__add_metric_weak_group() +- perf jevents: Support metric constraint +- perf tools: Update copy of libbpf's hashmap.c +- perf tools: Sync hashmap.h with libbpf's +- perf tools: Grab a copy of libbpf's hashmap +- libbpf, hashmap: Fix undefined behavior in hash_bits +- libbpf: Fix libbpf hashmap on (I)LP32 architectures +- libbpf: Define __WORDSIZE if not available +- libbpf, hashmap: Remove unused #include +- libbpf: fix missing __WORDSIZE definition +- perf parse-events: Fix an old style declaration +- perf metricgroup: Fix printing event names of metric group with multiple events incase of overlapping events +- tools bitmap: Implement bitmap_equal() operation at bitmap API +- perf metricgroup: Fix printing event names of metric group with multiple events +- perf list: Hide deprecated events by default +- perf tools: Move ALLOC_LIST into a function +- perf stat: Fix free memory access / memory leaks in metrics +- perf vendor events arm64: Add some missing events for Hisi hip08 HHA PMU +- perf vendor events arm64: Add some missing events for Hisi hip08 L3C PMU +- perf vendor events arm64: Add some missing events for Hisi hip08 DDRC PMU +- perf vendor events arm64: Fix Hisi hip08 DDRC PMU eventname +- perf jevents: Add support for Hisi hip08 L3C PMU aliasing +- perf jevents: Add support for Hisi hip08 HHA PMU aliasing +- perf jevents: Add support for Hisi hip08 DDRC PMU aliasing +- perf pmu: Support more complex PMU event aliasing +- perf metricgroup: Support multiple events for metricgroup +- perf metricgroup: Scale the metric result +- perf pmu: Change convert_scale from static to global +- perf metricgroup: Remove needless includes from metricgroup.h +- perf metricgroup: Add missing list_del_init() when flushing egroups list +- perf tools metric: Don't include duration_time in group +- perf list: Avoid extra : for --raw metrics +- perf jevents: Use nonlocal include statements in pmu-events.c +- perf jevents: Remove unused variable +- perf stat: Fix metrics with --no-merge +- libbpf: add resizable non-thread safe internal hashmap +- perf list: Output tool events +- perf evsel: Support printing evsel name for 'duration_time' +- perf stat: Implement duration_time as a proper event +- perf stat: Revert checks for duration_time +- perf stat: Implement duration_time as a proper event +- perf stat: Revert checks for duration_time +- perf tools: Fix legacy events symbol separator parsing +- perf list: Display metric expressions for --details option +- perf stat: Move 'metric_events' to 'struct perf_stat_config' +- perf stat: Pass a 'struct perf_stat_config' argument to global print functions +- perf stat: Pass 'struct perf_stat_config' argument to local print functions +- perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters() +- perf stat: Move STAT_RECORD out of perf_evlist__print_counters() +- perf stat: Introduce perf_evlist__print_counters() + * Thu Nov 9 2023 Kunkun Jiang - 4.19.90-2311.1.0.0238 - scsi: virtio_scsi: limit number of hw queues by nr_cpu_ids diff --git a/patches/0118-perf-stat-Introduce-perf_evlist__print_counters.patch b/patches/0118-perf-stat-Introduce-perf_evlist__print_counters.patch new file mode 100644 index 0000000..9ccb41e --- /dev/null +++ b/patches/0118-perf-stat-Introduce-perf_evlist__print_counters.patch @@ -0,0 +1,88 @@ +From f58c620c83b508633e9e532906cb52fb54555e2a Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:24 +0200 +Subject: [PATCH 001/201] perf stat: Introduce perf_evlist__print_counters() + +mainline inclusion +from mainline-v4.20-rc1 +commit a5a9eac1a018ad3bfcf9a3ec11eae99fd35f466b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a5a9eac1a018ad3bfcf9a3ec11eae99fd35f466b + +----------------------------------------------------------------------- + +To be in charge of printing out the stat output. It will be moved out of +the 'perf stat' command in the following patches. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-16-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index adabe9d4dc86..48327256f0bf 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1827,7 +1827,10 @@ static void print_footer(void) + "the same PMU. Try reorganizing the group.\n"); + } + +-static void print_counters(struct timespec *ts, int argc, const char **argv) ++static void ++perf_evlist__print_counters(struct perf_evlist *evlist, ++ struct timespec *ts, ++ int argc, const char **argv) + { + int interval = stat_config.interval; + struct perf_evsel *counter; +@@ -1859,14 +1862,14 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) + print_aggr(prefix); + break; + case AGGR_THREAD: +- evlist__for_each_entry(evsel_list, counter) { ++ evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_aggr_thread(counter, prefix); + } + break; + case AGGR_GLOBAL: +- evlist__for_each_entry(evsel_list, counter) { ++ evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_counter_aggr(counter, prefix); +@@ -1878,7 +1881,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) + if (metric_only) + print_no_aggr_metric(prefix); + else { +- evlist__for_each_entry(evsel_list, counter) { ++ evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; + print_counter(counter, prefix); +@@ -1896,6 +1899,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) + fflush(stat_config.output); + } + ++static void print_counters(struct timespec *ts, int argc, const char **argv) ++{ ++ perf_evlist__print_counters(evsel_list, ts, argc, argv); ++} ++ + static volatile int signr = -1; + + static void skip_signal(int signo) +-- +2.27.0 + diff --git a/patches/0119-perf-stat-Move-STAT_RECORD-out-of-perf_evlist__print.patch b/patches/0119-perf-stat-Move-STAT_RECORD-out-of-perf_evlist__print.patch new file mode 100644 index 0000000..6189456 --- /dev/null +++ b/patches/0119-perf-stat-Move-STAT_RECORD-out-of-perf_evlist__print.patch @@ -0,0 +1,62 @@ +From 0a0a381759790e5b2b961837faccd6c8aeefb038 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:25 +0200 +Subject: [PATCH 002/201] perf stat: Move STAT_RECORD out of + perf_evlist__print_counters() + +mainline inclusion +from mainline-v4.20-rc1 +commit 0174820a8ba108f2e72dac5caaea3500c8ca6323 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0174820a8ba108f2e72dac5caaea3500c8ca6323 + +------------------------------------------------------------------- + +It's stat related and should stay in the 'perf stat' command. The +perf_evlist__print_counters function will be moved out in the following +patches. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-17-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 48327256f0bf..78dfefd6f49a 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1836,10 +1836,6 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + struct perf_evsel *counter; + char buf[64], *prefix = NULL; + +- /* Do not print anything if we record to the pipe. */ +- if (STAT_RECORD && perf_stat.data.is_pipe) +- return; +- + if (interval) + print_interval(prefix = buf, ts); + else +@@ -1901,6 +1897,10 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + + static void print_counters(struct timespec *ts, int argc, const char **argv) + { ++ /* Do not print anything if we record to the pipe. */ ++ if (STAT_RECORD && perf_stat.data.is_pipe) ++ return; ++ + perf_evlist__print_counters(evsel_list, ts, argc, argv); + } + +-- +2.27.0 + diff --git a/patches/0120-perf-stat-Add-struct-perf_stat_config-argument-to-pe.patch b/patches/0120-perf-stat-Add-struct-perf_stat_config-argument-to-pe.patch new file mode 100644 index 0000000..f5ad303 --- /dev/null +++ b/patches/0120-perf-stat-Add-struct-perf_stat_config-argument-to-pe.patch @@ -0,0 +1,96 @@ +From 36827ecfdf56b255245f4ed510b2d2b2fdba0ddf Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:26 +0200 +Subject: [PATCH 003/201] perf stat: Add 'struct perf_stat_config' argument to + perf_evlist__print_counters() + +mainline inclusion +from mainline-v4.20-rc1 +commit b64df7f33743cd6095b4a007f5f15ff4432fbcf5 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b64df7f33743cd6095b4a007f5f15ff4432fbcf5 + +------------------------------------------------------------------------ + +Add a 'struct perf_stat_config' argument to perf_evlist__print_counters(), +so that it can be moved out of the 'perf stat' command to generic object +in the following patches. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-18-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 78dfefd6f49a..c35307ea6110 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1829,10 +1829,11 @@ static void print_footer(void) + + static void + perf_evlist__print_counters(struct perf_evlist *evlist, ++ struct perf_stat_config *config, + struct timespec *ts, + int argc, const char **argv) + { +- int interval = stat_config.interval; ++ int interval = config->interval; + struct perf_evsel *counter; + char buf[64], *prefix = NULL; + +@@ -1848,11 +1849,11 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + print_metric_headers(prefix, false); + if (num_print_iv++ == 25) + num_print_iv = 0; +- if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) +- fprintf(stat_config.output, "%s", prefix); ++ if (config->aggr_mode == AGGR_GLOBAL && prefix) ++ fprintf(config->output, "%s", prefix); + } + +- switch (stat_config.aggr_mode) { ++ switch (config->aggr_mode) { + case AGGR_CORE: + case AGGR_SOCKET: + print_aggr(prefix); +@@ -1871,7 +1872,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + print_counter_aggr(counter, prefix); + } + if (metric_only) +- fputc('\n', stat_config.output); ++ fputc('\n', config->output); + break; + case AGGR_NONE: + if (metric_only) +@@ -1892,7 +1893,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + if (!interval && !csv_output) + print_footer(); + +- fflush(stat_config.output); ++ fflush(config->output); + } + + static void print_counters(struct timespec *ts, int argc, const char **argv) +@@ -1901,7 +1902,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) + if (STAT_RECORD && perf_stat.data.is_pipe) + return; + +- perf_evlist__print_counters(evsel_list, ts, argc, argv); ++ perf_evlist__print_counters(evsel_list, &stat_config, ++ ts, argc, argv); + } + + static volatile int signr = -1; +-- +2.27.0 + diff --git a/patches/0121-perf-stat-Pass-struct-perf_stat_config-argument-to-l.patch b/patches/0121-perf-stat-Pass-struct-perf_stat_config-argument-to-l.patch new file mode 100644 index 0000000..e271a1c --- /dev/null +++ b/patches/0121-perf-stat-Pass-struct-perf_stat_config-argument-to-l.patch @@ -0,0 +1,471 @@ +From bf2703eb25ea734092e4749e7723f3d6a635bb7d Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:27 +0200 +Subject: [PATCH 004/201] perf stat: Pass 'struct perf_stat_config' argument to + local print functions + +mainline inclusion +from mainline-v4.20-rc1 +commit f3ca50e61ff4aebfbefc666be2e064d277ad524c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f3ca50e61ff4aebfbefc666be2e064d277ad524c + +----------------------------------------------------------------------- + +Add 'struct perf_stat_config' argument to print functions, so that those +functions can be moved out of the 'perf stat' command to a generic class +in the following patches. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-19-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 149 ++++++++++++++++++++------------------ + 1 file changed, 80 insertions(+), 69 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index c35307ea6110..267b2cc9e73a 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -795,30 +795,33 @@ static int run_perf_stat(int argc, const char **argv, int run_idx) + return ret; + } + +-static void print_running(u64 run, u64 ena) ++static void print_running(struct perf_stat_config *config, ++ u64 run, u64 ena) + { + if (csv_output) { +- fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f", ++ fprintf(config->output, "%s%" PRIu64 "%s%.2f", + csv_sep, + run, + csv_sep, + ena ? 100.0 * run / ena : 100.0); + } else if (run != ena) { +- fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena); ++ fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); + } + } + +-static void print_noise_pct(double total, double avg) ++static void print_noise_pct(struct perf_stat_config *config, ++ double total, double avg) + { + double pct = rel_stddev_stats(total, avg); + + if (csv_output) +- fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct); ++ fprintf(config->output, "%s%.2f%%", csv_sep, pct); + else if (pct) +- fprintf(stat_config.output, " ( +-%6.2f%% )", pct); ++ fprintf(config->output, " ( +-%6.2f%% )", pct); + } + +-static void print_noise(struct perf_evsel *evsel, double avg) ++static void print_noise(struct perf_stat_config *config, ++ struct perf_evsel *evsel, double avg) + { + struct perf_stat_evsel *ps; + +@@ -826,7 +829,7 @@ static void print_noise(struct perf_evsel *evsel, double avg) + return; + + ps = evsel->stats; +- print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); ++ print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); + } + + static void aggr_printout(struct perf_evsel *evsel, int id, int nr) +@@ -1122,13 +1125,14 @@ static bool is_mixed_hw_group(struct perf_evsel *counter) + return false; + } + +-static void printout(int id, int nr, struct perf_evsel *counter, double uval, ++static void printout(struct perf_stat_config *config, int id, int nr, ++ struct perf_evsel *counter, double uval, + char *prefix, u64 run, u64 ena, double noise, + struct runtime_stat *st) + { + struct perf_stat_output_ctx out; + struct outstate os = { +- .fh = stat_config.output, ++ .fh = config->output, + .prefix = prefix ? prefix : "", + .id = id, + .nr = nr, +@@ -1158,7 +1162,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, + pm = print_metric_csv; + nl = new_line_csv; + os.nfields = 3; +- os.nfields += aggr_fields[stat_config.aggr_mode]; ++ os.nfields += aggr_fields[config->aggr_mode]; + if (counter->cgrp) + os.nfields++; + } +@@ -1169,7 +1173,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, + } + aggr_printout(counter, id, nr); + +- fprintf(stat_config.output, "%*s%s", ++ fprintf(config->output, "%*s%s", + csv_output ? 0 : 18, + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, + csv_sep); +@@ -1180,22 +1184,22 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, + print_mixed_hw_group_error = 1; + } + +- fprintf(stat_config.output, "%-*s%s", ++ fprintf(config->output, "%-*s%s", + csv_output ? 0 : unit_width, + counter->unit, csv_sep); + +- fprintf(stat_config.output, "%*s", ++ fprintf(config->output, "%*s", + csv_output ? 0 : -25, + perf_evsel__name(counter)); + + if (counter->cgrp) +- fprintf(stat_config.output, "%s%s", ++ fprintf(config->output, "%s%s", + csv_sep, counter->cgrp->name); + + if (!csv_output) + pm(&os, NULL, NULL, "", 0); +- print_noise(counter, noise); +- print_running(run, ena); ++ print_noise(config, counter, noise); ++ print_running(config, run, ena); + if (csv_output) + pm(&os, NULL, NULL, "", 0); + return; +@@ -1210,16 +1214,16 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval, + out.force_header = false; + + if (csv_output && !metric_only) { +- print_noise(counter, noise); +- print_running(run, ena); ++ print_noise(config, counter, noise); ++ print_running(config, run, ena); + } + + perf_stat__print_shadow_stats(counter, uval, + first_shadow_cpu(counter, id), + &out, &metric_events, st); + if (!csv_output && !metric_only) { +- print_noise(counter, noise); +- print_running(run, ena); ++ print_noise(config, counter, noise); ++ print_running(config, run, ena); + } + } + +@@ -1346,9 +1350,10 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first) + } + } + +-static void print_aggr(char *prefix) ++static void print_aggr(struct perf_stat_config *config, ++ char *prefix) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + struct perf_evsel *counter; + int s, id, nr; + double uval; +@@ -1391,8 +1396,8 @@ static void print_aggr(char *prefix) + fprintf(output, "%s", prefix); + + uval = val * counter->scale; +- printout(id, nr, counter, uval, prefix, run, ena, 1.0, +- &rt_stat); ++ printout(config, id, nr, counter, uval, prefix, ++ run, ena, 1.0, &rt_stat); + if (!metric_only) + fputc('\n', output); + } +@@ -1455,9 +1460,10 @@ static struct perf_aggr_thread_value *sort_aggr_thread( + return buf; + } + +-static void print_aggr_thread(struct perf_evsel *counter, char *prefix) ++static void print_aggr_thread(struct perf_stat_config *config, ++ struct perf_evsel *counter, char *prefix) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + int nthreads = thread_map__nr(counter->threads); + int ncpus = cpu_map__nr(counter->cpus); + int thread, sorted_threads, id; +@@ -1474,12 +1480,12 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix) + fprintf(output, "%s", prefix); + + id = buf[thread].id; +- if (stat_config.stats) +- printout(id, 0, buf[thread].counter, buf[thread].uval, ++ if (config->stats) ++ printout(config, id, 0, buf[thread].counter, buf[thread].uval, + prefix, buf[thread].run, buf[thread].ena, 1.0, +- &stat_config.stats[id]); ++ &config->stats[id]); + else +- printout(id, 0, buf[thread].counter, buf[thread].uval, ++ printout(config, id, 0, buf[thread].counter, buf[thread].uval, + prefix, buf[thread].run, buf[thread].ena, 1.0, + &rt_stat); + fputc('\n', output); +@@ -1507,9 +1513,10 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data, + * Print out the results of a single counter: + * aggregated counts in system-wide mode + */ +-static void print_counter_aggr(struct perf_evsel *counter, char *prefix) ++static void print_counter_aggr(struct perf_stat_config *config, ++ struct perf_evsel *counter, char *prefix) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + double uval; + struct caggr_data cd = { .avg = 0.0 }; + +@@ -1520,7 +1527,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) + fprintf(output, "%s", prefix); + + uval = cd.avg * counter->scale; +- printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, ++ printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, + cd.avg, &rt_stat); + if (!metric_only) + fprintf(output, "\n"); +@@ -1540,9 +1547,10 @@ static void counter_cb(struct perf_evsel *counter, void *data, + * Print out the results of a single counter: + * does not use aggregated count in system-wide + */ +-static void print_counter(struct perf_evsel *counter, char *prefix) ++static void print_counter(struct perf_stat_config *config, ++ struct perf_evsel *counter, char *prefix) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + u64 ena, run, val; + double uval; + int cpu; +@@ -1560,14 +1568,15 @@ static void print_counter(struct perf_evsel *counter, char *prefix) + fprintf(output, "%s", prefix); + + uval = val * counter->scale; +- printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, ++ printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, + &rt_stat); + + fputc('\n', output); + } + } + +-static void print_no_aggr_metric(char *prefix) ++static void print_no_aggr_metric(struct perf_stat_config *config, ++ char *prefix) + { + int cpu; + int nrcpus = 0; +@@ -1580,7 +1589,7 @@ static void print_no_aggr_metric(char *prefix) + bool first = true; + + if (prefix) +- fputs(prefix, stat_config.output); ++ fputs(prefix, config->output); + evlist__for_each_entry(evsel_list, counter) { + if (is_duration_time(counter)) + continue; +@@ -1593,10 +1602,10 @@ static void print_no_aggr_metric(char *prefix) + run = perf_counts(counter->counts, cpu, 0)->run; + + uval = val * counter->scale; +- printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, ++ printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0, + &rt_stat); + } +- fputc('\n', stat_config.output); ++ fputc('\n', config->output); + } + } + +@@ -1616,25 +1625,25 @@ static const char *aggr_header_csv[] = { + [AGGR_GLOBAL] = "" + }; + +-static void print_metric_headers(const char *prefix, bool no_indent) ++static void print_metric_headers(struct perf_stat_config *config, ++ const char *prefix, bool no_indent) + { + struct perf_stat_output_ctx out; + struct perf_evsel *counter; + struct outstate os = { +- .fh = stat_config.output ++ .fh = config->output + }; + + if (prefix) +- fprintf(stat_config.output, "%s", prefix); ++ fprintf(config->output, "%s", prefix); + + if (!csv_output && !no_indent) +- fprintf(stat_config.output, "%*s", +- aggr_header_lens[stat_config.aggr_mode], ""); ++ fprintf(config->output, "%*s", ++ aggr_header_lens[config->aggr_mode], ""); + if (csv_output) { +- if (stat_config.interval) +- fputs("time,", stat_config.output); +- fputs(aggr_header_csv[stat_config.aggr_mode], +- stat_config.output); ++ if (config->interval) ++ fputs("time,", config->output); ++ fputs(aggr_header_csv[config->aggr_mode], config->output); + } + + /* Print metrics headers only */ +@@ -1653,12 +1662,13 @@ static void print_metric_headers(const char *prefix, bool no_indent) + &metric_events, + &rt_stat); + } +- fputc('\n', stat_config.output); ++ fputc('\n', config->output); + } + +-static void print_interval(char *prefix, struct timespec *ts) ++static void print_interval(struct perf_stat_config *config, ++ char *prefix, struct timespec *ts) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + static int num_print_interval; + + if (interval_clear) +@@ -1667,7 +1677,7 @@ static void print_interval(char *prefix, struct timespec *ts) + sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); + + if ((num_print_interval == 0 && !csv_output) || interval_clear) { +- switch (stat_config.aggr_mode) { ++ switch (config->aggr_mode) { + case AGGR_SOCKET: + fprintf(output, "# time socket cpus"); + if (!metric_only) +@@ -1699,14 +1709,15 @@ static void print_interval(char *prefix, struct timespec *ts) + } + + if ((num_print_interval == 0 || interval_clear) && metric_only) +- print_metric_headers(" ", true); ++ print_metric_headers(config, " ", true); + if (++num_print_interval == 25) + num_print_interval = 0; + } + +-static void print_header(int argc, const char **argv) ++static void print_header(struct perf_stat_config *config, ++ int argc, const char **argv) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + int i; + + fflush(stdout); +@@ -1774,10 +1785,10 @@ static double timeval2double(struct timeval *t) + return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; + } + +-static void print_footer(void) ++static void print_footer(struct perf_stat_config *config) + { + double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; +- FILE *output = stat_config.output; ++ FILE *output = config->output; + int n; + + if (!null_run) +@@ -1808,7 +1819,7 @@ static void print_footer(void) + fprintf(output, " %17.*f +- %.*f seconds time elapsed", + precision, avg, precision, sd); + +- print_noise_pct(sd, avg); ++ print_noise_pct(config, sd, avg); + } + fprintf(output, "\n\n"); + +@@ -1838,15 +1849,15 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + char buf[64], *prefix = NULL; + + if (interval) +- print_interval(prefix = buf, ts); ++ print_interval(config, prefix = buf, ts); + else +- print_header(argc, argv); ++ print_header(config, argc, argv); + + if (metric_only) { + static int num_print_iv; + + if (num_print_iv == 0 && !interval) +- print_metric_headers(prefix, false); ++ print_metric_headers(config, prefix, false); + if (num_print_iv++ == 25) + num_print_iv = 0; + if (config->aggr_mode == AGGR_GLOBAL && prefix) +@@ -1856,32 +1867,32 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + switch (config->aggr_mode) { + case AGGR_CORE: + case AGGR_SOCKET: +- print_aggr(prefix); ++ print_aggr(config, prefix); + break; + case AGGR_THREAD: + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; +- print_aggr_thread(counter, prefix); ++ print_aggr_thread(config, counter, prefix); + } + break; + case AGGR_GLOBAL: + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; +- print_counter_aggr(counter, prefix); ++ print_counter_aggr(config, counter, prefix); + } + if (metric_only) + fputc('\n', config->output); + break; + case AGGR_NONE: + if (metric_only) +- print_no_aggr_metric(prefix); ++ print_no_aggr_metric(config, prefix); + else { + evlist__for_each_entry(evlist, counter) { + if (is_duration_time(counter)) + continue; +- print_counter(counter, prefix); ++ print_counter(config, counter, prefix); + } + } + break; +@@ -1891,7 +1902,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + } + + if (!interval && !csv_output) +- print_footer(); ++ print_footer(config); + + fflush(config->output); + } +-- +2.27.0 + diff --git a/patches/0122-perf-stat-Pass-a-struct-perf_stat_config-argument-to.patch b/patches/0122-perf-stat-Pass-a-struct-perf_stat_config-argument-to.patch new file mode 100644 index 0000000..003489f --- /dev/null +++ b/patches/0122-perf-stat-Pass-a-struct-perf_stat_config-argument-to.patch @@ -0,0 +1,772 @@ +From 3f9d26228fa45a37759308d29e22d64330a5e17c Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:28 +0200 +Subject: [PATCH 005/201] perf stat: Pass a 'struct perf_stat_config' argument + to global print functions + +mainline inclusion +from mainline-v4.20-rc1 +commit 6ca9a082b1908ff7f8adedf08166043b83b266f6 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6ca9a082b1908ff7f8adedf08166043b83b266f6 + +---------------------------------------------------------------------- + +Add 'struct perf_stat_config' argument to the global print functions, so +that these functions can be used out of the 'perf stat' command code. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-20-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-script.c | 8 +- + tools/perf/builtin-stat.c | 74 +++++++++-------- + tools/perf/util/stat-shadow.c | 147 ++++++++++++++++++---------------- + tools/perf/util/stat.h | 8 +- + 4 files changed, 131 insertions(+), 106 deletions(-) + +diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c +index b8162ded720e..607dd95b5c34 100644 +--- a/tools/perf/builtin-script.c ++++ b/tools/perf/builtin-script.c +@@ -1548,7 +1548,8 @@ struct metric_ctx { + FILE *fp; + }; + +-static void script_print_metric(void *ctx, const char *color, ++static void script_print_metric(struct perf_stat_config *config __maybe_unused, ++ void *ctx, const char *color, + const char *fmt, + const char *unit, double val) + { +@@ -1566,7 +1567,8 @@ static void script_print_metric(void *ctx, const char *color, + fprintf(mctx->fp, " %s\n", unit); + } + +-static void script_new_line(void *ctx) ++static void script_new_line(struct perf_stat_config *config __maybe_unused, ++ void *ctx) + { + struct metric_ctx *mctx = ctx; + +@@ -1607,7 +1609,7 @@ static void perf_sample__fprint_metric(struct perf_script *script, + evsel_script(evsel)->val = val; + if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) { + for_each_group_member (ev2, evsel->leader) { +- perf_stat__print_shadow_stats(ev2, ++ perf_stat__print_shadow_stats(&stat_config, ev2, + evsel_script(ev2)->val, + sample->cpu, + &ctx, +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 267b2cc9e73a..651fef3c92de 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -832,11 +832,12 @@ static void print_noise(struct perf_stat_config *config, + print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg); + } + +-static void aggr_printout(struct perf_evsel *evsel, int id, int nr) ++static void aggr_printout(struct perf_stat_config *config, ++ struct perf_evsel *evsel, int id, int nr) + { +- switch (stat_config.aggr_mode) { ++ switch (config->aggr_mode) { + case AGGR_CORE: +- fprintf(stat_config.output, "S%d-C%*d%s%*d%s", ++ fprintf(config->output, "S%d-C%*d%s%*d%s", + cpu_map__id_to_socket(id), + csv_output ? 0 : -8, + cpu_map__id_to_cpu(id), +@@ -846,7 +847,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) + csv_sep); + break; + case AGGR_SOCKET: +- fprintf(stat_config.output, "S%*d%s%*d%s", ++ fprintf(config->output, "S%*d%s%*d%s", + csv_output ? 0 : -5, + id, + csv_sep, +@@ -855,12 +856,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) + csv_sep); + break; + case AGGR_NONE: +- fprintf(stat_config.output, "CPU%*d%s", ++ fprintf(config->output, "CPU%*d%s", + csv_output ? 0 : -4, + perf_evsel__cpus(evsel)->map[id], csv_sep); + break; + case AGGR_THREAD: +- fprintf(stat_config.output, "%*s-%*d%s", ++ fprintf(config->output, "%*s-%*d%s", + csv_output ? 0 : 16, + thread_map__comm(evsel->threads, id), + csv_output ? 0 : -8, +@@ -885,24 +886,27 @@ struct outstate { + + #define METRIC_LEN 35 + +-static void new_line_std(void *ctx) ++static void new_line_std(struct perf_stat_config *config __maybe_unused, ++ void *ctx) + { + struct outstate *os = ctx; + + os->newline = true; + } + +-static void do_new_line_std(struct outstate *os) ++static void do_new_line_std(struct perf_stat_config *config, ++ struct outstate *os) + { + fputc('\n', os->fh); + fputs(os->prefix, os->fh); +- aggr_printout(os->evsel, os->id, os->nr); +- if (stat_config.aggr_mode == AGGR_NONE) ++ aggr_printout(config, os->evsel, os->id, os->nr); ++ if (config->aggr_mode == AGGR_NONE) + fprintf(os->fh, " "); + fprintf(os->fh, " "); + } + +-static void print_metric_std(void *ctx, const char *color, const char *fmt, ++static void print_metric_std(struct perf_stat_config *config, ++ void *ctx, const char *color, const char *fmt, + const char *unit, double val) + { + struct outstate *os = ctx; +@@ -918,7 +922,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt, + } + + if (newline) +- do_new_line_std(os); ++ do_new_line_std(config, os); + + n = fprintf(out, " # "); + if (color) +@@ -928,7 +932,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt, + fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); + } + +-static void new_line_csv(void *ctx) ++static void new_line_csv(struct perf_stat_config *config, void *ctx) + { + struct outstate *os = ctx; + int i; +@@ -936,12 +940,13 @@ static void new_line_csv(void *ctx) + fputc('\n', os->fh); + if (os->prefix) + fprintf(os->fh, "%s%s", os->prefix, csv_sep); +- aggr_printout(os->evsel, os->id, os->nr); ++ aggr_printout(config, os->evsel, os->id, os->nr); + for (i = 0; i < os->nfields; i++) + fputs(csv_sep, os->fh); + } + +-static void print_metric_csv(void *ctx, ++static void print_metric_csv(struct perf_stat_config *config __maybe_unused, ++ void *ctx, + const char *color __maybe_unused, + const char *fmt, const char *unit, double val) + { +@@ -988,7 +993,8 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel, + return unit; + } + +-static void print_metric_only(void *ctx, const char *color, const char *fmt, ++static void print_metric_only(struct perf_stat_config *config __maybe_unused, ++ void *ctx, const char *color, const char *fmt, + const char *unit, double val) + { + struct outstate *os = ctx; +@@ -1009,7 +1015,8 @@ static void print_metric_only(void *ctx, const char *color, const char *fmt, + fprintf(out, "%*s ", mlen, str); + } + +-static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, ++static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, ++ void *ctx, const char *color __maybe_unused, + const char *fmt, + const char *unit, double val) + { +@@ -1029,11 +1036,13 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, + fprintf(out, "%s%s", vals, csv_sep); + } + +-static void new_line_metric(void *ctx __maybe_unused) ++static void new_line_metric(struct perf_stat_config *config __maybe_unused, ++ void *ctx __maybe_unused) + { + } + +-static void print_metric_header(void *ctx, const char *color __maybe_unused, ++static void print_metric_header(struct perf_stat_config *config __maybe_unused, ++ void *ctx, const char *color __maybe_unused, + const char *fmt __maybe_unused, + const char *unit, double val __maybe_unused) + { +@@ -1071,9 +1080,10 @@ static int first_shadow_cpu(struct perf_evsel *evsel, int id) + return 0; + } + +-static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) ++static void abs_printout(struct perf_stat_config *config, ++ int id, int nr, struct perf_evsel *evsel, double avg) + { +- FILE *output = stat_config.output; ++ FILE *output = config->output; + double sc = evsel->scale; + const char *fmt; + +@@ -1086,7 +1096,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) + fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; + } + +- aggr_printout(evsel, id, nr); ++ aggr_printout(config, evsel, id, nr); + + fprintf(output, fmt, avg, csv_sep); + +@@ -1139,7 +1149,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, + .evsel = counter, + }; + print_metric_t pm = print_metric_std; +- void (*nl)(void *); ++ new_line_t nl; + + if (metric_only) { + nl = new_line_metric; +@@ -1168,10 +1178,10 @@ static void printout(struct perf_stat_config *config, int id, int nr, + } + if (run == 0 || ena == 0 || counter->counts->scaled == -1) { + if (metric_only) { +- pm(&os, NULL, "", "", 0); ++ pm(config, &os, NULL, "", "", 0); + return; + } +- aggr_printout(counter, id, nr); ++ aggr_printout(config, counter, id, nr); + + fprintf(config->output, "%*s%s", + csv_output ? 0 : 18, +@@ -1197,16 +1207,16 @@ static void printout(struct perf_stat_config *config, int id, int nr, + csv_sep, counter->cgrp->name); + + if (!csv_output) +- pm(&os, NULL, NULL, "", 0); ++ pm(config, &os, NULL, NULL, "", 0); + print_noise(config, counter, noise); + print_running(config, run, ena); + if (csv_output) +- pm(&os, NULL, NULL, "", 0); ++ pm(config, &os, NULL, NULL, "", 0); + return; + } + + if (!metric_only) +- abs_printout(id, nr, counter, uval); ++ abs_printout(config, id, nr, counter, uval); + + out.print_metric = pm; + out.new_line = nl; +@@ -1218,7 +1228,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, + print_running(config, run, ena); + } + +- perf_stat__print_shadow_stats(counter, uval, ++ perf_stat__print_shadow_stats(config, counter, uval, + first_shadow_cpu(counter, id), + &out, &metric_events, st); + if (!csv_output && !metric_only) { +@@ -1390,7 +1400,7 @@ static void print_aggr(struct perf_stat_config *config, + val = ad.val; + if (first && metric_only) { + first = false; +- aggr_printout(counter, id, nr); ++ aggr_printout(config, counter, id, nr); + } + if (prefix && !metric_only) + fprintf(output, "%s", prefix); +@@ -1594,7 +1604,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config, + if (is_duration_time(counter)) + continue; + if (first) { +- aggr_printout(counter, cpu, 0); ++ aggr_printout(config, counter, cpu, 0); + first = false; + } + val = perf_counts(counter->counts, cpu, 0)->val; +@@ -1656,7 +1666,7 @@ static void print_metric_headers(struct perf_stat_config *config, + out.new_line = new_line_metric; + out.force_header = true; + os.evsel = counter; +- perf_stat__print_shadow_stats(counter, 0, ++ perf_stat__print_shadow_stats(config, counter, 0, + 0, + &out, + &metric_events, +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 59475287e2e1..93c075ddc717 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -411,7 +411,8 @@ static double runtime_stat_n(struct runtime_stat *st, + return v->stats.n; + } + +-static void print_stalled_cycles_frontend(int cpu, ++static void print_stalled_cycles_frontend(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, double avg, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +@@ -428,13 +429,14 @@ static void print_stalled_cycles_frontend(int cpu, + color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); + + if (ratio) +- out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle", ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle", + ratio); + else +- out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0); ++ out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0); + } + +-static void print_stalled_cycles_backend(int cpu, ++static void print_stalled_cycles_backend(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, double avg, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +@@ -450,10 +452,11 @@ static void print_stalled_cycles_backend(int cpu, + + color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); + +- out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); + } + +-static void print_branch_misses(int cpu, ++static void print_branch_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -470,10 +473,11 @@ static void print_branch_misses(int cpu, + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); + +- out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio); + } + +-static void print_l1_dcache_misses(int cpu, ++static void print_l1_dcache_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -491,10 +495,11 @@ static void print_l1_dcache_misses(int cpu, + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); + +- out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); + } + +-static void print_l1_icache_misses(int cpu, ++static void print_l1_icache_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -511,10 +516,11 @@ static void print_l1_icache_misses(int cpu, + ratio = avg / total * 100.0; + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); +- out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); + } + +-static void print_dtlb_cache_misses(int cpu, ++static void print_dtlb_cache_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -530,10 +536,11 @@ static void print_dtlb_cache_misses(int cpu, + ratio = avg / total * 100.0; + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); +- out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); + } + +-static void print_itlb_cache_misses(int cpu, ++static void print_itlb_cache_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -549,10 +556,11 @@ static void print_itlb_cache_misses(int cpu, + ratio = avg / total * 100.0; + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); +- out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); + } + +-static void print_ll_cache_misses(int cpu, ++static void print_ll_cache_misses(struct perf_stat_config *config, ++ int cpu, + struct perf_evsel *evsel, + double avg, + struct perf_stat_output_ctx *out, +@@ -568,7 +576,7 @@ static void print_ll_cache_misses(int cpu, + ratio = avg / total * 100.0; + + color = get_ratio_color(GRC_CACHE_MISSES, ratio); +- out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); ++ out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); + } + + /* +@@ -675,7 +683,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st) + return sanitize_val(1.0 - sum); + } + +-static void print_smi_cost(int cpu, struct perf_evsel *evsel, ++static void print_smi_cost(struct perf_stat_config *config, ++ int cpu, struct perf_evsel *evsel, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) + { +@@ -695,11 +704,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel, + + if (cost > 10) + color = PERF_COLOR_RED; +- out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost); +- out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num); ++ out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost); ++ out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); + } + +-static void generic_metric(const char *metric_expr, ++static void generic_metric(struct perf_stat_config *config, ++ const char *metric_expr, + struct perf_evsel **metric_events, + char *name, + const char *metric_name, +@@ -738,20 +748,21 @@ static void generic_metric(const char *metric_expr, + const char *p = metric_expr; + + if (expr__parse(&ratio, &pctx, &p) == 0) +- print_metric(ctxp, NULL, "%8.1f", ++ print_metric(config, ctxp, NULL, "%8.1f", + metric_name ? + metric_name : + out->force_header ? name : "", + ratio); + else +- print_metric(ctxp, NULL, NULL, ++ print_metric(config, ctxp, NULL, NULL, + out->force_header ? + (metric_name ? metric_name : name) : "", 0); + } else +- print_metric(ctxp, NULL, NULL, "", 0); ++ print_metric(config, ctxp, NULL, NULL, "", 0); + } + +-void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ++void perf_stat__print_shadow_stats(struct perf_stat_config *config, ++ struct perf_evsel *evsel, + double avg, int cpu, + struct perf_stat_output_ctx *out, + struct rblist *metric_events, +@@ -770,10 +781,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + + if (total) { + ratio = avg / total; +- print_metric(ctxp, NULL, "%7.2f ", ++ print_metric(config, ctxp, NULL, "%7.2f ", + "insn per cycle", ratio); + } else { +- print_metric(ctxp, NULL, NULL, "insn per cycle", 0); ++ print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0); + } + + total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT, +@@ -784,20 +795,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ctx, cpu)); + + if (total && avg) { +- out->new_line(ctxp); ++ out->new_line(config, ctxp); + ratio = total / avg; +- print_metric(ctxp, NULL, "%7.2f ", ++ print_metric(config, ctxp, NULL, "%7.2f ", + "stalled cycles per insn", + ratio); + } else if (have_frontend_stalled) { +- print_metric(ctxp, NULL, NULL, ++ print_metric(config, ctxp, NULL, NULL, + "stalled cycles per insn", 0); + } + } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) { + if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0) +- print_branch_misses(cpu, evsel, avg, out, st); ++ print_branch_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all branches", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all branches", 0); + } else if ( + evsel->attr.type == PERF_TYPE_HW_CACHE && + evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | +@@ -805,9 +816,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { + + if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0) +- print_l1_dcache_misses(cpu, evsel, avg, out, st); ++ print_l1_dcache_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0); + } else if ( + evsel->attr.type == PERF_TYPE_HW_CACHE && + evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | +@@ -815,9 +826,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { + + if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0) +- print_l1_icache_misses(cpu, evsel, avg, out, st); ++ print_l1_icache_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0); + } else if ( + evsel->attr.type == PERF_TYPE_HW_CACHE && + evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | +@@ -825,9 +836,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { + + if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0) +- print_dtlb_cache_misses(cpu, evsel, avg, out, st); ++ print_dtlb_cache_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0); + } else if ( + evsel->attr.type == PERF_TYPE_HW_CACHE && + evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | +@@ -835,9 +846,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { + + if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0) +- print_itlb_cache_misses(cpu, evsel, avg, out, st); ++ print_itlb_cache_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0); + } else if ( + evsel->attr.type == PERF_TYPE_HW_CACHE && + evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | +@@ -845,9 +856,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { + + if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0) +- print_ll_cache_misses(cpu, evsel, avg, out, st); ++ print_ll_cache_misses(config, cpu, evsel, avg, out, st); + else +- print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0); + } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) { + total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu); + +@@ -855,32 +866,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ratio = avg * 100 / total; + + if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0) +- print_metric(ctxp, NULL, "%8.3f %%", ++ print_metric(config, ctxp, NULL, "%8.3f %%", + "of all cache refs", ratio); + else +- print_metric(ctxp, NULL, NULL, "of all cache refs", 0); ++ print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0); + } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { +- print_stalled_cycles_frontend(cpu, evsel, avg, out, st); ++ print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st); + } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { +- print_stalled_cycles_backend(cpu, evsel, avg, out, st); ++ print_stalled_cycles_backend(config, cpu, evsel, avg, out, st); + } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { + total = runtime_stat_avg(st, STAT_NSECS, 0, cpu); + + if (total) { + ratio = avg / total; +- print_metric(ctxp, NULL, "%8.3f", "GHz", ratio); ++ print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio); + } else { +- print_metric(ctxp, NULL, NULL, "Ghz", 0); ++ print_metric(config, ctxp, NULL, NULL, "Ghz", 0); + } + } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) { + total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); + + if (total) +- print_metric(ctxp, NULL, ++ print_metric(config, ctxp, NULL, + "%7.2f%%", "transactional cycles", + 100.0 * (avg / total)); + else +- print_metric(ctxp, NULL, NULL, "transactional cycles", ++ print_metric(config, ctxp, NULL, NULL, "transactional cycles", + 0); + } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) { + total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); +@@ -889,10 +900,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + if (total2 < avg) + total2 = avg; + if (total) +- print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles", ++ print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles", + 100.0 * ((total2-avg) / total)); + else +- print_metric(ctxp, NULL, NULL, "aborted cycles", 0); ++ print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0); + } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) { + total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, + ctx, cpu); +@@ -901,10 +912,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + ratio = total / avg; + + if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0) +- print_metric(ctxp, NULL, "%8.0f", ++ print_metric(config, ctxp, NULL, "%8.0f", + "cycles / transaction", ratio); + else +- print_metric(ctxp, NULL, NULL, "cycles / transaction", ++ print_metric(config, ctxp, NULL, NULL, "cycles / transaction", + 0); + } else if (perf_stat_evsel__is(evsel, ELISION_START)) { + total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, +@@ -913,33 +924,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + if (avg) + ratio = total / avg; + +- print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); ++ print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio); + } else if (perf_evsel__is_clock(evsel)) { + if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) +- print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", ++ print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized", + avg / (ratio * evsel->scale)); + else +- print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); ++ print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0); + } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) { + double fe_bound = td_fe_bound(ctx, cpu, st); + + if (fe_bound > 0.2) + color = PERF_COLOR_RED; +- print_metric(ctxp, color, "%8.1f%%", "frontend bound", ++ print_metric(config, ctxp, color, "%8.1f%%", "frontend bound", + fe_bound * 100.); + } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) { + double retiring = td_retiring(ctx, cpu, st); + + if (retiring > 0.7) + color = PERF_COLOR_GREEN; +- print_metric(ctxp, color, "%8.1f%%", "retiring", ++ print_metric(config, ctxp, color, "%8.1f%%", "retiring", + retiring * 100.); + } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) { + double bad_spec = td_bad_spec(ctx, cpu, st); + + if (bad_spec > 0.1) + color = PERF_COLOR_RED; +- print_metric(ctxp, color, "%8.1f%%", "bad speculation", ++ print_metric(config, ctxp, color, "%8.1f%%", "bad speculation", + bad_spec * 100.); + } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) { + double be_bound = td_be_bound(ctx, cpu, st); +@@ -956,12 +967,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + if (be_bound > 0.2) + color = PERF_COLOR_RED; + if (td_total_slots(ctx, cpu, st) > 0) +- print_metric(ctxp, color, "%8.1f%%", name, ++ print_metric(config, ctxp, color, "%8.1f%%", name, + be_bound * 100.); + else +- print_metric(ctxp, NULL, NULL, name, 0); ++ print_metric(config, ctxp, NULL, NULL, name, 0); + } else if (evsel->metric_expr) { +- generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name, ++ generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, + evsel->metric_name, avg, cpu, out, st); + } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { + char unit = 'M'; +@@ -976,9 +987,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + unit = 'K'; + } + snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); +- print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio); ++ print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio); + } else if (perf_stat_evsel__is(evsel, SMI_NUM)) { +- print_smi_cost(cpu, evsel, out, st); ++ print_smi_cost(config, cpu, evsel, out, st); + } else { + num = 0; + } +@@ -988,12 +999,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, + + list_for_each_entry (mexp, &me->head, nd) { + if (num++ > 0) +- out->new_line(ctxp); +- generic_metric(mexp->metric_expr, mexp->metric_events, ++ out->new_line(config, ctxp); ++ generic_metric(config, mexp->metric_expr, mexp->metric_events, + evsel->name, mexp->metric_name, + avg, cpu, out, st); + } + } + if (num == 0) +- print_metric(ctxp, NULL, NULL, NULL, 0); ++ print_metric(config, ctxp, NULL, NULL, NULL, 0); + } +diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h +index e19abb1635c4..c223bbb81d13 100644 +--- a/tools/perf/util/stat.h ++++ b/tools/perf/util/stat.h +@@ -130,9 +130,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel, + extern struct runtime_stat rt_stat; + extern struct stats walltime_nsecs_stats; + +-typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit, ++typedef void (*print_metric_t)(struct perf_stat_config *config, ++ void *ctx, const char *color, const char *unit, + const char *fmt, double val); +-typedef void (*new_line_t )(void *ctx); ++typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx); + + void runtime_stat__init(struct runtime_stat *st); + void runtime_stat__exit(struct runtime_stat *st); +@@ -148,7 +149,8 @@ struct perf_stat_output_ctx { + bool force_header; + }; + +-void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ++void perf_stat__print_shadow_stats(struct perf_stat_config *config, ++ struct perf_evsel *evsel, + double avg, int cpu, + struct perf_stat_output_ctx *out, + struct rblist *metric_events, +-- +2.27.0 + diff --git a/patches/0123-perf-stat-Move-metric_events-to-struct-perf_stat_con.patch b/patches/0123-perf-stat-Move-metric_events-to-struct-perf_stat_con.patch new file mode 100644 index 0000000..f0b177c --- /dev/null +++ b/patches/0123-perf-stat-Move-metric_events-to-struct-perf_stat_con.patch @@ -0,0 +1,117 @@ +From 4eb984aff402a0421d7656d7c81d3c83d82521d3 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 30 Aug 2018 08:32:51 +0200 +Subject: [PATCH 006/201] perf stat: Move 'metric_events' to 'struct + perf_stat_config' + +mainline inclusion +from mainline-v4.20-rc1 +commit d0192fdba09a8901db133fe5a1fcd22d40fcf545 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0192fdba09a8901db133fe5a1fcd22d40fcf545 + +-------------------------------------------------------------------- + +Move the static variable 'metric_events' to 'struct perf_stat_config', +so that it can be passed around and used outside 'perf stat' command. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: David Ahern +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20180830063252.23729-43-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflict: + tools/perf/builtin-stat.c + tools/perf/util/stat.h +--- + tools/perf/builtin-stat.c | 10 ++++------ + tools/perf/util/stat.h | 17 +++++++++-------- + 2 files changed, 13 insertions(+), 14 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 651fef3c92de..da1e60029ff1 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -137,8 +137,6 @@ static const char *smi_cost_attrs = { + + static struct perf_evlist *evsel_list; + +-static struct rblist metric_events; +- + static struct target target = { + .uid = UINT_MAX, + }; +@@ -1230,7 +1228,7 @@ static void printout(struct perf_stat_config *config, int id, int nr, + + perf_stat__print_shadow_stats(config, counter, uval, + first_shadow_cpu(counter, id), +- &out, &metric_events, st); ++ &out, &config->metric_events, st); + if (!csv_output && !metric_only) { + print_noise(config, counter, noise); + print_running(config, run, ena); +@@ -1669,7 +1667,7 @@ static void print_metric_headers(struct perf_stat_config *config, + perf_stat__print_shadow_stats(config, counter, 0, + 0, + &out, +- &metric_events, ++ &config->metric_events, + &rt_stat); + } + fputc('\n', config->output); +@@ -1989,7 +1987,7 @@ static int parse_metric_groups(const struct option *opt, + const char *str, + int unset __maybe_unused) + { +- return metricgroup__parse_groups(opt, str, &metric_events); ++ return metricgroup__parse_groups(opt, str, &stat_config.metric_events); + } + + static struct option stat_options[] = { +@@ -2445,7 +2443,7 @@ static int add_default_attributes(void) + struct option opt = { .value = &evsel_list }; + + return metricgroup__parse_groups(&opt, "transaction", +- &metric_events); ++ &stat_config.metric_events); + } + + if (pmu_have_event("cpu", "cycles-ct") && +diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h +index c223bbb81d13..8a7d8425acf8 100644 +--- a/tools/perf/util/stat.h ++++ b/tools/perf/util/stat.h +@@ -85,14 +85,15 @@ struct runtime_stat { + }; + + struct perf_stat_config { +- enum aggr_mode aggr_mode; +- bool scale; +- FILE *output; +- unsigned int interval; +- unsigned int timeout; +- int times; +- struct runtime_stat *stats; +- int stats_num; ++ enum aggr_mode aggr_mode; ++ bool scale; ++ FILE *output; ++ unsigned int interval; ++ unsigned int timeout; ++ int times; ++ struct runtime_stat *stats; ++ int stats_num; ++ struct rblist metric_events; + }; + + void update_stats(struct stats *stats, u64 val); +-- +2.27.0 + diff --git a/patches/0124-perf-list-Display-metric-expressions-for-details-opt.patch b/patches/0124-perf-list-Display-metric-expressions-for-details-opt.patch new file mode 100644 index 0000000..aca0507 --- /dev/null +++ b/patches/0124-perf-list-Display-metric-expressions-for-details-opt.patch @@ -0,0 +1,145 @@ +From 16055ffe7f4937ac992b9e84f120ad3128b23352 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Wed, 13 Feb 2019 13:32:41 +0100 +Subject: [PATCH 007/201] perf list: Display metric expressions for --details + option + +mainline inclusion +from mainline-v5.1-rc1 +commit 33bbc571ed79cace481fae4031b80a51d93ae997 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=33bbc571ed79cace481fae4031b80a51d93ae997 + +------------------------------------------------------------ + +Display metric expression itself when --details is specified. + +Current list with no details: + + # perf list metrics + ... + TopDownL1: + IPC + [Instructions Per Cycle (per logical thread)] + SLOTS + [Total issue-pipeline slots] + ... + +Detailed output with metric formula: + + # perf list --details metrics + ... + TopDownL1: + IPC + [Instructions Per Cycle (per logical thread)] + [inst_retired.any / cpu_clk_unhalted.thread] + SLOTS + [Total issue-pipeline slots] + [4*(( cpu_clk_unhalted.thread_any / 2 ) if #smt_on else cycles)] + ... + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20190213123246.4015-6-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-list.c | 8 ++++---- + tools/perf/util/metricgroup.c | 8 +++++++- + tools/perf/util/metricgroup.h | 3 ++- + tools/perf/util/parse-events.c | 2 +- + 4 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c +index ead221e49f00..c9f98d00c0e9 100644 +--- a/tools/perf/builtin-list.c ++++ b/tools/perf/builtin-list.c +@@ -82,9 +82,9 @@ int cmd_list(int argc, const char **argv) + else if (strcmp(argv[i], "sdt") == 0) + print_sdt_events(NULL, NULL, raw_dump); + else if (strcmp(argv[i], "metric") == 0) +- metricgroup__print(true, false, NULL, raw_dump); ++ metricgroup__print(true, false, NULL, raw_dump, details_flag); + else if (strcmp(argv[i], "metricgroup") == 0) +- metricgroup__print(false, true, NULL, raw_dump); ++ metricgroup__print(false, true, NULL, raw_dump, details_flag); + else if ((sep = strchr(argv[i], ':')) != NULL) { + int sep_idx; + +@@ -102,7 +102,7 @@ int cmd_list(int argc, const char **argv) + s[sep_idx] = '\0'; + print_tracepoint_events(s, s + sep_idx + 1, raw_dump); + print_sdt_events(s, s + sep_idx + 1, raw_dump); +- metricgroup__print(true, true, s, raw_dump); ++ metricgroup__print(true, true, s, raw_dump, details_flag); + free(s); + } else { + if (asprintf(&s, "*%s*", argv[i]) < 0) { +@@ -119,7 +119,7 @@ int cmd_list(int argc, const char **argv) + details_flag); + print_tracepoint_events(NULL, s, raw_dump); + print_sdt_events(NULL, s, raw_dump); +- metricgroup__print(true, true, NULL, raw_dump); ++ metricgroup__print(true, true, NULL, raw_dump, details_flag); + free(s); + } + } +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 6dcc6e1182a5..27552a0b990a 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -296,7 +296,7 @@ static void metricgroup__print_strlist(struct strlist *metrics, bool raw) + } + + void metricgroup__print(bool metrics, bool metricgroups, char *filter, +- bool raw) ++ bool raw, bool details) + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); + struct pmu_event *pe; +@@ -355,6 +355,12 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + if (asprintf(&s, "%s\n%*s%s]", + pe->metric_name, 8, "[", pe->desc) < 0) + return; ++ ++ if (details) { ++ if (asprintf(&s, "%s\n%*s%s]", ++ s, 8, "[", pe->metric_expr) < 0) ++ return; ++ } + } + + if (!s) +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 8a155dba0581..5c52097a5c63 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -27,6 +27,7 @@ int metricgroup__parse_groups(const struct option *opt, + const char *str, + struct rblist *metric_events); + +-void metricgroup__print(bool metrics, bool groups, char *filter, bool raw); ++void metricgroup__print(bool metrics, bool groups, char *filter, ++ bool raw, bool details); + bool metricgroup__has_metric(const char *metric); + #endif +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 0eff0c3ba9ee..f5a7d42b0928 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -2545,7 +2545,7 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag, + + print_sdt_events(NULL, NULL, name_only); + +- metricgroup__print(true, true, NULL, name_only); ++ metricgroup__print(true, true, NULL, name_only, details_flag); + } + + int parse_events__is_hardcoded_term(struct parse_events_term *term) +-- +2.27.0 + diff --git a/patches/0125-perf-tools-Fix-legacy-events-symbol-separator-parsin.patch b/patches/0125-perf-tools-Fix-legacy-events-symbol-separator-parsin.patch new file mode 100644 index 0000000..6ee5209 --- /dev/null +++ b/patches/0125-perf-tools-Fix-legacy-events-symbol-separator-parsin.patch @@ -0,0 +1,112 @@ +From 8d49212ae241e5352ea7fca8a14be4a34da70060 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Wed, 13 Feb 2019 13:32:40 +0100 +Subject: [PATCH 008/201] perf tools: Fix legacy events symbol separator + parsing + +mainline inclusion +from mainline-v5.1-rc1 +commit 714a92d83fd1e20461f53549cfbee77b20be5032 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=714a92d83fd1e20461f53549cfbee77b20be5032 + +----------------------------------------------------------------- + +Fixing legacy symbol events parsing. We can't support single slash +separator, like 'cycles/u', because it conflicts with non empty terms, +like 'cycles/period/u'. + +Keeping only '//' and ':' separator for these events: + cycles//u + cycles:k + +And removing '/' separator support, which is not working +anymore. Also adding automated tests for above events. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lkml.kernel.org/r/20190213123246.4015-5-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-events.c | 30 ++++++++++++++++++++++++++++++ + tools/perf/util/parse-events.y | 4 ++-- + 2 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c +index 532c95e8fa6b..8f3c80e13584 100644 +--- a/tools/perf/tests/parse-events.c ++++ b/tools/perf/tests/parse-events.c +@@ -1356,6 +1356,26 @@ static int test__checkevent_complex_name(struct perf_evlist *evlist) + return 0; + } + ++static int test__sym_event_slash(struct perf_evlist *evlist) ++{ ++ struct perf_evsel *evsel = perf_evlist__first(evlist); ++ ++ TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); ++ TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); ++ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); ++ return 0; ++} ++ ++static int test__sym_event_dc(struct perf_evlist *evlist) ++{ ++ struct perf_evsel *evsel = perf_evlist__first(evlist); ++ ++ TEST_ASSERT_VAL("wrong type", evsel->attr.type == PERF_TYPE_HARDWARE); ++ TEST_ASSERT_VAL("wrong config", evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES); ++ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); ++ return 0; ++} ++ + static int count_tracepoints(void) + { + struct dirent *events_ent; +@@ -1697,6 +1717,16 @@ static struct evlist_test test__events[] = { + .name = "cycles/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks'/Duk", + .check = test__checkevent_complex_name, + .id = 53 ++ }, ++ { ++ .name = "cycles//u", ++ .check = test__sym_event_slash, ++ .id = 54, ++ }, ++ { ++ .name = "cycles:k", ++ .check = test__sym_event_dc, ++ .id = 55, + } + }; + +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index 8d7578be708a..5d5413c21b64 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -311,7 +311,7 @@ value_sym '/' event_config '/' + $$ = list; + } + | +-value_sym sep_slash_dc ++value_sym sep_slash_slash_dc + { + struct list_head *list; + int type = $1 >> 16; +@@ -702,7 +702,7 @@ PE_VALUE PE_ARRAY_RANGE PE_VALUE + + sep_dc: ':' | + +-sep_slash_dc: '/' | ':' | ++sep_slash_slash_dc: '/' '/' | ':' | + + %% + +-- +2.27.0 + diff --git a/patches/0126-perf-stat-Revert-checks-for-duration_time.patch b/patches/0126-perf-stat-Revert-checks-for-duration_time.patch new file mode 100644 index 0000000..e8eaa3b --- /dev/null +++ b/patches/0126-perf-stat-Revert-checks-for-duration_time.patch @@ -0,0 +1,105 @@ +From 744525c9170deae41ba87831a8288f84041b1625 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Tue, 26 Mar 2019 15:18:20 -0700 +Subject: [PATCH 009/201] perf stat: Revert checks for duration_time + +mainline inclusion +from mainline-v5.2-rc1 +commit c2b3c170db610896e4e633cba2135045333811c2 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c2b3c170db610896e4e633cba2135045333811c2 + +---------------------------------------------------------------------- + +This reverts e864c5ca145e ("perf stat: Hide internal duration_time +counter") but doing it manually since the code has now moved to a +different file. + +The next patch will properly implement duration_time as a full event, so +no need to hide it anymore. + +Signed-off-by: Andi Kleen +Acked-by: Jiri Olsa +Link: http://lkml.kernel.org/r/20190326221823.11518-2-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/builtin-stat.c +--- + tools/perf/builtin-stat.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index da1e60029ff1..e45fc66426e2 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -206,11 +206,6 @@ static struct perf_stat_config stat_config = { + .scale = true, + }; + +-static bool is_duration_time(struct perf_evsel *evsel) +-{ +- return !strcmp(evsel->name, "duration_time"); +-} +- + static inline void diff_timespec(struct timespec *r, struct timespec *a, + struct timespec *b) + { +@@ -1385,8 +1380,6 @@ static void print_aggr(struct perf_stat_config *config, + ad.id = id = aggr_map->map[s]; + first = true; + evlist__for_each_entry(evsel_list, counter) { +- if (is_duration_time(counter)) +- continue; + + ad.val = ad.ena = ad.run = 0; + ad.nr = 0; +@@ -1599,8 +1592,6 @@ static void print_no_aggr_metric(struct perf_stat_config *config, + if (prefix) + fputs(prefix, config->output); + evlist__for_each_entry(evsel_list, counter) { +- if (is_duration_time(counter)) +- continue; + if (first) { + aggr_printout(config, counter, cpu, 0); + first = false; +@@ -1656,8 +1647,6 @@ static void print_metric_headers(struct perf_stat_config *config, + + /* Print metrics headers only */ + evlist__for_each_entry(evsel_list, counter) { +- if (is_duration_time(counter)) +- continue; + os.evsel = counter; + out.ctx = &os; + out.print_metric = print_metric_header; +@@ -1879,15 +1868,11 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + break; + case AGGR_THREAD: + evlist__for_each_entry(evlist, counter) { +- if (is_duration_time(counter)) +- continue; + print_aggr_thread(config, counter, prefix); + } + break; + case AGGR_GLOBAL: + evlist__for_each_entry(evlist, counter) { +- if (is_duration_time(counter)) +- continue; + print_counter_aggr(config, counter, prefix); + } + if (metric_only) +@@ -1898,8 +1883,6 @@ perf_evlist__print_counters(struct perf_evlist *evlist, + print_no_aggr_metric(config, prefix); + else { + evlist__for_each_entry(evlist, counter) { +- if (is_duration_time(counter)) +- continue; + print_counter(config, counter, prefix); + } + } +-- +2.27.0 + diff --git a/patches/0127-perf-stat-Implement-duration_time-as-a-proper-event.patch b/patches/0127-perf-stat-Implement-duration_time-as-a-proper-event.patch new file mode 100644 index 0000000..237d7f4 --- /dev/null +++ b/patches/0127-perf-stat-Implement-duration_time-as-a-proper-event.patch @@ -0,0 +1,343 @@ +From 4de09fdfa20b9de2c79c9b370dee3771e104cbe8 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Tue, 26 Mar 2019 15:18:21 -0700 +Subject: [PATCH 010/201] perf stat: Implement duration_time as a proper event + +mainline inclusion +from mainline-v5.2-rc1 +commit f0fbb114e3025f3f737a1e1c5c39c5b2b2e671bd +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f0fbb114e3025f3f737a1e1c5c39c5b2b2e671bd + +---------------------------------------------------------------------- + +The perf metric expression use 'duration_time' internally to normalize +events. Normal 'perf stat' without -x also prints the duration time. +But when using -x, the interval is not output anywhere, which is +inconvenient for any post processing which often wants to normalize +values to time. + +So implement 'duration_time' as a proper perf event that can be +specified explicitely with -e. + +The previous implementation of 'duration_time' only worked for metric +processing. This adds the concept of a tool event that is handled by the +tool. On the kernel level it is still mapped to the dummy software +event, but the values are not read anymore, but instead computed by the +tool. + +Add proper plumbing to handle this in the event parser, and display it +in 'perf stat'. We don't want 'duration_time' to be added up, so it's +only printed for the first CPU. + +% perf stat -e duration_time,cycles true + + Performance counter stats for 'true': + + 555,476 ns duration_time + 771,958 cycles + + 0.000555476 seconds time elapsed + + 0.000644000 seconds user + 0.000000000 seconds sys + +Signed-off-by: Andi Kleen +Acked-by: Jiri Olsa +Link: http://lkml.kernel.org/r/20190326221823.11518-3-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflict: + tools/perf/util/evsel.h +--- + tools/perf/builtin-stat.c | 28 ++++++++++++++++++------- + tools/perf/util/evsel.h | 6 ++++++ + tools/perf/util/parse-events.c | 38 +++++++++++++++++++++++++++++----- + tools/perf/util/parse-events.h | 4 ++++ + tools/perf/util/parse-events.l | 11 +++++++++- + tools/perf/util/parse-events.y | 12 +++++++++++ + 6 files changed, 86 insertions(+), 13 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index e45fc66426e2..c96c0715171f 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -325,11 +325,25 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, + process_synthesized_event, NULL); + } + ++static int read_single_counter(struct perf_evsel *counter, int cpu, ++ int thread, struct timespec *rs) ++{ ++ if (counter->tool_event == PERF_TOOL_DURATION_TIME) { ++ u64 val = rs->tv_nsec + rs->tv_sec*1000000000ULL; ++ struct perf_counts_values *count = ++ perf_counts(counter->counts, cpu, thread); ++ count->ena = count->run = val; ++ count->val = val; ++ return 0; ++ } ++ return perf_evsel__read_counter(counter, cpu, thread); ++} ++ + /* + * Read out the results of a single counter: + * do not aggregate counts across CPUs in system-wide mode + */ +-static int read_counter(struct perf_evsel *counter) ++static int read_counter(struct perf_evsel *counter, struct timespec *rs) + { + int nthreads = thread_map__nr(evsel_list->threads); + int ncpus, cpu, thread; +@@ -356,7 +370,7 @@ static int read_counter(struct perf_evsel *counter) + * (via perf_evsel__read_counter) and sets threir count->loaded. + */ + if (!count->loaded && +- perf_evsel__read_counter(counter, cpu, thread)) { ++ read_single_counter(counter, cpu, thread, rs)) { + counter->counts->scaled = -1; + perf_counts(counter->counts, cpu, thread)->ena = 0; + perf_counts(counter->counts, cpu, thread)->run = 0; +@@ -385,13 +399,13 @@ static int read_counter(struct perf_evsel *counter) + return 0; + } + +-static void read_counters(void) ++static void read_counters(struct timespec *rs) + { + struct perf_evsel *counter; + int ret; + + evlist__for_each_entry(evsel_list, counter) { +- ret = read_counter(counter); ++ ret = read_counter(counter, rs); + if (ret) + pr_debug("failed to read counter %s\n", counter->name); + +@@ -404,11 +418,11 @@ static void process_interval(void) + { + struct timespec ts, rs; + +- read_counters(); +- + clock_gettime(CLOCK_MONOTONIC, &ts); + diff_timespec(&rs, &ts, &ref_time); + ++ read_counters(&rs); ++ + if (STAT_RECORD) { + if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL)) + pr_err("failed to write stat round event\n"); +@@ -756,7 +770,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + * avoid arbitrary skew, we must read all counters before closing any + * group leaders. + */ +- read_counters(); ++ read_counters(&(struct timespec) { .tv_nsec = t1-t0 }); + perf_evlist__close(evsel_list); + + return WEXITSTATUS(status); +diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h +index feec6bf22a40..dab3930e2a8c 100644 +--- a/tools/perf/util/evsel.h ++++ b/tools/perf/util/evsel.h +@@ -71,6 +71,11 @@ struct perf_evsel_config_term { + + struct perf_stat_evsel; + ++enum perf_tool_event { ++ PERF_TOOL_NONE = 0, ++ PERF_TOOL_DURATION_TIME = 1, ++}; ++ + /** struct perf_evsel - event selector + * + * @evlist - evlist this evsel is in, if it is in one. +@@ -115,6 +120,7 @@ struct perf_evsel { + unsigned int sample_size; + int id_pos; + int is_pos; ++ enum perf_tool_event tool_event; + bool uniquified_name; + bool snapshot; + bool supported; +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index f5a7d42b0928..36d0851c452b 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -317,10 +317,12 @@ static struct perf_evsel * + __add_event(struct list_head *list, int *idx, + struct perf_event_attr *attr, + char *name, struct perf_pmu *pmu, +- struct list_head *config_terms, bool auto_merge_stats) ++ struct list_head *config_terms, bool auto_merge_stats, ++ const char *cpu_list) + { + struct perf_evsel *evsel; +- struct cpu_map *cpus = pmu ? pmu->cpus : NULL; ++ struct cpu_map *cpus = pmu ? pmu->cpus : ++ cpu_list ? cpu_map__new(cpu_list) : NULL; + + event_attr_init(attr); + +@@ -348,7 +350,25 @@ static int add_event(struct list_head *list, int *idx, + struct perf_event_attr *attr, char *name, + struct list_head *config_terms) + { +- return __add_event(list, idx, attr, name, NULL, config_terms, false) ? 0 : -ENOMEM; ++ return __add_event(list, idx, attr, name, NULL, config_terms, false, NULL) ? 0 : -ENOMEM; ++} ++ ++static int add_event_tool(struct list_head *list, int *idx, ++ enum perf_tool_event tool_event) ++{ ++ struct perf_evsel *evsel; ++ struct perf_event_attr attr = { ++ .type = PERF_TYPE_SOFTWARE, ++ .config = PERF_COUNT_SW_DUMMY, ++ }; ++ ++ evsel = __add_event(list, idx, &attr, NULL, NULL, NULL, false, "0"); ++ if (!evsel) ++ return -ENOMEM; ++ evsel->tool_event = tool_event; ++ if (tool_event == PERF_TOOL_DURATION_TIME) ++ evsel->unit = strdup("ns"); ++ return 0; + } + + static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) +@@ -1225,6 +1245,13 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, + get_config_name(head_config), &config_terms); + } + ++int parse_events_add_tool(struct parse_events_state *parse_state, ++ struct list_head *list, ++ enum perf_tool_event tool_event) ++{ ++ return add_event_tool(list, &parse_state->idx, tool_event); ++} ++ + int parse_events_add_pmu(struct parse_events_state *parse_state, + struct list_head *list, char *name, + struct list_head *head_config, +@@ -1259,7 +1286,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, + + if (!head_config) { + attr.type = pmu->type; +- evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); ++ evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, ++ auto_merge_stats, NULL); + if (evsel) { + evsel->pmu_name = name ? strdup(name) : NULL; + evsel->use_uncore_alias = use_uncore_alias; +@@ -1294,7 +1322,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, + + evsel = __add_event(list, &parse_state->idx, &attr, + get_config_name(head_config), pmu, +- &config_terms, auto_merge_stats); ++ &config_terms, auto_merge_stats, NULL); + if (evsel) { + evsel->unit = info.unit; + evsel->scale = info.scale; +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 4473dac27aee..638e2a0bec35 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -159,6 +159,10 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, + struct list_head *list, + u32 type, u64 config, + struct list_head *head_config); ++enum perf_tool_event; ++int parse_events_add_tool(struct parse_events_state *parse_state, ++ struct list_head *list, ++ enum perf_tool_event tool_event); + int parse_events_add_cache(struct list_head *list, int *idx, + char *type, char *op_result1, char *op_result2, + struct parse_events_error *error, +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index 5f761f3ed0f3..d8c82cd8d610 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -15,6 +15,7 @@ + #include "../perf.h" + #include "parse-events.h" + #include "parse-events-bison.h" ++#include "evsel.h" + + char *parse_events_get_text(yyscan_t yyscanner); + YYSTYPE *parse_events_get_lval(yyscan_t yyscanner); +@@ -154,6 +155,14 @@ static int sym(yyscan_t scanner, int type, int config) + return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; + } + ++static int tool(yyscan_t scanner, enum perf_tool_event event) ++{ ++ YYSTYPE *yylval = parse_events_get_lval(scanner); ++ ++ yylval->num = event; ++ return PE_VALUE_SYM_TOOL; ++} ++ + static int term(yyscan_t scanner, int type) + { + YYSTYPE *yylval = parse_events_get_lval(scanner); +@@ -321,7 +330,7 @@ cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU + alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } + emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } + dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } +-duration_time { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } ++duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); } + bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } + + /* +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index 5d5413c21b64..a2c7b6fb1fd5 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -14,6 +14,7 @@ + #include + #include "util.h" + #include "pmu.h" ++#include "evsel.h" + #include "debug.h" + #include "parse-events.h" + #include "parse-events-bison.h" +@@ -45,6 +46,7 @@ static void inc_group_count(struct list_head *list, + + %token PE_START_EVENTS PE_START_TERMS + %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM ++%token PE_VALUE_SYM_TOOL + %token PE_EVENT_NAME + %token PE_NAME + %token PE_BPF_OBJECT PE_BPF_SOURCE +@@ -58,6 +60,7 @@ static void inc_group_count(struct list_head *list, + %type PE_VALUE + %type PE_VALUE_SYM_HW + %type PE_VALUE_SYM_SW ++%type PE_VALUE_SYM_TOOL + %type PE_RAW + %type PE_TERM + %type PE_NAME +@@ -321,6 +324,15 @@ value_sym sep_slash_slash_dc + ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL)); + $$ = list; + } ++| ++PE_VALUE_SYM_TOOL sep_slash_slash_dc ++{ ++ struct list_head *list; ++ ++ ALLOC_LIST(list); ++ ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); ++ $$ = list; ++} + + event_legacy_cache: + PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config +-- +2.27.0 + diff --git a/patches/0128-perf-evsel-Support-printing-evsel-name-for-duration_.patch b/patches/0128-perf-evsel-Support-printing-evsel-name-for-duration_.patch new file mode 100644 index 0000000..f1f5b22 --- /dev/null +++ b/patches/0128-perf-evsel-Support-printing-evsel-name-for-duration_.patch @@ -0,0 +1,59 @@ +From f20b39339978d851d7a44972d3c7974a3acdc6fa Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Tue, 26 Mar 2019 15:18:22 -0700 +Subject: [PATCH 011/201] perf evsel: Support printing evsel name for + 'duration_time' + +mainline inclusion +from mainline-v5.2-rc1 +commit 3371f389e4be6efc496ca395b21911a8f2c2d23f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3371f389e4be6efc496ca395b21911a8f2c2d23f + +------------------------------------------------------------------------ + +Implement printing the correct name for duration_time + +Signed-off-by: Andi Kleen +Acked-by: Jiri Olsa +Link: http://lkml.kernel.org/r/20190326221823.11518-4-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/evsel.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c +index 4390a8d8ba0b..e0fb67670e03 100644 +--- a/tools/perf/util/evsel.c ++++ b/tools/perf/util/evsel.c +@@ -586,6 +586,12 @@ static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size) + return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); + } + ++static int perf_evsel__tool_name(char *bf, size_t size) ++{ ++ int ret = scnprintf(bf, size, "duration_time"); ++ return ret; ++} ++ + const char *perf_evsel__name(struct perf_evsel *evsel) + { + char bf[128]; +@@ -610,7 +616,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel) + break; + + case PERF_TYPE_SOFTWARE: +- perf_evsel__sw_name(evsel, bf, sizeof(bf)); ++ if (evsel->tool_event) ++ perf_evsel__tool_name(bf, sizeof(bf)); ++ else ++ perf_evsel__sw_name(evsel, bf, sizeof(bf)); + break; + + case PERF_TYPE_TRACEPOINT: +-- +2.27.0 + diff --git a/patches/0129-perf-list-Output-tool-events.patch b/patches/0129-perf-list-Output-tool-events.patch new file mode 100644 index 0000000..1e53573 --- /dev/null +++ b/patches/0129-perf-list-Output-tool-events.patch @@ -0,0 +1,148 @@ +From e61fd6e1d87c9ff8d33b5b07e4be63440bece6eb Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Tue, 26 Mar 2019 15:18:23 -0700 +Subject: [PATCH 012/201] perf list: Output tool events + +mainline inclusion +from mainline-v5.2-rc1 +commit 5e0861baa3fa73e8bd861a4b7ba7fa992b1dff82 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5e0861baa3fa73e8bd861a4b7ba7fa992b1dff82 + +---------------------------------------------------------------------- + +Add support in 'perf list' to output tool internal events, currently +only 'duration_time'. + +Committer testing: + + $ perf list dur* + + List of pre-defined events (to be used in -e): + + duration_time [Tool event] + + Metric Groups: + + $ perf list sw + + List of pre-defined events (to be used in -e): + + alignment-faults [Software event] + bpf-output [Software event] + context-switches OR cs [Software event] + cpu-clock [Software event] + cpu-migrations OR migrations [Software event] + dummy [Software event] + emulation-faults [Software event] + major-faults [Software event] + minor-faults [Software event] + page-faults OR faults [Software event] + task-clock [Software event] + + duration_time [Tool event] + + $ perf list | grep duration + duration_time [Tool event] + [L1D miss outstandings duration in cycles] + page walk duration are excluded in Skylake] + load. EPT page walk duration are excluded in Skylake] + page walk duration are excluded in Skylake] + store. EPT page walk duration are excluded in Skylake] + (instruction fetch) request. EPT page walk duration are excluded in + instruction fetch request. EPT page walk duration are excluded in + $ + +Signed-off-by: Andi Kleen +Tested-by: Arnaldo Carvalho de Melo +Acked-by: Jiri Olsa +Link: http://lkml.kernel.org/r/20190326221823.11518-5-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-list.c | 6 ++++-- + tools/perf/util/parse-events.c | 20 ++++++++++++++++++++ + tools/perf/util/parse-events.h | 1 + + 3 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c +index c9f98d00c0e9..e4606919bda9 100644 +--- a/tools/perf/builtin-list.c ++++ b/tools/perf/builtin-list.c +@@ -70,10 +70,11 @@ int cmd_list(int argc, const char **argv) + print_symbol_events(NULL, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump); + else if (strcmp(argv[i], "sw") == 0 || +- strcmp(argv[i], "software") == 0) ++ strcmp(argv[i], "software") == 0) { + print_symbol_events(NULL, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); +- else if (strcmp(argv[i], "cache") == 0 || ++ print_tool_events(NULL, raw_dump); ++ } else if (strcmp(argv[i], "cache") == 0 || + strcmp(argv[i], "hwcache") == 0) + print_hwcache_events(NULL, raw_dump); + else if (strcmp(argv[i], "pmu") == 0) +@@ -113,6 +114,7 @@ int cmd_list(int argc, const char **argv) + event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump); + print_symbol_events(s, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); ++ print_tool_events(s, raw_dump); + print_hwcache_events(s, raw_dump); + print_pmu_events(s, raw_dump, !desc_flag, + long_desc_flag, +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 36d0851c452b..c0a13cf41ef6 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -2460,6 +2460,25 @@ int print_hwcache_events(const char *event_glob, bool name_only) + return evt_num; + } + ++static void print_tool_event(const char *name, const char *event_glob, ++ bool name_only) ++{ ++ if (event_glob && !strglobmatch(name, event_glob)) ++ return; ++ if (name_only) ++ printf("%s ", name); ++ else ++ printf(" %-50s [%s]\n", name, "Tool event"); ++ ++} ++ ++void print_tool_events(const char *event_glob, bool name_only) ++{ ++ print_tool_event("duration_time", event_glob, name_only); ++ if (pager_in_use()) ++ printf("\n"); ++} ++ + void print_symbol_events(const char *event_glob, unsigned type, + struct event_symbol *syms, unsigned max, + bool name_only) +@@ -2543,6 +2562,7 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag, + + print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX, name_only); ++ print_tool_events(event_glob, name_only); + + print_hwcache_events(event_glob, name_only); + +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 638e2a0bec35..58c6730526f9 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -203,6 +203,7 @@ extern struct event_symbol event_symbols_sw[]; + void print_symbol_events(const char *event_glob, unsigned type, + struct event_symbol *syms, unsigned max, + bool name_only); ++void print_tool_events(const char *event_glob, bool name_only); + void print_tracepoint_events(const char *subsys_glob, const char *event_glob, + bool name_only); + int print_hwcache_events(const char *event_glob, bool name_only); +-- +2.27.0 + diff --git a/patches/0130-libbpf-add-resizable-non-thread-safe-internal-hashma.patch b/patches/0130-libbpf-add-resizable-non-thread-safe-internal-hashma.patch new file mode 100644 index 0000000..32344bf --- /dev/null +++ b/patches/0130-libbpf-add-resizable-non-thread-safe-internal-hashma.patch @@ -0,0 +1,476 @@ +From b1161e911d8edf2a5235b8419886018ff4ee0d64 Mon Sep 17 00:00:00 2001 +From: Andrii Nakryiko +Date: Fri, 24 May 2019 11:59:00 -0700 +Subject: [PATCH 013/201] libbpf: add resizable non-thread safe internal + hashmap + +mainline inclusion +from mainline-v5.3-rc1 +commit e3b924224028c6fc31545e3812eecbe2ddbf35f6 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e3b924224028c6fc31545e3812eecbe2ddbf35f6 + +---------------------------------------------------------------------- + +There is a need for fast point lookups inside libbpf for multiple use +cases (e.g., name resolution for BTF-to-C conversion, by-name lookups in +BTF for upcoming BPF CO-RE relocation support, etc). This patch +implements simple resizable non-thread safe hashmap using single linked +list chains. + +Four different insert strategies are supported: + - HASHMAP_ADD - only add key/value if key doesn't exist yet; + - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise, + update value; + - HASHMAP_UPDATE - update value, if key already exists; otherwise, do + nothing and return -ENOENT; + - HASHMAP_APPEND - always add key/value pair, even if key already exists. + This turns hashmap into a multimap by allowing multiple values to be + associated with the same key. Most useful read API for such hashmap is + hashmap__for_each_key_entry() iteration. If hashmap__find() is still + used, it will return last inserted key/value entry (first in a bucket + chain). + +For HASHMAP_SET and HASHMAP_UPDATE, old key/value pair is returned, so +that calling code can handle proper memory management, if necessary. + +Signed-off-by: Andrii Nakryiko +Signed-off-by: Alexei Starovoitov +Signed-off-by: hongrongxuan + + Conflicts: + tools/lib/bpf/Build + tools/lib/bpf/hashmap.h +--- + tools/lib/bpf/Build | 2 +- + tools/lib/bpf/hashmap.c | 229 ++++++++++++++++++++++++++++++++++++++++ + tools/lib/bpf/hashmap.h | 172 ++++++++++++++++++++++++++++++ + 3 files changed, 402 insertions(+), 1 deletion(-) + create mode 100644 tools/lib/bpf/hashmap.c + create mode 100644 tools/lib/bpf/hashmap.h + +diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build +index 6eb9bacd1948..3e993bf724db 100644 +--- a/tools/lib/bpf/Build ++++ b/tools/lib/bpf/Build +@@ -1 +1 @@ +-libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o ++libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o hashmap.o +diff --git a/tools/lib/bpf/hashmap.c b/tools/lib/bpf/hashmap.c +new file mode 100644 +index 000000000000..6122272943e6 +--- /dev/null ++++ b/tools/lib/bpf/hashmap.c +@@ -0,0 +1,229 @@ ++// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) ++ ++/* ++ * Generic non-thread safe hash map implementation. ++ * ++ * Copyright (c) 2019 Facebook ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "hashmap.h" ++ ++/* start with 4 buckets */ ++#define HASHMAP_MIN_CAP_BITS 2 ++ ++static void hashmap_add_entry(struct hashmap_entry **pprev, ++ struct hashmap_entry *entry) ++{ ++ entry->next = *pprev; ++ *pprev = entry; ++} ++ ++static void hashmap_del_entry(struct hashmap_entry **pprev, ++ struct hashmap_entry *entry) ++{ ++ *pprev = entry->next; ++ entry->next = NULL; ++} ++ ++void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, void *ctx) ++{ ++ map->hash_fn = hash_fn; ++ map->equal_fn = equal_fn; ++ map->ctx = ctx; ++ ++ map->buckets = NULL; ++ map->cap = 0; ++ map->cap_bits = 0; ++ map->sz = 0; ++} ++ ++struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, ++ void *ctx) ++{ ++ struct hashmap *map = malloc(sizeof(struct hashmap)); ++ ++ if (!map) ++ return ERR_PTR(-ENOMEM); ++ hashmap__init(map, hash_fn, equal_fn, ctx); ++ return map; ++} ++ ++void hashmap__clear(struct hashmap *map) ++{ ++ free(map->buckets); ++ map->cap = map->cap_bits = map->sz = 0; ++} ++ ++void hashmap__free(struct hashmap *map) ++{ ++ if (!map) ++ return; ++ ++ hashmap__clear(map); ++ free(map); ++} ++ ++size_t hashmap__size(const struct hashmap *map) ++{ ++ return map->sz; ++} ++ ++size_t hashmap__capacity(const struct hashmap *map) ++{ ++ return map->cap; ++} ++ ++static bool hashmap_needs_to_grow(struct hashmap *map) ++{ ++ /* grow if empty or more than 75% filled */ ++ return (map->cap == 0) || ((map->sz + 1) * 4 / 3 > map->cap); ++} ++ ++static int hashmap_grow(struct hashmap *map) ++{ ++ struct hashmap_entry **new_buckets; ++ struct hashmap_entry *cur, *tmp; ++ size_t new_cap_bits, new_cap; ++ size_t h; ++ int bkt; ++ ++ new_cap_bits = map->cap_bits + 1; ++ if (new_cap_bits < HASHMAP_MIN_CAP_BITS) ++ new_cap_bits = HASHMAP_MIN_CAP_BITS; ++ ++ new_cap = 1UL << new_cap_bits; ++ new_buckets = calloc(new_cap, sizeof(new_buckets[0])); ++ if (!new_buckets) ++ return -ENOMEM; ++ ++ hashmap__for_each_entry_safe(map, cur, tmp, bkt) { ++ h = hash_bits(map->hash_fn(cur->key, map->ctx), new_cap_bits); ++ hashmap_add_entry(&new_buckets[h], cur); ++ } ++ ++ map->cap = new_cap; ++ map->cap_bits = new_cap_bits; ++ free(map->buckets); ++ map->buckets = new_buckets; ++ ++ return 0; ++} ++ ++static bool hashmap_find_entry(const struct hashmap *map, ++ const void *key, size_t hash, ++ struct hashmap_entry ***pprev, ++ struct hashmap_entry **entry) ++{ ++ struct hashmap_entry *cur, **prev_ptr; ++ ++ if (!map->buckets) ++ return false; ++ ++ for (prev_ptr = &map->buckets[hash], cur = *prev_ptr; ++ cur; ++ prev_ptr = &cur->next, cur = cur->next) { ++ if (map->equal_fn(cur->key, key, map->ctx)) { ++ if (pprev) ++ *pprev = prev_ptr; ++ *entry = cur; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++int hashmap__insert(struct hashmap *map, const void *key, void *value, ++ enum hashmap_insert_strategy strategy, ++ const void **old_key, void **old_value) ++{ ++ struct hashmap_entry *entry; ++ size_t h; ++ int err; ++ ++ if (old_key) ++ *old_key = NULL; ++ if (old_value) ++ *old_value = NULL; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (strategy != HASHMAP_APPEND && ++ hashmap_find_entry(map, key, h, NULL, &entry)) { ++ if (old_key) ++ *old_key = entry->key; ++ if (old_value) ++ *old_value = entry->value; ++ ++ if (strategy == HASHMAP_SET || strategy == HASHMAP_UPDATE) { ++ entry->key = key; ++ entry->value = value; ++ return 0; ++ } else if (strategy == HASHMAP_ADD) { ++ return -EEXIST; ++ } ++ } ++ ++ if (strategy == HASHMAP_UPDATE) ++ return -ENOENT; ++ ++ if (hashmap_needs_to_grow(map)) { ++ err = hashmap_grow(map); ++ if (err) ++ return err; ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ } ++ ++ entry = malloc(sizeof(struct hashmap_entry)); ++ if (!entry) ++ return -ENOMEM; ++ ++ entry->key = key; ++ entry->value = value; ++ hashmap_add_entry(&map->buckets[h], entry); ++ map->sz++; ++ ++ return 0; ++} ++ ++bool hashmap__find(const struct hashmap *map, const void *key, void **value) ++{ ++ struct hashmap_entry *entry; ++ size_t h; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (!hashmap_find_entry(map, key, h, NULL, &entry)) ++ return false; ++ ++ if (value) ++ *value = entry->value; ++ return true; ++} ++ ++bool hashmap__delete(struct hashmap *map, const void *key, ++ const void **old_key, void **old_value) ++{ ++ struct hashmap_entry **pprev, *entry; ++ size_t h; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (!hashmap_find_entry(map, key, h, &pprev, &entry)) ++ return false; ++ ++ if (old_key) ++ *old_key = entry->key; ++ if (old_value) ++ *old_value = entry->value; ++ ++ hashmap_del_entry(pprev, entry); ++ free(entry); ++ map->sz--; ++ ++ return true; ++} ++ +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +new file mode 100644 +index 000000000000..ab97b9797100 +--- /dev/null ++++ b/tools/lib/bpf/hashmap.h +@@ -0,0 +1,172 @@ ++/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ ++ ++/* ++ * Generic non-thread safe hash map implementation. ++ * ++ * Copyright (c) 2019 Facebook ++ */ ++#ifndef __LIBBPF_HASHMAP_H ++#define __LIBBPF_HASHMAP_H ++ ++#include ++#include ++ ++static inline size_t hash_bits(size_t h, int bits) ++{ ++ /* shuffle bits and return requested number of upper bits */ ++ return (h * 11400714819323198485llu) >> (__WORDSIZE - bits); ++} ++ ++typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); ++typedef bool (*hashmap_equal_fn)(const void *key1, const void *key2, void *ctx); ++ ++struct hashmap_entry { ++ const void *key; ++ void *value; ++ struct hashmap_entry *next; ++}; ++ ++struct hashmap { ++ hashmap_hash_fn hash_fn; ++ hashmap_equal_fn equal_fn; ++ void *ctx; ++ ++ struct hashmap_entry **buckets; ++ size_t cap; ++ size_t cap_bits; ++ size_t sz; ++}; ++ ++#define HASHMAP_INIT(hash_fn, equal_fn, ctx) { \ ++ .hash_fn = (hash_fn), \ ++ .equal_fn = (equal_fn), \ ++ .ctx = (ctx), \ ++ .buckets = NULL, \ ++ .cap = 0, \ ++ .cap_bits = 0, \ ++ .sz = 0, \ ++} ++ ++void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, void *ctx); ++struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, ++ void *ctx); ++void hashmap__clear(struct hashmap *map); ++void hashmap__free(struct hashmap *map); ++ ++size_t hashmap__size(const struct hashmap *map); ++size_t hashmap__capacity(const struct hashmap *map); ++ ++/* ++ * Hashmap insertion strategy: ++ * - HASHMAP_ADD - only add key/value if key doesn't exist yet; ++ * - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise, ++ * update value; ++ * - HASHMAP_UPDATE - update value, if key already exists; otherwise, do ++ * nothing and return -ENOENT; ++ * - HASHMAP_APPEND - always add key/value pair, even if key already exists. ++ * This turns hashmap into a multimap by allowing multiple values to be ++ * associated with the same key. Most useful read API for such hashmap is ++ * hashmap__for_each_key_entry() iteration. If hashmap__find() is still ++ * used, it will return last inserted key/value entry (first in a bucket ++ * chain). ++ */ ++enum hashmap_insert_strategy { ++ HASHMAP_ADD, ++ HASHMAP_SET, ++ HASHMAP_UPDATE, ++ HASHMAP_APPEND, ++}; ++ ++/* ++ * hashmap__insert() adds key/value entry w/ various semantics, depending on ++ * provided strategy value. If a given key/value pair replaced already ++ * existing key/value pair, both old key and old value will be returned ++ * through old_key and old_value to allow calling code do proper memory ++ * management. ++ */ ++int hashmap__insert(struct hashmap *map, const void *key, void *value, ++ enum hashmap_insert_strategy strategy, ++ const void **old_key, void **old_value); ++ ++static inline int hashmap__add(struct hashmap *map, ++ const void *key, void *value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_ADD, NULL, NULL); ++} ++ ++static inline int hashmap__set(struct hashmap *map, ++ const void *key, void *value, ++ const void **old_key, void **old_value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_SET, ++ old_key, old_value); ++} ++ ++static inline int hashmap__update(struct hashmap *map, ++ const void *key, void *value, ++ const void **old_key, void **old_value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_UPDATE, ++ old_key, old_value); ++} ++ ++static inline int hashmap__append(struct hashmap *map, ++ const void *key, void *value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_APPEND, NULL, NULL); ++} ++ ++bool hashmap__delete(struct hashmap *map, const void *key, ++ const void **old_key, void **old_value); ++ ++bool hashmap__find(const struct hashmap *map, const void *key, void **value); ++ ++/* ++ * hashmap__for_each_entry - iterate over all entries in hashmap ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @bkt: integer used as a bucket loop cursor ++ */ ++#define hashmap__for_each_entry(map, cur, bkt) \ ++ for (bkt = 0; bkt < map->cap; bkt++) \ ++ for (cur = map->buckets[bkt]; cur; cur = cur->next) ++ ++/* ++ * hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe ++ * against removals ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @tmp: struct hashmap_entry * used as a temporary next cursor storage ++ * @bkt: integer used as a bucket loop cursor ++ */ ++#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \ ++ for (bkt = 0; bkt < map->cap; bkt++) \ ++ for (cur = map->buckets[bkt]; \ ++ cur && ({tmp = cur->next; true; }); \ ++ cur = tmp) ++ ++/* ++ * hashmap__for_each_key_entry - iterate over entries associated with given key ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @key: key to iterate entries for ++ */ ++#define hashmap__for_each_key_entry(map, cur, _key) \ ++ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ ++ map->cap_bits); \ ++ map->buckets ? map->buckets[bkt] : NULL; }); \ ++ cur; \ ++ cur = cur->next) \ ++ if (map->equal_fn(cur->key, (_key), map->ctx)) ++ ++#define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ ++ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ ++ map->cap_bits); \ ++ cur = map->buckets ? map->buckets[bkt] : NULL; }); \ ++ cur && ({ tmp = cur->next; true; }); \ ++ cur = tmp) \ ++ if (map->equal_fn(cur->key, (_key), map->ctx)) ++ ++#endif /* __LIBBPF_HASHMAP_H */ +-- +2.27.0 + diff --git a/patches/0131-perf-stat-Fix-metrics-with-no-merge.patch b/patches/0131-perf-stat-Fix-metrics-with-no-merge.patch new file mode 100644 index 0000000..9571135 --- /dev/null +++ b/patches/0131-perf-stat-Fix-metrics-with-no-merge.patch @@ -0,0 +1,82 @@ +From 7dfd2106230977845705617a25773803c1ce2e5a Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Mon, 24 Jun 2019 12:37:11 -0700 +Subject: [PATCH 014/201] perf stat: Fix metrics with --no-merge + +mainline inclusion +from mainline-v5.3-rc1 +commit e3a9427323a53ceee540276a74af7706f350d052 +category: feature +bugzilla: e3a9427323a53ceee540276a74af7706f350d052 + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e3a9427323a53ceee540276a74af7706f350d052 + +---------------------------------------------------------------------- + +Since Fixes: 8c5421c016a4 ("perf pmu: Display pmu name when printing +unmerged events in stat") using --no-merge adds the PMU name to the +evsel name. + +This breaks the metric value lookup because the parser doesn't know +about this. + +Remove the extra postfixes for the metric evaluation. + +Signed-off-by: Andi Kleen +Acked-by: Jiri Olsa +Cc: Agustin Vega-Frias +Cc: Kan Liang +Fixes: 8c5421c016a4 ("perf pmu: Display pmu name when printing unmerged events in stat") +Link: http://lkml.kernel.org/r/20190624193711.35241-5-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/stat-shadow.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 93c075ddc717..77982aae7aaf 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -723,6 +723,7 @@ static void generic_metric(struct perf_stat_config *config, + double ratio; + int i; + void *ctxp = out->ctx; ++ char *n, *pn; + + expr__ctx_init(&pctx); + expr__add_id(&pctx, name, avg); +@@ -742,7 +743,19 @@ static void generic_metric(struct perf_stat_config *config, + stats = &v->stats; + scale = 1.0; + } +- expr__add_id(&pctx, metric_events[i]->name, avg_stats(stats)*scale); ++ ++ n = strdup(metric_events[i]->name); ++ if (!n) ++ return; ++ /* ++ * This display code with --no-merge adds [cpu] postfixes. ++ * These are not supported by the parser. Remove everything ++ * after the space. ++ */ ++ pn = strchr(n, ' '); ++ if (pn) ++ *pn = 0; ++ expr__add_id(&pctx, n, avg_stats(stats)*scale); + } + if (!metric_events[i]) { + const char *p = metric_expr; +@@ -759,6 +772,9 @@ static void generic_metric(struct perf_stat_config *config, + (metric_name ? metric_name : name) : "", 0); + } else + print_metric(config, ctxp, NULL, NULL, "", 0); ++ ++ for (i = 1; i < pctx.num_ids; i++) ++ free((void *)pctx.ids[i].name); + } + + void perf_stat__print_shadow_stats(struct perf_stat_config *config, +-- +2.27.0 + diff --git a/patches/0132-perf-jevents-Remove-unused-variable.patch b/patches/0132-perf-jevents-Remove-unused-variable.patch new file mode 100644 index 0000000..930ed97 --- /dev/null +++ b/patches/0132-perf-jevents-Remove-unused-variable.patch @@ -0,0 +1,54 @@ +From 1e5e3a66f153300977d6d74aec7fb87a47532f95 Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Wed, 15 May 2019 11:19:29 +0000 +Subject: [PATCH 015/201] perf jevents: Remove unused variable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.2-rc1 +commit 8e8f515d567f9ec1d960e9fdb117d39753b7504d +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8e8f515d567f9ec1d960e9fdb117d39753b7504d + +---------------------------------------------------------------------- + +Address gcc warning: + + pmu-events/jevents.c: In function ‘save_arch_std_events’: + pmu-events/jevents.c:417:15: warning: unused variable ‘sb’ [-Wunused-variable] + struct stat *sb = data; + ^~ + +Signed-off-by: Zenghui Yu +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: John Garry +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: wanghaibin.wang@huawei.com +Link: http://lkml.kernel.org/r/1557919169-23972-1-git-send-email-yuzenghui@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index af7f961b1edc..1209d0feaeb5 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -417,7 +417,6 @@ static int save_arch_std_events(void *data, char *name, char *event, + char *metric_name, char *metric_group) + { + struct event_struct *es; +- struct stat *sb = data; + + es = malloc(sizeof(*es)); + if (!es) +-- +2.27.0 + diff --git a/patches/0133-perf-jevents-Use-nonlocal-include-statements-in-pmu-.patch b/patches/0133-perf-jevents-Use-nonlocal-include-statements-in-pmu-.patch new file mode 100644 index 0000000..ae5b007 --- /dev/null +++ b/patches/0133-perf-jevents-Use-nonlocal-include-statements-in-pmu-.patch @@ -0,0 +1,60 @@ +From ae0acec647f86efed2ac7a8d94852efc4136e8ed Mon Sep 17 00:00:00 2001 +From: Luke Mujica +Date: Tue, 25 Jun 2019 10:31:22 -0700 +Subject: [PATCH 016/201] perf jevents: Use nonlocal include statements in + pmu-events.c + +mainline inclusion +from mainline-v5.3-rc1 +commit 06c642c0e9fceafd16b1a4c80d44b1c09e282215 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=06c642c0e9fceafd16b1a4c80d44b1c09e282215 + +---------------------------------------------------------------------- + +Change pmu-events.c to not use local include statements. The code that +creates the include statements for pmu-events.c is in jevents.c. + +pmu-events.c is a generated file, and for build systems that put +generated files in a separate directory, include statements with local +pathing cannot find non-generated files. + +Signed-off-by: Luke Mujica +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Numfor Mbiziwo-Tiapo +Cc: Stephane Eranian +Link: https://lkml.kernel.org/n/tip-prgnwmaoo1pv9zz4vnv1bjaj@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 1209d0feaeb5..55c8bf2b0b32 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -849,7 +849,7 @@ static void create_empty_mapping(const char *output_file) + _Exit(1); + } + +- fprintf(outfp, "#include \"../../pmu-events/pmu-events.h\"\n"); ++ fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n"); + print_mapping_table_prefix(outfp); + print_mapping_table_suffix(outfp); + fclose(outfp); +@@ -1103,7 +1103,7 @@ int main(int argc, char *argv[]) + } + + /* Include pmu-events.h first */ +- fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n"); ++ fprintf(eventsfp, "#include \"pmu-events/pmu-events.h\"\n"); + + /* + * The mapfile allows multiple CPUids to point to the same JSON file, +-- +2.27.0 + diff --git a/patches/0134-perf-list-Avoid-extra-for-raw-metrics.patch b/patches/0134-perf-list-Avoid-extra-for-raw-metrics.patch new file mode 100644 index 0000000..1458916 --- /dev/null +++ b/patches/0134-perf-list-Avoid-extra-for-raw-metrics.patch @@ -0,0 +1,43 @@ +From 936090e8e295cd14a5ac086baba7123ec345de95 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Fri, 28 Jun 2019 15:07:36 -0700 +Subject: [PATCH 017/201] perf list: Avoid extra : for --raw metrics + +mainline inclusion +from mainline-v5.3-rc1 +commit 9c344d15f5783260f57c711f3fce72dd744bebe2 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9c344d15f5783260f57c711f3fce72dd744bebe2 + +---------------------------------------------------------------------- + +When printing the metrics raw, don't print : after the metricgroups. +This helps the command line completion to complete those too. + +Signed-off-by: Andi Kleen +Cc: Jiri Olsa +Link: http://lkml.kernel.org/r/20190628220737.13259-2-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 27552a0b990a..90c22757ca9d 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -388,7 +388,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + struct mep *me = container_of(node, struct mep, nd); + + if (metricgroups) +- printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n"); ++ printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n"); + if (metrics) + metricgroup__print_strlist(me->metrics, raw); + next = rb_next(node); +-- +2.27.0 + diff --git a/patches/0135-perf-tools-metric-Don-t-include-duration_time-in-gro.patch b/patches/0135-perf-tools-metric-Don-t-include-duration_time-in-gro.patch new file mode 100644 index 0000000..d3856c9 --- /dev/null +++ b/patches/0135-perf-tools-metric-Don-t-include-duration_time-in-gro.patch @@ -0,0 +1,76 @@ +From 4f8b8c59605dc32e5224879c3e24ac750a05b482 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Fri, 28 Jun 2019 15:07:37 -0700 +Subject: [PATCH 018/201] perf tools metric: Don't include duration_time in + group + +mainline inclusion +from mainline-v5.3-rc1 +commit 488c3bf7ece89e47887607863207021283e37828 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=488c3bf7ece89e47887607863207021283e37828 + +------------------------------------------------------------------------ + +The Memory_BW metric generates groups including duration_time, which +maps to a software event. + +For some reason this makes the group always not count. + +Always put duration_time outside a group when generating metrics. It's +always the same time, so no need to group it. + +Signed-off-by: Andi Kleen +Cc: Jiri Olsa +Link: http://lkml.kernel.org/r/20190628220737.13259-3-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 90c22757ca9d..dae3779d4fef 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -422,6 +422,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + const char **ids; + int idnum; + struct egroup *eg; ++ bool no_group = false; + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + +@@ -432,11 +433,25 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + strbuf_addf(events, ","); + for (j = 0; j < idnum; j++) { + pr_debug("found event %s\n", ids[j]); ++ /* ++ * Duration time maps to a software event and can make ++ * groups not count. Always use it outside a ++ * group. ++ */ ++ if (!strcmp(ids[j], "duration_time")) { ++ if (j > 0) ++ strbuf_addf(events, "}:W,"); ++ strbuf_addf(events, "duration_time"); ++ no_group = true; ++ continue; ++ } + strbuf_addf(events, "%s%s", +- j == 0 ? "{" : ",", ++ j == 0 || no_group ? "{" : ",", + ids[j]); ++ no_group = false; + } +- strbuf_addf(events, "}:W"); ++ if (!no_group) ++ strbuf_addf(events, "}:W"); + + eg = malloc(sizeof(struct egroup)); + if (!eg) { +-- +2.27.0 + diff --git a/patches/0136-perf-metricgroup-Add-missing-list_del_init-when-flus.patch b/patches/0136-perf-metricgroup-Add-missing-list_del_init-when-flus.patch new file mode 100644 index 0000000..601cdc2 --- /dev/null +++ b/patches/0136-perf-metricgroup-Add-missing-list_del_init-when-flus.patch @@ -0,0 +1,48 @@ +From 05ef3cb8a048bcc5eb4a16faae5e192a521a240c Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Thu, 4 Jul 2019 12:20:21 -0300 +Subject: [PATCH 019/201] perf metricgroup: Add missing list_del_init() when + flushing egroups list + +mainline inclusion +from mainline-v5.3-rc1 +commit acc7bfb3db9744c4a18c96fd6536069e8647cb11 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acc7bfb3db9744c4a18c96fd6536069e8647cb11 + +------------------------------------------------------------------------ + +So that at the end each of the entries have its list node struct cleared +and the egroup list head ends emptied. + +Cc: Adrian Hunter +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Namhyung Kim +Link: https://lkml.kernel.org/n/tip-dxzj1ah350fy9ec0xbhb15b6@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index dae3779d4fef..4c6ecda3e7ac 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -504,6 +504,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) + for (i = 0; i < eg->idnum; i++) + free((char *)eg->ids[i]); + free(eg->ids); ++ list_del_init(&eg->nd); + free(eg); + } + } +-- +2.27.0 + diff --git a/patches/0137-perf-metricgroup-Remove-needless-includes-from-metri.patch b/patches/0137-perf-metricgroup-Remove-needless-includes-from-metri.patch new file mode 100644 index 0000000..fcc2356 --- /dev/null +++ b/patches/0137-perf-metricgroup-Remove-needless-includes-from-metri.patch @@ -0,0 +1,89 @@ +From dfb7c7fcf8833337c750f07a2f876f5f22e1f1be Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Wed, 21 Aug 2019 10:54:14 -0300 +Subject: [PATCH 020/201] perf metricgroup: Remove needless includes from + metricgroup.h + +mainline inclusion +from mainline-v5.4-rc1 +commit 0b8026e8fb0ea3893caa2f1924a2c15fcf6760b3 +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b8026e8fb0ea3893caa2f1924a2c15fcf6760b3 + +------------------------------------------------------------------------ + +There we need just some struct forward declarations, do that instead and +add the includes needed by metricgroup.c. + +That should help with needless rebuilds when changing the removed +headers from metricgroup.h. + +Cc: Adrian Hunter +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Namhyung Kim +Link: https://lkml.kernel.org/n/tip-1fkskjws6imir2hhztqhdyb0@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c + tools/perf/util/metricgroup.h +--- + tools/perf/util/metricgroup.c | 3 ++- + tools/perf/util/metricgroup.h | 13 ++++++++----- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 4c6ecda3e7ac..503cd543de9c 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -16,17 +16,18 @@ + + #include "metricgroup.h" + #include "evlist.h" ++#include "evsel.h" + #include "strbuf.h" + #include "pmu.h" + #include "expr.h" + #include "rblist.h" + #include +-#include + #include + #include "pmu-events/pmu-events.h" + #include "strlist.h" + #include + #include ++#include + + struct metric_event *metricgroup__lookup(struct rblist *metric_events, + struct perf_evsel *evsel, +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 5c52097a5c63..b5d785f37073 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -1,11 +1,14 @@ ++// SPDX-License-Identifier: GPL-2.0-only + #ifndef METRICGROUP_H + #define METRICGROUP_H 1 + +-#include "linux/list.h" +-#include "rblist.h" +-#include +-#include "evlist.h" +-#include "strbuf.h" ++#include ++#include ++#include ++ ++struct perf_evsel; ++struct option; ++struct rblist; + + struct metric_event { + struct rb_node nd; +-- +2.27.0 + diff --git a/patches/0138-perf-pmu-Change-convert_scale-from-static-to-global.patch b/patches/0138-perf-pmu-Change-convert_scale-from-static-to-global.patch new file mode 100644 index 0000000..3de7995 --- /dev/null +++ b/patches/0138-perf-pmu-Change-convert_scale-from-static-to-global.patch @@ -0,0 +1,86 @@ +From ab598ff7883c85c929b287a06501d9df15b1a42c Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Wed, 28 Aug 2019 13:59:29 +0800 +Subject: [PATCH 021/201] perf pmu: Change convert_scale from static to global + +mainline inclusion +from mainline-v5.4-rc1 +commit 287f2649f791819dd2d8f32f0213c8c521d6dfa0 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=287f2649f791819dd2d8f32f0213c8c521d6dfa0 + +------------------------------------------------------------------------ + +The function convert_scale() can be used to convert string to unit and +scale. For example, + + s = "6000000000ns"; + convert_scale(s, &unit, &scale); + +unit = "ns", scale = 6000000000. + +Currently this function is static. This patch renames the function to +perf_pmu__convert_scale and changes the function to global. No +functional change. + +Signed-off-by: Jin Yao +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20190828055932.8269-2-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 6 +++--- + tools/perf/util/pmu.h | 2 ++ + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index aa91fcb51a6d..256a9792bd7e 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -100,7 +100,7 @@ static int pmu_format(const char *name, struct list_head *format) + return 0; + } + +-static int convert_scale(const char *scale, char **end, double *sval) ++int perf_pmu__convert_scale(const char *scale, char **end, double *sval) + { + char *lc; + int ret = 0; +@@ -163,7 +163,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * + else + scale[sret] = '\0'; + +- ret = convert_scale(scale, NULL, &alias->scale); ++ ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); + error: + close(fd); + return ret; +@@ -371,7 +371,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + desc ? strdup(desc) : NULL; + alias->topic = topic ? strdup(topic) : NULL; + if (unit) { +- if (convert_scale(unit, &unit, &alias->scale) < 0) ++ if (perf_pmu__convert_scale(unit, &unit, &alias->scale) < 0) + return -1; + snprintf(alias->unit, sizeof(alias->unit), "%s", unit); + } +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 76fecec7b3f9..ea0e7c36eae9 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -94,4 +94,6 @@ struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); + + struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); + ++int perf_pmu__convert_scale(const char *scale, char **end, double *sval); ++ + #endif /* __PMU_H */ +-- +2.27.0 + diff --git a/patches/0139-perf-metricgroup-Scale-the-metric-result.patch b/patches/0139-perf-metricgroup-Scale-the-metric-result.patch new file mode 100644 index 0000000..ce059b4 --- /dev/null +++ b/patches/0139-perf-metricgroup-Scale-the-metric-result.patch @@ -0,0 +1,186 @@ +From a9fa8ae0dd8e2c2cddf376b6ce19f06bf812992d Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Wed, 28 Aug 2019 13:59:31 +0800 +Subject: [PATCH 022/201] perf metricgroup: Scale the metric result + +mainline inclusion +from mainline-v5.4-rc1 +commit 287f2649f791819dd2d8f32f0213c8c521d6dfa0 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=287f2649f791819dd2d8f32f0213c8c521d6dfa0 + +------------------------------------------------------------------------ + +Some metrics define the scale unit, such as + + { + "BriefDescription": "Intel Optane DC persistent memory read latency (ns). Derived from unc_m_pmm_rpq_occupancy.all", + "Counter": "0,1,2,3", + "EventCode": "0xE0", + "EventName": "UNC_M_PMM_READ_LATENCY", + "MetricExpr": "UNC_M_PMM_RPQ_OCCUPANCY.ALL / UNC_M_PMM_RPQ_INSERTS / UNC_M_CLOCKTICKS", + "MetricName": "UNC_M_PMM_READ_LATENCY", + "PerPkg": "1", + "ScaleUnit": "6000000000ns", + "UMask": "0x1", + "Unit": "iMC" + }, + +For above example, the ratio should be, + +ratio = (UNC_M_PMM_RPQ_OCCUPANCY.ALL / UNC_M_PMM_RPQ_INSERTS / UNC_M_CLOCKTICKS) * 6000000000 + +But in current code, the ratio is not scaled ( * 6000000000) + +With this patch, the ratio is scaled and the unit (ns) is printed. + +For example, + # 219.4 ns UNC_M_PMM_READ_LATENCY + +Signed-off-by: Jin Yao +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20190828055932.8269-4-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 3 +++ + tools/perf/util/metricgroup.h | 1 + + tools/perf/util/stat-shadow.c | 38 +++++++++++++++++++++++++---------- + 3 files changed, 31 insertions(+), 11 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 503cd543de9c..d01f16448bab 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -93,6 +93,7 @@ struct egroup { + const char **ids; + const char *metric_name; + const char *metric_expr; ++ const char *metric_unit; + }; + + static bool record_evsel(int *ind, struct perf_evsel **start, +@@ -191,6 +192,7 @@ static int metricgroup__setup_events(struct list_head *groups, + } + expr->metric_expr = eg->metric_expr; + expr->metric_name = eg->metric_name; ++ expr->metric_unit = eg->metric_unit; + expr->metric_events = metric_events; + list_add(&expr->nd, &me->head); + } +@@ -463,6 +465,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + eg->idnum = idnum; + eg->metric_name = pe->metric_name; + eg->metric_expr = pe->metric_expr; ++ eg->metric_unit = pe->unit; + list_add_tail(&eg->nd, group_list); + ret = 0; + } +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index b5d785f37073..9c6e6913f905 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -20,6 +20,7 @@ struct metric_expr { + struct list_head nd; + const char *metric_expr; + const char *metric_name; ++ const char *metric_unit; + struct perf_evsel **metric_events; + }; + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 77982aae7aaf..f687ca257e5d 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -713,6 +713,7 @@ static void generic_metric(struct perf_stat_config *config, + struct perf_evsel **metric_events, + char *name, + const char *metric_name, ++ const char *metric_unit, + double avg, + int cpu, + struct perf_stat_output_ctx *out, +@@ -720,7 +721,7 @@ static void generic_metric(struct perf_stat_config *config, + { + print_metric_t print_metric = out->print_metric; + struct parse_ctx pctx; +- double ratio; ++ double ratio, scale; + int i; + void *ctxp = out->ctx; + char *n, *pn; +@@ -730,7 +731,6 @@ static void generic_metric(struct perf_stat_config *config, + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; +- double scale; + + if (!strcmp(metric_events[i]->name, "duration_time")) { + stats = &walltime_nsecs_stats; +@@ -760,16 +760,32 @@ static void generic_metric(struct perf_stat_config *config, + if (!metric_events[i]) { + const char *p = metric_expr; + +- if (expr__parse(&ratio, &pctx, &p) == 0) +- print_metric(config, ctxp, NULL, "%8.1f", +- metric_name ? +- metric_name : +- out->force_header ? name : "", +- ratio); +- else ++ if (expr__parse(&ratio, &pctx, &p) == 0) { ++ char *unit; ++ char metric_bf[64]; ++ ++ if (metric_unit && metric_name) { ++ if (perf_pmu__convert_scale(metric_unit, ++ &unit, &scale) >= 0) { ++ ratio *= scale; ++ } ++ ++ scnprintf(metric_bf, sizeof(metric_bf), ++ "%s %s", unit, metric_name); ++ print_metric(config, ctxp, NULL, "%8.1f", ++ metric_bf, ratio); ++ } else { ++ print_metric(config, ctxp, NULL, "%8.1f", ++ metric_name ? ++ metric_name : ++ out->force_header ? name : "", ++ ratio); ++ } ++ } else { + print_metric(config, ctxp, NULL, NULL, + out->force_header ? + (metric_name ? metric_name : name) : "", 0); ++ } + } else + print_metric(config, ctxp, NULL, NULL, "", 0); + +@@ -989,7 +1005,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + print_metric(config, ctxp, NULL, NULL, name, 0); + } else if (evsel->metric_expr) { + generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, +- evsel->metric_name, avg, cpu, out, st); ++ evsel->metric_name, NULL, avg, cpu, out, st); + } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { + char unit = 'M'; + char unit_buf[10]; +@@ -1018,7 +1034,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + out->new_line(config, ctxp); + generic_metric(config, mexp->metric_expr, mexp->metric_events, + evsel->name, mexp->metric_name, +- avg, cpu, out, st); ++ mexp->metric_unit, avg, cpu, out, st); + } + } + if (num == 0) +-- +2.27.0 + diff --git a/patches/0140-perf-metricgroup-Support-multiple-events-for-metricg.patch b/patches/0140-perf-metricgroup-Support-multiple-events-for-metricg.patch new file mode 100644 index 0000000..3b7be00 --- /dev/null +++ b/patches/0140-perf-metricgroup-Support-multiple-events-for-metricg.patch @@ -0,0 +1,316 @@ +From c650ff6651b9ee0f846f73275d580f062197ec78 Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Wed, 28 Aug 2019 13:59:32 +0800 +Subject: [PATCH 023/201] perf metricgroup: Support multiple events for + metricgroup + +mainline inclusion +from mainline-v5.4-rc1 +commit f01642e4912bb80a01d693f4cc6fb0897207a090 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f01642e4912bb80a01d693f4cc6fb0897207a090 + +------------------------------------------------------------------------ + +Some uncore metrics don't work as expected. For example, on +cascadelakex: + + root@lkp-csl-2sp2:~# perf stat -M UNC_M_PMM_BANDWIDTH.TOTAL -a -- sleep 1 + + Performance counter stats for 'system wide': + + 1841092 unc_m_pmm_rpq_inserts + 3680816 unc_m_pmm_wpq_inserts + + 1.001775055 seconds time elapsed + + root@lkp-csl-2sp2:~# perf stat -M UNC_M_PMM_READ_LATENCY -a -- sleep 1 + + Performance counter stats for 'system wide': + + 860649746 unc_m_pmm_rpq_occupancy.all + 1840557 unc_m_pmm_rpq_inserts + 12790627455 unc_m_clockticks + + 1.001773348 seconds time elapsed + +No metrics 'UNC_M_PMM_BANDWIDTH.TOTAL' or 'UNC_M_PMM_READ_LATENCY' are +reported. + +The issue is, the case of an alias expanding to mulitple events is not +supported, typically the uncore events. (see comments in +find_evsel_group()). + +For UNC_M_PMM_BANDWIDTH.TOTAL in above example, the expanded event group +is '{unc_m_pmm_rpq_inserts,unc_m_pmm_wpq_inserts}:W', but the actual +events passed to find_evsel_group are: + + unc_m_pmm_rpq_inserts + unc_m_pmm_rpq_inserts + unc_m_pmm_rpq_inserts + unc_m_pmm_rpq_inserts + unc_m_pmm_rpq_inserts + unc_m_pmm_rpq_inserts + unc_m_pmm_wpq_inserts + unc_m_pmm_wpq_inserts + unc_m_pmm_wpq_inserts + unc_m_pmm_wpq_inserts + unc_m_pmm_wpq_inserts + unc_m_pmm_wpq_inserts + +For this multiple events case, it's not supported well. + +This patch introduces a new field 'metric_leader' in struct evsel. The +first event is considered as a metric leader. For the rest of same +events, they point to the first event via it's metric_leader field in +struct evsel. + +This design is for adding the counting results of all same events to the +first event in group (the metric_leader). + +With this patch, + + root@lkp-csl-2sp2:~# perf stat -M UNC_M_PMM_BANDWIDTH.TOTAL -a -- sleep 1 + + Performance counter stats for 'system wide': + + 1842108 unc_m_pmm_rpq_inserts # 337.2 MB/sec UNC_M_PMM_BANDWIDTH.TOTAL + 3682209 unc_m_pmm_wpq_inserts + + 1.001819706 seconds time elapsed + + root@lkp-csl-2sp2:~# perf stat -M UNC_M_PMM_READ_LATENCY -a -- sleep 1 + + Performance counter stats for 'system wide': + + 861970685 unc_m_pmm_rpq_occupancy.all # 219.4 ns UNC_M_PMM_READ_LATENCY + 1842772 unc_m_pmm_rpq_inserts + 12790196356 unc_m_clockticks + + 1.001749103 seconds time elapsed + +Now we can see the correct metrics 'UNC_M_PMM_BANDWIDTH.TOTAL' and +'UNC_M_PMM_READ_LATENCY'. + +Signed-off-by: Jin Yao +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20190828055932.8269-5-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/evsel.h | 1 + + tools/perf/util/metricgroup.c | 90 ++++++++++++++++++----------------- + tools/perf/util/stat-shadow.c | 27 +++++++++-- + 3 files changed, 71 insertions(+), 47 deletions(-) + +diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h +index dab3930e2a8c..be63c73ca69c 100644 +--- a/tools/perf/util/evsel.h ++++ b/tools/perf/util/evsel.h +@@ -149,6 +149,7 @@ struct perf_evsel { + const char * metric_expr; + const char * metric_name; + struct perf_evsel **metric_events; ++ struct perf_evsel *metric_leader; + bool collect_stat; + bool weak_group; + const char *pmu_name; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index d01f16448bab..375866dab75b 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -96,57 +96,61 @@ struct egroup { + const char *metric_unit; + }; + +-static bool record_evsel(int *ind, struct perf_evsel **start, +- int idnum, +- struct perf_evsel **metric_events, +- struct perf_evsel *ev) +-{ +- metric_events[*ind] = ev; +- if (*ind == 0) +- *start = ev; +- if (++*ind == idnum) { +- metric_events[*ind] = NULL; +- return true; +- } +- return false; +-} +- + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, +- const char **ids, +- int idnum, +- struct perf_evsel **metric_events) ++ const char **ids, ++ int idnum, ++ struct perf_evsel **metric_events) + { +- struct perf_evsel *ev, *start = NULL; +- int ind = 0; ++ struct perf_evsel *ev; ++ int i = 0; ++ bool leader_found; + + evlist__for_each_entry (perf_evlist, ev) { +- if (ev->collect_stat) +- continue; +- if (!strcmp(ev->name, ids[ind])) { +- if (record_evsel(&ind, &start, idnum, +- metric_events, ev)) +- return start; ++ if (!strcmp(ev->name, ids[i])) { ++ if (!metric_events[i]) ++ metric_events[i] = ev; + } else { +- /* +- * We saw some other event that is not +- * in our list of events. Discard +- * the whole match and start again. +- */ +- ind = 0; +- start = NULL; +- if (!strcmp(ev->name, ids[ind])) { +- if (record_evsel(&ind, &start, idnum, +- metric_events, ev)) +- return start; ++ if (++i == idnum) { ++ /* Discard the whole match and start again */ ++ i = 0; ++ memset(metric_events, 0, ++ sizeof(struct evsel *) * idnum); ++ continue; ++ } ++ ++ if (!strcmp(ev->name, ids[i])) ++ metric_events[i] = ev; ++ else { ++ /* Discard the whole match and start again */ ++ i = 0; ++ memset(metric_events, 0, ++ sizeof(struct evsel *) * idnum); ++ continue; + } + } + } +- /* +- * This can happen when an alias expands to multiple +- * events, like for uncore events. +- * We don't support this case for now. +- */ +- return NULL; ++ ++ if (i != idnum - 1) { ++ /* Not whole match */ ++ return NULL; ++ } ++ ++ metric_events[idnum] = NULL; ++ ++ for (i = 0; i < idnum; i++) { ++ leader_found = false; ++ evlist__for_each_entry(perf_evlist, ev) { ++ if (!leader_found && (ev == metric_events[i])) ++ leader_found = true; ++ ++ if (leader_found && ++ !strcmp(ev->name, metric_events[i]->name)) { ++ ev->metric_leader = metric_events[i]; ++ } ++ } ++ } ++ ++ return metric_events[0]; + } + + static int metricgroup__setup_events(struct list_head *groups, +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index f687ca257e5d..a274f04cbeee 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -29,6 +29,8 @@ struct saved_value { + int cpu; + struct runtime_stat *stat; + struct stats stats; ++ u64 metric_total; ++ int metric_other; + }; + + static int saved_value_cmp(struct rb_node *rb_node, const void *entry) +@@ -210,6 +212,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, + { + int ctx = evsel_context(counter); + u64 count_ns = count; ++ struct saved_value *v; + + count *= counter->scale; + +@@ -264,9 +267,15 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, + update_runtime_stat(st, STAT_APERF, ctx, cpu, count); + + if (counter->collect_stat) { +- struct saved_value *v = saved_value_lookup(counter, cpu, true, +- STAT_NONE, 0, st); ++ v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st); + update_stats(&v->stats, count); ++ if (counter->metric_leader) ++ v->metric_total += count; ++ } else if (counter->metric_leader) { ++ v = saved_value_lookup(counter->metric_leader, ++ cpu, true, STAT_NONE, 0, st); ++ v->metric_total += count; ++ v->metric_other++; + } + } + +@@ -727,10 +736,10 @@ static void generic_metric(struct perf_stat_config *config, + char *n, *pn; + + expr__ctx_init(&pctx); +- expr__add_id(&pctx, name, avg); + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; ++ u64 metric_total = 0; + + if (!strcmp(metric_events[i]->name, "duration_time")) { + stats = &walltime_nsecs_stats; +@@ -742,6 +751,9 @@ static void generic_metric(struct perf_stat_config *config, + break; + stats = &v->stats; + scale = 1.0; ++ ++ if (v->metric_other) ++ metric_total = v->metric_total; + } + + n = strdup(metric_events[i]->name); +@@ -755,8 +767,15 @@ static void generic_metric(struct perf_stat_config *config, + pn = strchr(n, ' '); + if (pn) + *pn = 0; +- expr__add_id(&pctx, n, avg_stats(stats)*scale); ++ ++ if (metric_total) ++ expr__add_id(&pctx, n, metric_total); ++ else ++ expr__add_id(&pctx, n, avg_stats(stats)*scale); + } ++ ++ expr__add_id(&pctx, name, avg); ++ + if (!metric_events[i]) { + const char *p = metric_expr; + +-- +2.27.0 + diff --git a/patches/0141-perf-pmu-Support-more-complex-PMU-event-aliasing.patch b/patches/0141-perf-pmu-Support-more-complex-PMU-event-aliasing.patch new file mode 100644 index 0000000..3e34bb9 --- /dev/null +++ b/patches/0141-perf-pmu-Support-more-complex-PMU-event-aliasing.patch @@ -0,0 +1,124 @@ +From 837ab95c606351cf258959cd33f9b2a7d3c0b5f9 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 28 Jun 2019 22:35:49 +0800 +Subject: [PATCH 024/201] perf pmu: Support more complex PMU event aliasing + +mainline inclusion +from mainline-v5.3-rc1 +commit 730670b1d108c4a8aa1924762738ca38593ee44c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=730670b1d108c4a8aa1924762738ca38593ee44c + +------------------------------------------------------------------------ + +The jevent "Unit" field is used for uncore PMU alias definition. + +The form uncore_pmu_example_X is supported, where "X" is a wildcard, to +support multiple instances of the same PMU in a system. + +Unfortunately this format not suitable for all uncore PMUs; take the +Hisi DDRC uncore PMU for example, where the name is in the form +hisi_scclX_ddrcY. + +For for current jevent parsing, we would be required to hardcode an +uncore alias translation for each possible value of X. This is not +scalable. + +Instead, add support for "Unit" field in the form "hisi_sccl,ddrc", +where we can match by hisi_scclX and ddrcY. Tokens in Unit field are +delimited by ','. + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ben Hutchings +Cc: Hendrik Brueckner +Cc: Kan Liang +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Thomas Richter +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lkml.kernel.org/r/1561732552-143038-2-git-send-email-john.garry@huawei.com +[ Shut up older gcc complianing about the last arg to strtok_r() being uninitialized, set that tmp to NULL ] +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 46 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 41 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 256a9792bd7e..147989e2bff0 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -741,6 +741,46 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) + return map; + } + ++static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) ++{ ++ char *tmp = NULL, *tok, *str; ++ bool res; ++ ++ str = strdup(pmu_name); ++ if (!str) ++ return false; ++ ++ /* ++ * uncore alias may be from different PMU with common prefix ++ */ ++ tok = strtok_r(str, ",", &tmp); ++ if (strncmp(pmu_name, tok, strlen(tok))) { ++ res = false; ++ goto out; ++ } ++ ++ /* ++ * Match more complex aliases where the alias name is a comma-delimited ++ * list of tokens, orderly contained in the matching PMU name. ++ * ++ * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we ++ * match "socket" in "socketX_pmunameY" and then "pmuname" in ++ * "pmunameY". ++ */ ++ for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) { ++ name = strstr(name, tok); ++ if (!name) { ++ res = false; ++ goto out; ++ } ++ } ++ ++ res = true; ++out: ++ free(str); ++ return res; ++} ++ + /* + * From the pmu_events_map, find the table of PMU events that corresponds + * to the current running CPU. Then, add all PMU events from that table +@@ -771,12 +811,8 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) + break; + } + +- /* +- * uncore alias may be from different PMU +- * with common prefix +- */ + if (pmu_is_uncore(name) && +- !strncmp(pname, name, strlen(pname))) ++ pmu_uncore_alias_match(pname, name)) + goto new_alias; + + if (strcmp(pname, name)) +-- +2.27.0 + diff --git a/patches/0142-perf-jevents-Add-support-for-Hisi-hip08-DDRC-PMU-ali.patch b/patches/0142-perf-jevents-Add-support-for-Hisi-hip08-DDRC-PMU-ali.patch new file mode 100644 index 0000000..1615b29 --- /dev/null +++ b/patches/0142-perf-jevents-Add-support-for-Hisi-hip08-DDRC-PMU-ali.patch @@ -0,0 +1,153 @@ +From 23613a50c4e84e51444051ba608de3cc45cc3ad9 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 28 Jun 2019 22:35:50 +0800 +Subject: [PATCH 025/201] perf jevents: Add support for Hisi hip08 DDRC PMU + aliasing + +mainline inclusion +from mainline-v5.3-rc1 +commit 57cc732479bac2a3cbd759fb07188657c871d5c1 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=57cc732479bac2a3cbd759fb07188657c871d5c1 + +------------------------------------------------------------------------ + +Add support for Hisi hip08 DDRC PMU aliasing. We can now do something like +this: + +$perf list + +[snip] + +uncore ddrc: + uncore_hisi_ddrc.act_cmd + [DDRC active commands. Unit: hisi_sccl,ddrc] + uncore_hisi_ddrc.flux_rcmd + [DDRC read commands. Unit: hisi_sccl,ddrc] + uncore_hisi_ddrc.flux_wcmd + [DDRC write commands. Unit: hisi_sccl,ddrc] + uncore_hisi_ddrc.flux_wr + [DDRC precharge commands. Unit: hisi_sccl,ddrc] + uncore_hisi_ddrc.rnk_chg + [DDRC rank commands. Unit: hisi_sccl,ddrc] + uncore_hisi_ddrc.rw_chg + [DDRC read and write changes. Unit: hisi_sccl,ddrc] + +Performance counter stats for 'system wide': + + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl1_ddrc0] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl3_ddrc1] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl5_ddrc2] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl7_ddrc3] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl5_ddrc0] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl7_ddrc1] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl1_ddrc3] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl1_ddrc1] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl3_ddrc2] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl5_ddrc3] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl3_ddrc0] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl5_ddrc1] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl7_ddrc2] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl7_ddrc0] + 20,421 uncore_hisi_ddrc.flux_rcmd [hisi_sccl1_ddrc2] + 0 uncore_hisi_ddrc.flux_rcmd [hisi_sccl3_ddrc3] + + 1.001559011 seconds time elapsed + +The kernel driver is in drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ben Hutchings +Cc: Hendrik Brueckner +Cc: Kan Liang +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Thomas Richter +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lkml.kernel.org/r/1561732552-143038-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/pmu-events/jevents.c +--- + .../arm64/hisilicon/hip08/uncore-ddrc.json | 44 +++++++++++++++++++ + tools/perf/pmu-events/jevents.c | 1 + + 2 files changed, 45 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +new file mode 100644 +index 000000000000..0d1556fcdffe +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +@@ -0,0 +1,44 @@ ++[ ++ { ++ "EventCode": "0x02", ++ "EventName": "uncore_hisi_ddrc.flux_wcmd", ++ "BriefDescription": "DDRC write commands", ++ "PublicDescription": "DDRC write commands", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x03", ++ "EventName": "uncore_hisi_ddrc.flux_rcmd", ++ "BriefDescription": "DDRC read commands", ++ "PublicDescription": "DDRC read commands", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x04", ++ "EventName": "uncore_hisi_ddrc.flux_wr", ++ "BriefDescription": "DDRC precharge commands", ++ "PublicDescription": "DDRC precharge commands", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x05", ++ "EventName": "uncore_hisi_ddrc.act_cmd", ++ "BriefDescription": "DDRC active commands", ++ "PublicDescription": "DDRC active commands", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x06", ++ "EventName": "uncore_hisi_ddrc.rnk_chg", ++ "BriefDescription": "DDRC rank commands", ++ "PublicDescription": "DDRC rank commands", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x07", ++ "EventName": "uncore_hisi_ddrc.rw_chg", ++ "BriefDescription": "DDRC read and write changes", ++ "PublicDescription": "DDRC read and write changes", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++] +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 55c8bf2b0b32..e3c8b4b34cb0 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -238,6 +238,7 @@ static struct map { + { "UPI LL", "uncore_upi" }, + { "L3PMC", "amd_l3" }, + { "DFPMC", "amd_df" }, ++ { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, + {} + }; + +-- +2.27.0 + diff --git a/patches/0143-perf-jevents-Add-support-for-Hisi-hip08-HHA-PMU-alia.patch b/patches/0143-perf-jevents-Add-support-for-Hisi-hip08-HHA-PMU-alia.patch new file mode 100644 index 0000000..a9229e6 --- /dev/null +++ b/patches/0143-perf-jevents-Add-support-for-Hisi-hip08-HHA-PMU-alia.patch @@ -0,0 +1,117 @@ +From 0c6076da3c1b6c6bde349c706f196dea620cd0e5 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 28 Jun 2019 22:35:51 +0800 +Subject: [PATCH 026/201] perf jevents: Add support for Hisi hip08 HHA PMU + aliasing + +mainline inclusion +from mainline-v5.3-rc1 +commit 8f5b703add99473b59b4a38a6b66afbafc29d92e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8f5b703add99473b59b4a38a6b66afbafc29d92e + +------------------------------------------------------------------------ + +Add support for Hisi hip08 HHA PMU aliasing. + +The kernel driver is in drivers/perf/hisilicon/hisi_uncore_hha_pmu.c + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ben Hutchings +Cc: Hendrik Brueckner +Cc: Kan Liang +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Thomas Richter +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lkml.kernel.org/r/1561732552-143038-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip08/uncore-hha.json | 51 +++++++++++++++++++ + tools/perf/pmu-events/jevents.c | 1 + + 2 files changed, 52 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +new file mode 100644 +index 000000000000..447d3064de90 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +@@ -0,0 +1,51 @@ ++[ ++ { ++ "EventCode": "0x00", ++ "EventName": "uncore_hisi_hha.rx_ops_num", ++ "BriefDescription": "The number of all operations received by the HHA", ++ "PublicDescription": "The number of all operations received by the HHA", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x01", ++ "EventName": "uncore_hisi_hha.rx_outer", ++ "BriefDescription": "The number of all operations received by the HHA from another socket", ++ "PublicDescription": "The number of all operations received by the HHA from another socket", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x02", ++ "EventName": "uncore_hisi_hha.rx_sccl", ++ "BriefDescription": "The number of all operations received by the HHA from another SCCL in this socket", ++ "PublicDescription": "The number of all operations received by the HHA from another SCCL in this socket", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x1c", ++ "EventName": "uncore_hisi_hha.rd_ddr_64b", ++ "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 64 bytes", ++ "PublicDescription": "The number of read operations sent by HHA to DDRC which size is 64bytes", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x1d", ++ "EventName": "uncore_hisi_hha.wr_dr_64b", ++ "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", ++ "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x1e", ++ "EventName": "uncore_hisi_hha.rd_ddr_128b", ++ "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes", ++ "PublicDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x1f", ++ "EventName": "uncore_hisi_hha.wr_ddr_128b", ++ "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", ++ "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", ++ "Unit": "hisi_sccl,hha", ++ }, ++] +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index e3c8b4b34cb0..24223bac1993 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -239,6 +239,7 @@ static struct map { + { "L3PMC", "amd_l3" }, + { "DFPMC", "amd_df" }, + { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, ++ { "hisi_sccl,hha", "hisi_sccl,hha" }, + {} + }; + +-- +2.27.0 + diff --git a/patches/0144-perf-jevents-Add-support-for-Hisi-hip08-L3C-PMU-alia.patch b/patches/0144-perf-jevents-Add-support-for-Hisi-hip08-L3C-PMU-alia.patch new file mode 100644 index 0000000..5a8ba30 --- /dev/null +++ b/patches/0144-perf-jevents-Add-support-for-Hisi-hip08-L3C-PMU-alia.patch @@ -0,0 +1,103 @@ +From 5b4c2a0be90df3842095d9ed3bbd5d0bfef4ef30 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 28 Jun 2019 22:35:52 +0800 +Subject: [PATCH 027/201] perf jevents: Add support for Hisi hip08 L3C PMU + aliasing + +mainline inclusion +from mainline-v5.3-rc1 +commit edd93a4076cf18ede423c167de6d6fb8e4211e7b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=edd93a4076cf18ede423c167de6d6fb8e4211e7b + +------------------------------------------------------------------------ + +Add support for Hisi hip08 L3C PMU aliasing. + +The kernel driver is in drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ben Hutchings +Cc: Hendrik Brueckner +Cc: Kan Liang +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Thomas Richter +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lkml.kernel.org/r/1561732552-143038-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip08/uncore-l3c.json | 37 +++++++++++++++++++ + tools/perf/pmu-events/jevents.c | 1 + + 2 files changed, 38 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +new file mode 100644 +index 000000000000..ca48747642e1 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +@@ -0,0 +1,37 @@ ++[ ++ { ++ "EventCode": "0x00", ++ "EventName": "uncore_hisi_l3c.rd_cpipe", ++ "BriefDescription": "Total read accesses", ++ "PublicDescription": "Total read accesses", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x01", ++ "EventName": "uncore_hisi_l3c.wr_cpipe", ++ "BriefDescription": "Total write accesses", ++ "PublicDescription": "Total write accesses", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x02", ++ "EventName": "uncore_hisi_l3c.rd_hit_cpipe", ++ "BriefDescription": "Total read hits", ++ "PublicDescription": "Total read hits", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x03", ++ "EventName": "uncore_hisi_l3c.wr_hit_cpipe", ++ "BriefDescription": "Total write hits", ++ "PublicDescription": "Total write hits", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x04", ++ "EventName": "uncore_hisi_l3c.victim_num", ++ "BriefDescription": "l3c precharge commands", ++ "PublicDescription": "l3c precharge commands", ++ "Unit": "hisi_sccl,l3c", ++ }, ++] +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 24223bac1993..b6960ef3a553 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -240,6 +240,7 @@ static struct map { + { "DFPMC", "amd_df" }, + { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, + { "hisi_sccl,hha", "hisi_sccl,hha" }, ++ { "hisi_sccl,l3c", "hisi_sccl,l3c" }, + {} + }; + +-- +2.27.0 + diff --git a/patches/0145-perf-vendor-events-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch b/patches/0145-perf-vendor-events-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch new file mode 100644 index 0000000..79e5fd5 --- /dev/null +++ b/patches/0145-perf-vendor-events-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch @@ -0,0 +1,52 @@ +From d1a1248e70094869a82c8f3b43e80718e4d211eb Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 4 Sep 2019 23:54:41 +0800 +Subject: [PATCH 028/201] perf vendor events arm64: Fix Hisi hip08 DDRC PMU + eventname + +mainline inclusion +from mainline-v5.5-rc1 +commit 84b0975f4853ba32d2d9b3c19ffa2b947f023fb3 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=84b0975f4853ba32d2d9b3c19ffa2b947f023fb3 + +------------------------------------------------------------------------ + +The "EventName" for the DDRC precharge command event is incorrect, so +fix it. + +Fixes: 57cc732479ba ("perf jevents: Add support for Hisi hip08 DDRC PMU aliasing") +Signed-off-by: John Garry +Reviewed-by: Shaokun Zhang +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1567612484-195727-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +index 0d1556fcdffe..99f4fc425564 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +@@ -15,7 +15,7 @@ + }, + { + "EventCode": "0x04", +- "EventName": "uncore_hisi_ddrc.flux_wr", ++ "EventName": "uncore_hisi_ddrc.pre_cmd", + "BriefDescription": "DDRC precharge commands", + "PublicDescription": "DDRC precharge commands", + "Unit": "hisi_sccl,ddrc", +-- +2.27.0 + diff --git a/patches/0146-perf-vendor-events-arm64-Add-some-missing-events-for.patch b/patches/0146-perf-vendor-events-arm64-Add-some-missing-events-for.patch new file mode 100644 index 0000000..8928a66 --- /dev/null +++ b/patches/0146-perf-vendor-events-arm64-Add-some-missing-events-for.patch @@ -0,0 +1,60 @@ +From 2ba983a40018104ce95c97db4ab9fcb7ff91f974 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 4 Sep 2019 23:54:42 +0800 +Subject: [PATCH 029/201] perf vendor events arm64: Add some missing events for + Hisi hip08 DDRC PMU + +mainline inclusion +from mainline-v5.5-rc1 +commit 1410732a1b642ba82730a95bdf7f4dafbac1891a +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1410732a1b642ba82730a95bdf7f4dafbac1891a + +------------------------------------------------------------------------ + +Add some more missing events. + +Signed-off-by: John Garry +Reviewed-by: Shaokun Zhang +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1567612484-195727-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/arm64/hisilicon/hip08/uncore-ddrc.json | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +index 99f4fc425564..7da86942dae2 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +@@ -1,4 +1,18 @@ + [ ++ { ++ "EventCode": "0x00", ++ "EventName": "uncore_hisi_ddrc.flux_wr", ++ "BriefDescription": "DDRC total write operations", ++ "PublicDescription": "DDRC total write operations", ++ "Unit": "hisi_sccl,ddrc", ++ }, ++ { ++ "EventCode": "0x01", ++ "EventName": "uncore_hisi_ddrc.flux_rd", ++ "BriefDescription": "DDRC total read operations", ++ "PublicDescription": "DDRC total read operations", ++ "Unit": "hisi_sccl,ddrc", ++ }, + { + "EventCode": "0x02", + "EventName": "uncore_hisi_ddrc.flux_wcmd", +-- +2.27.0 + diff --git a/patches/0147-perf-vendor-events-arm64-Add-some-missing-events-for.patch b/patches/0147-perf-vendor-events-arm64-Add-some-missing-events-for.patch new file mode 100644 index 0000000..8f1670c --- /dev/null +++ b/patches/0147-perf-vendor-events-arm64-Add-some-missing-events-for.patch @@ -0,0 +1,102 @@ +From 512e47929f31707b18b9345c7dd172e48eb451a0 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 4 Sep 2019 23:54:43 +0800 +Subject: [PATCH 030/201] perf vendor events arm64: Add some missing events for + Hisi hip08 L3C PMU + +mainline inclusion +from mainline-v5.5-rc1 +commit e3ae569541802a6c9e89ab1f0f3ff613a5a1237b +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e3ae569541802a6c9e89ab1f0f3ff613a5a1237b + +------------------------------------------------------------------------ + +Add some more missing events. + +Signed-off-by: John Garry +Reviewed-by: Shaokun Zhang +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1567612484-195727-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip08/uncore-l3c.json | 56 +++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +index ca48747642e1..f463d0acfaef 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +@@ -34,4 +34,60 @@ + "PublicDescription": "l3c precharge commands", + "Unit": "hisi_sccl,l3c", + }, ++ { ++ "EventCode": "0x20", ++ "EventName": "uncore_hisi_l3c.rd_spipe", ++ "BriefDescription": "Count of the number of read lines that come from this cluster of CPU core in spipe", ++ "PublicDescription": "Count of the number of read lines that come from this cluster of CPU core in spipe", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x21", ++ "EventName": "uncore_hisi_l3c.wr_spipe", ++ "BriefDescription": "Count of the number of write lines that come from this cluster of CPU core in spipe", ++ "PublicDescription": "Count of the number of write lines that come from this cluster of CPU core in spipe", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x22", ++ "EventName": "uncore_hisi_l3c.rd_hit_spipe", ++ "BriefDescription": "Count of the number of read lines that hits in spipe of this L3C", ++ "PublicDescription": "Count of the number of read lines that hits in spipe of this L3C", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x23", ++ "EventName": "uncore_hisi_l3c.wr_hit_spipe", ++ "BriefDescription": "Count of the number of write lines that hits in spipe of this L3C", ++ "PublicDescription": "Count of the number of write lines that hits in spipe of this L3C", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x29", ++ "EventName": "uncore_hisi_l3c.back_invalid", ++ "BriefDescription": "Count of the number of L3C back invalid operations", ++ "PublicDescription": "Count of the number of L3C back invalid operations", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x40", ++ "EventName": "uncore_hisi_l3c.retry_cpu", ++ "BriefDescription": "Count of the number of retry that L3C suppresses the CPU operations", ++ "PublicDescription": "Count of the number of retry that L3C suppresses the CPU operations", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x41", ++ "EventName": "uncore_hisi_l3c.retry_ring", ++ "BriefDescription": "Count of the number of retry that L3C suppresses the ring operations", ++ "PublicDescription": "Count of the number of retry that L3C suppresses the ring operations", ++ "Unit": "hisi_sccl,l3c", ++ }, ++ { ++ "EventCode": "0x42", ++ "EventName": "uncore_hisi_l3c.prefetch_drop", ++ "BriefDescription": "Count of the number of prefetch drops from this L3C", ++ "PublicDescription": "Count of the number of prefetch drops from this L3C", ++ "Unit": "hisi_sccl,l3c", ++ }, + ] +-- +2.27.0 + diff --git a/patches/0148-perf-vendor-events-arm64-Add-some-missing-events-for.patch b/patches/0148-perf-vendor-events-arm64-Add-some-missing-events-for.patch new file mode 100644 index 0000000..7665b09 --- /dev/null +++ b/patches/0148-perf-vendor-events-arm64-Add-some-missing-events-for.patch @@ -0,0 +1,85 @@ +From 394d1db77007ebac4a69b73c690901ebf4dc733a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 4 Sep 2019 23:54:44 +0800 +Subject: [PATCH 031/201] perf vendor events arm64: Add some missing events for + Hisi hip08 HHA PMU + +mainline inclusion +from mainline-v5.5-rc1 +commit 2b7847158120136c4b23684c768a82d571ee59bf +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2b7847158120136c4b23684c768a82d571ee59bf + +------------------------------------------------------------------------ + +Add some more missing events. + +A trivial typo is also fixed. + +Signed-off-by: John Garry +Reviewed-by: Shaokun Zhang +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1567612484-195727-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip08/uncore-hha.json | 23 ++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +index 447d3064de90..3be418a248ea 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +@@ -20,6 +20,13 @@ + "PublicDescription": "The number of all operations received by the HHA from another SCCL in this socket", + "Unit": "hisi_sccl,hha", + }, ++ { ++ "EventCode": "0x03", ++ "EventName": "uncore_hisi_hha.rx_ccix", ++ "BriefDescription": "Count of the number of operations that HHA has received from CCIX", ++ "PublicDescription": "Count of the number of operations that HHA has received from CCIX", ++ "Unit": "hisi_sccl,hha", ++ }, + { + "EventCode": "0x1c", + "EventName": "uncore_hisi_hha.rd_ddr_64b", +@@ -29,7 +36,7 @@ + }, + { + "EventCode": "0x1d", +- "EventName": "uncore_hisi_hha.wr_dr_64b", ++ "EventName": "uncore_hisi_hha.wr_ddr_64b", + "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", + "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", + "Unit": "hisi_sccl,hha", +@@ -48,4 +55,18 @@ + "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", + "Unit": "hisi_sccl,hha", + }, ++ { ++ "EventCode": "0x20", ++ "EventName": "uncore_hisi_hha.spill_num", ++ "BriefDescription": "Count of the number of spill operations that the HHA has sent", ++ "PublicDescription": "Count of the number of spill operations that the HHA has sent", ++ "Unit": "hisi_sccl,hha", ++ }, ++ { ++ "EventCode": "0x21", ++ "EventName": "uncore_hisi_hha.spill_success", ++ "BriefDescription": "Count of the number of successful spill operations that the HHA has sent", ++ "PublicDescription": "Count of the number of successful spill operations that the HHA has sent", ++ "Unit": "hisi_sccl,hha", ++ }, + ] +-- +2.27.0 + diff --git a/patches/0149-perf-stat-Fix-free-memory-access-memory-leaks-in-met.patch b/patches/0149-perf-stat-Fix-free-memory-access-memory-leaks-in-met.patch new file mode 100644 index 0000000..b0d12de --- /dev/null +++ b/patches/0149-perf-stat-Fix-free-memory-access-memory-leaks-in-met.patch @@ -0,0 +1,124 @@ +From 1ce326c8887a25381760da2070d9bfd1934bd068 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Mon, 23 Sep 2019 16:33:39 -0700 +Subject: [PATCH 032/201] perf stat: Fix free memory access / memory leaks in + metrics + +mainline inclusion +from mainline-v5.4-rc1 +commit 6f6473c37d34b00676a152ec7e60770c78ed7c2f +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6f6473c37d34b00676a152ec7e60770c78ed7c2f + +------------------------------------------------------------------------ + +Make sure to not free the name passed in by the caller, but free all the +allocated ids when parsing expressions. + +The loop at the end knows that the first entry shouldn't be freed, so +make sure the caller name is the first entry. + +Fixes + + % perf stat -M IpB,IpCall,IpTB,IPC,Retiring_SMT,Frontend_Bound_SMT,Kernel_Utilization,CPU_Utilization --metric-only -a -I 1000 sleep 2 + + valgrind: + 1.009943231 ==21527== Invalid read of size 1 + ==21527== at 0x483CB74: strcmp (vg_replace_strmem.c:849) + ==21527== by 0x582CF8: collect_all_aliases (stat-display.c:554) + ==21527== by 0x582EB3: collect_data (stat-display.c:577) + ==21527== by 0x583A32: print_counter_aggr (stat-display.c:806) + ==21527== by 0x584FAD: perf_evlist__print_counters (stat-display.c:1200) + ==21527== by 0x45133A: print_counters (builtin-stat.c:655) + ==21527== by 0x450629: process_interval (builtin-stat.c:353) + ==21527== by 0x450FBD: __run_perf_stat (builtin-stat.c:564) + ==21527== by 0x451285: run_perf_stat (builtin-stat.c:636) + ==21527== by 0x454619: cmd_stat (builtin-stat.c:1966) + ==21527== by 0x4D557D: run_builtin (perf.c:310) + ==21527== by 0x4D57EA: handle_internal_command (perf.c:362) + ==21527== Address 0x12826cd0 is 0 bytes inside a block of size 25 free'd + ==21527== at 0x4839A0C: free (vg_replace_malloc.c:540) + ==21527== by 0x627041: __zfree (zalloc.c:13) + ==21527== by 0x57F66A: generic_metric (stat-shadow.c:814) + ==21527== by 0x580B21: perf_stat__print_shadow_stats (stat-shadow.c:1057) + ==21527== by 0x58418E: print_metric_headers (stat-display.c:943) + ==21527== by 0x5844BC: print_interval (stat-display.c:1004) + ==21527== by 0x584DEB: perf_evlist__print_counters (stat-display.c:1172) + ==21527== by 0x45133A: print_counters (builtin-stat.c:655) + ==21527== by 0x450629: process_interval (builtin-stat.c:353) + ==21527== by 0x450FBD: __run_perf_stat (builtin-stat.c:564) + ==21527== by 0x451285: run_perf_stat (builtin-stat.c:636) + ==21527== by 0x454619: cmd_stat (builtin-stat.c:1966) + ==21527== Block was alloc'd at + ==21527== at 0x483880B: malloc (vg_replace_malloc.c:309) + ==21527== by 0x51677DE: strdup (in /usr/lib64/libc-2.29.so) + ==21527== by 0x506457: parse_events_name (parse-events.c:1754) + ==21527== by 0x5550BB: parse_events_parse (parse-events.y:214) + ==21527== by 0x50694D: parse_events__scanner (parse-events.c:1887) + ==21527== by 0x506AEF: parse_events (parse-events.c:1927) + ==21527== by 0x521D8B: metricgroup__parse_groups (metricgroup.c:527) + ==21527== by 0x45156F: parse_metric_groups (builtin-stat.c:721) + ==21527== by 0x6228A9: get_value (parse-options.c:243) + ==21527== by 0x62363F: parse_short_opt (parse-options.c:348) + ==21527== by 0x62363F: parse_options_step (parse-options.c:536) + ==21527== by 0x62363F: parse_options_subcommand (parse-options.c:651) + ==21527== by 0x453C1D: cmd_stat (builtin-stat.c:1718) + ==21527== by 0x4D557D: run_builtin (perf.c:310) + +and also a leak report. + +Committer testing: + +Before: + + # perf stat -M IpB,IpCall,IpTB,IPC,Retiring_SMT,Frontend_Bound_SMT,Kernel_Utilization,CPU_Utilization --metric-only -a -I 1000 sleep 2 + # time CPU_Utilization + 1.000470810 free(): double free detected in tcache 2 + Aborted (core dumped) + # + +After: + + # perf stat -M IpB,IpCall,IpTB,IPC,Retiring_SMT,Frontend_Bound_SMT,Kernel_Utilization,CPU_Utilization --metric-only -a -I 1000 sleep 2 + # time CPU_Utilization + 1.000494752 0.1 + 2.001105112 0.1 + # + +Signed-off-by: Andi Kleen +Acked-by: Jiri Olsa +Tested-by: Arnaldo Carvalho de Melo +Link: http://lore.kernel.org/lkml/20190923233339.25326-3-andi@firstfloor.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/stat-shadow.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index a274f04cbeee..c9d92c1dac0e 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -736,6 +736,8 @@ static void generic_metric(struct perf_stat_config *config, + char *n, *pn; + + expr__ctx_init(&pctx); ++ /* Must be first id entry */ ++ expr__add_id(&pctx, name, avg); + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; +@@ -774,8 +776,6 @@ static void generic_metric(struct perf_stat_config *config, + expr__add_id(&pctx, n, avg_stats(stats)*scale); + } + +- expr__add_id(&pctx, name, avg); +- + if (!metric_events[i]) { + const char *p = metric_expr; + +-- +2.27.0 + diff --git a/patches/0150-perf-tools-Move-ALLOC_LIST-into-a-function.patch b/patches/0150-perf-tools-Move-ALLOC_LIST-into-a-function.patch new file mode 100644 index 0000000..63e7018 --- /dev/null +++ b/patches/0150-perf-tools-Move-ALLOC_LIST-into-a-function.patch @@ -0,0 +1,236 @@ +From 272232b23a91bc246d17a1117162180670de1c92 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Tue, 22 Oct 2019 17:53:32 -0700 +Subject: [PATCH 033/201] perf tools: Move ALLOC_LIST into a function + +mainline inclusion +from mainline-v5.5-rc1 +commit a26e47162d7670ddea4f67978ecf848dc23ef671 +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a26e47162d7670ddea4f67978ecf848dc23ef671 + +------------------------------------------------------------------------ + +Having a YYABORT in a macro makes it hard to free memory for components +of a rule. Separate the logic out. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Alexei Starovoitov +Cc: Andi Kleen +Cc: Daniel Borkmann +Cc: Jin Yao +Cc: John Garry +Cc: Kan Liang +Cc: Mark Rutland +Cc: Martin KaFai Lau +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Stephane Eranian +Cc: Yonghong Song +Cc: bpf@vger.kernel.org +Cc: clang-built-linux@googlegroups.com +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20191023005337.196160-5-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/parse-events.y | 65 ++++++++++++++++++++++------------ + 1 file changed, 43 insertions(+), 22 deletions(-) + +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index a2c7b6fb1fd5..ef4c83b07c22 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -27,12 +27,17 @@ do { \ + YYABORT; \ + } while (0) + +-#define ALLOC_LIST(list) \ +-do { \ +- list = malloc(sizeof(*list)); \ +- ABORT_ON(!list); \ +- INIT_LIST_HEAD(list); \ +-} while (0) ++static struct list_head* alloc_list() ++{ ++ struct list_head *list; ++ ++ list = malloc(sizeof(*list)); ++ if (!list) ++ return NULL; ++ ++ INIT_LIST_HEAD(list); ++ return list; ++} + + static void inc_group_count(struct list_head *list, + struct parse_events_state *parse_state) +@@ -240,7 +245,8 @@ PE_NAME opt_pmu_config + if (error) + error->idx = @1.first_column; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) { + struct perf_pmu *pmu = NULL; + int ok = 0; +@@ -308,7 +314,8 @@ value_sym '/' event_config '/' + int type = $1 >> 16; + int config = $1 & 255; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, $3)); + parse_events_terms__delete($3); + $$ = list; +@@ -320,7 +327,8 @@ value_sym sep_slash_slash_dc + int type = $1 >> 16; + int config = $1 & 255; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL)); + $$ = list; + } +@@ -329,7 +337,8 @@ PE_VALUE_SYM_TOOL sep_slash_slash_dc + { + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); + $$ = list; + } +@@ -341,7 +350,8 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_e + struct parse_events_error *error = parse_state->error; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6)); + parse_events_terms__delete($6); + $$ = list; +@@ -353,7 +363,8 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config + struct parse_events_error *error = parse_state->error; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4)); + parse_events_terms__delete($4); + $$ = list; +@@ -365,7 +376,8 @@ PE_NAME_CACHE_TYPE opt_event_config + struct parse_events_error *error = parse_state->error; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2)); + parse_events_terms__delete($2); + $$ = list; +@@ -377,7 +389,8 @@ PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc + struct parse_events_state *parse_state = _parse_state; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx, + (void *) $2, $6, $4)); + $$ = list; +@@ -388,7 +401,8 @@ PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc + struct parse_events_state *parse_state = _parse_state; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx, + (void *) $2, NULL, $4)); + $$ = list; +@@ -399,7 +413,8 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc + struct parse_events_state *parse_state = _parse_state; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx, + (void *) $2, $4, 0)); + $$ = list; +@@ -410,7 +425,8 @@ PE_PREFIX_MEM PE_VALUE sep_dc + struct parse_events_state *parse_state = _parse_state; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx, + (void *) $2, NULL, 0)); + $$ = list; +@@ -423,7 +439,8 @@ tracepoint_name opt_event_config + struct parse_events_error *error = parse_state->error; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + if (error) + error->idx = @1.first_column; + +@@ -459,7 +476,8 @@ PE_VALUE ':' PE_VALUE opt_event_config + { + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4)); + parse_events_terms__delete($4); + $$ = list; +@@ -470,7 +488,8 @@ PE_RAW opt_event_config + { + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2)); + parse_events_terms__delete($2); + $$ = list; +@@ -483,7 +502,8 @@ PE_BPF_OBJECT opt_event_config + struct parse_events_error *error = parse_state->error; + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_load_bpf(parse_state, list, $1, false, $2)); + parse_events_terms__delete($2); + $$ = list; +@@ -493,7 +513,8 @@ PE_BPF_SOURCE opt_event_config + { + struct list_head *list; + +- ALLOC_LIST(list); ++ list = alloc_list(); ++ ABORT_ON(!list); + ABORT_ON(parse_events_load_bpf(_parse_state, list, $1, true, $2)); + parse_events_terms__delete($2); + $$ = list; +-- +2.27.0 + diff --git a/patches/0151-perf-list-Hide-deprecated-events-by-default.patch b/patches/0151-perf-list-Hide-deprecated-events-by-default.patch new file mode 100644 index 0000000..41ce6b9 --- /dev/null +++ b/patches/0151-perf-list-Hide-deprecated-events-by-default.patch @@ -0,0 +1,393 @@ +From 2670fb710163524ae338f2736fe240abb18e9af8 Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Tue, 15 Oct 2019 10:53:57 +0800 +Subject: [PATCH 034/201] perf list: Hide deprecated events by default + +mainline inclusion +from mainline-v5.5-rc1 +commit a7f6c8c81afdd6d24eb12558f2fb66901207d349 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a7f6c8c81afdd6d24eb12558f2fb66901207d349 + +------------------------------------------------------------------------ + +There are some deprecated events listed by perf list. But we can't +remove them from perf list with ease because some old scripts may use +them. + +Deprecated events are old names of renamed events. When an event gets +renamed the old name is kept around for some time and marked with +Deprecated. The newer Intel event lists in the tree already have these +headers. + +So we need to keep them in the event list, but provide a new option to +show them. The new option is "--deprecated". + +With this patch, the deprecated events are hidden by default but they +can be displayed when option "--deprecated" is enabled. + +Signed-off-by: Jin Yao +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jin Yao +Cc: Kan Liang +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20191015025357.8708-1-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/Documentation/perf-list.txt | 3 +++ + tools/perf/builtin-list.c | 14 ++++++++++---- + tools/perf/pmu-events/jevents.c | 26 ++++++++++++++++++++------ + tools/perf/pmu-events/jevents.h | 3 ++- + tools/perf/pmu-events/pmu-events.h | 1 + + tools/perf/util/parse-events.c | 4 ++-- + tools/perf/util/parse-events.h | 2 +- + tools/perf/util/pmu.c | 17 +++++++++++++---- + tools/perf/util/pmu.h | 4 +++- + 9 files changed, 55 insertions(+), 19 deletions(-) + +diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt +index 236b9b97dfdb..54d16b4d1ede 100644 +--- a/tools/perf/Documentation/perf-list.txt ++++ b/tools/perf/Documentation/perf-list.txt +@@ -36,6 +36,9 @@ Enable debugging output. + Print how named events are resolved internally into perf events, and also + any extra expressions computed by perf stat. + ++--deprecated:: ++Print deprecated events. By default the deprecated events are hidden. ++ + [[EVENT_MODIFIERS]] + EVENT MODIFIERS + --------------- +diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c +index e4606919bda9..169f1ece7c68 100644 +--- a/tools/perf/builtin-list.c ++++ b/tools/perf/builtin-list.c +@@ -27,6 +27,7 @@ int cmd_list(int argc, const char **argv) + int i; + bool raw_dump = false; + bool long_desc_flag = false; ++ bool deprecated = false; + struct option list_options[] = { + OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), + OPT_BOOLEAN('d', "desc", &desc_flag, +@@ -35,6 +36,8 @@ int cmd_list(int argc, const char **argv) + "Print longer event descriptions."), + OPT_BOOLEAN(0, "details", &details_flag, + "Print information on the perf event names and expressions used internally by events."), ++ OPT_BOOLEAN(0, "deprecated", &deprecated, ++ "Print deprecated events."), + OPT_INCR(0, "debug", &verbose, + "Enable debugging output"), + OPT_END() +@@ -56,7 +59,7 @@ int cmd_list(int argc, const char **argv) + + if (argc == 0) { + print_events(NULL, raw_dump, !desc_flag, long_desc_flag, +- details_flag); ++ details_flag, deprecated); + return 0; + } + +@@ -79,7 +82,8 @@ int cmd_list(int argc, const char **argv) + print_hwcache_events(NULL, raw_dump); + else if (strcmp(argv[i], "pmu") == 0) + print_pmu_events(NULL, raw_dump, !desc_flag, +- long_desc_flag, details_flag); ++ long_desc_flag, details_flag, ++ deprecated); + else if (strcmp(argv[i], "sdt") == 0) + print_sdt_events(NULL, NULL, raw_dump); + else if (strcmp(argv[i], "metric") == 0) +@@ -92,7 +96,8 @@ int cmd_list(int argc, const char **argv) + if (sep == NULL) { + print_events(argv[i], raw_dump, !desc_flag, + long_desc_flag, +- details_flag); ++ details_flag, ++ deprecated); + continue; + } + sep_idx = sep - argv[i]; +@@ -118,7 +123,8 @@ int cmd_list(int argc, const char **argv) + print_hwcache_events(s, raw_dump); + print_pmu_events(s, raw_dump, !desc_flag, + long_desc_flag, +- details_flag); ++ details_flag, ++ deprecated); + print_tracepoint_events(NULL, s, raw_dump); + print_sdt_events(NULL, s, raw_dump); + metricgroup__print(true, true, NULL, raw_dump, details_flag); +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index b6960ef3a553..a1eff577f002 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -323,7 +323,8 @@ static int print_events_table_entry(void *data, char *name, char *event, + char *desc, char *long_desc, + char *pmu, char *unit, char *perpkg, + char *metric_expr, +- char *metric_name, char *metric_group) ++ char *metric_name, char *metric_group, ++ char *deprecated) + { + struct perf_entry_data *pd = data; + FILE *outfp = pd->outfp; +@@ -355,6 +356,8 @@ static int print_events_table_entry(void *data, char *name, char *event, + fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name); + if (metric_group) + fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group); ++ if (deprecated) ++ fprintf(outfp, "\t.deprecated = \"%s\",\n", deprecated); + fprintf(outfp, "},\n"); + + return 0; +@@ -372,6 +375,7 @@ struct event_struct { + char *metric_expr; + char *metric_name; + char *metric_group; ++ char *deprecated; + }; + + #define ADD_EVENT_FIELD(field) do { if (field) { \ +@@ -399,6 +403,7 @@ struct event_struct { + op(metric_expr); \ + op(metric_name); \ + op(metric_group); \ ++ op(deprecated); \ + } while (0) + + static LIST_HEAD(arch_std_events); +@@ -417,7 +422,8 @@ static void free_arch_std_events(void) + static int save_arch_std_events(void *data, char *name, char *event, + char *desc, char *long_desc, char *pmu, + char *unit, char *perpkg, char *metric_expr, +- char *metric_name, char *metric_group) ++ char *metric_name, char *metric_group, ++ char *deprecated) + { + struct event_struct *es; + +@@ -480,7 +486,8 @@ static int + try_fixup(const char *fn, char *arch_std, char **event, char **desc, + char **name, char **long_desc, char **pmu, char **filter, + char **perpkg, char **unit, char **metric_expr, char **metric_name, +- char **metric_group, unsigned long long eventcode) ++ char **metric_group, unsigned long long eventcode, ++ char **deprecated) + { + /* try to find matching event from arch standard values */ + struct event_struct *es; +@@ -508,7 +515,8 @@ int json_events(const char *fn, + char *long_desc, + char *pmu, char *unit, char *perpkg, + char *metric_expr, +- char *metric_name, char *metric_group), ++ char *metric_name, char *metric_group, ++ char *deprecated), + void *data) + { + int err; +@@ -537,6 +545,7 @@ int json_events(const char *fn, + char *metric_expr = NULL; + char *metric_name = NULL; + char *metric_group = NULL; ++ char *deprecated = NULL; + char *arch_std = NULL; + unsigned long long eventcode = 0; + struct msrmap *msr = NULL; +@@ -615,6 +624,8 @@ int json_events(const char *fn, + addfield(map, &unit, "", "", val); + } else if (json_streq(map, field, "PerPkg")) { + addfield(map, &perpkg, "", "", val); ++ } else if (json_streq(map, field, "Deprecated")) { ++ addfield(map, &deprecated, "", "", val); + } else if (json_streq(map, field, "MetricName")) { + addfield(map, &metric_name, "", "", val); + } else if (json_streq(map, field, "MetricGroup")) { +@@ -659,12 +670,14 @@ int json_events(const char *fn, + err = try_fixup(fn, arch_std, &event, &desc, &name, + &long_desc, &pmu, &filter, &perpkg, + &unit, &metric_expr, &metric_name, +- &metric_group, eventcode); ++ &metric_group, eventcode, ++ &deprecated); + if (err) + goto free_strings; + } + err = func(data, name, real_event(name, event), desc, long_desc, +- pmu, unit, perpkg, metric_expr, metric_name, metric_group); ++ pmu, unit, perpkg, metric_expr, metric_name, ++ metric_group, deprecated); + free_strings: + free(event); + free(desc); +@@ -674,6 +687,7 @@ int json_events(const char *fn, + free(pmu); + free(filter); + free(perpkg); ++ free(deprecated); + free(unit); + free(metric_expr); + free(metric_name); +diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h +index 4684c673c445..5cda49a42143 100644 +--- a/tools/perf/pmu-events/jevents.h ++++ b/tools/perf/pmu-events/jevents.h +@@ -7,7 +7,8 @@ int json_events(const char *fn, + char *long_desc, + char *pmu, + char *unit, char *perpkg, char *metric_expr, +- char *metric_name, char *metric_group), ++ char *metric_name, char *metric_group, ++ char *deprecated), + void *data); + char *get_cpu_str(void); + +diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h +index 92a4d15ee0b9..caeb577d36c9 100644 +--- a/tools/perf/pmu-events/pmu-events.h ++++ b/tools/perf/pmu-events/pmu-events.h +@@ -17,6 +17,7 @@ struct pmu_event { + const char *metric_expr; + const char *metric_name; + const char *metric_group; ++ const char *deprecated; + }; + + /* +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index c0a13cf41ef6..8b9b13b6e901 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -2555,7 +2555,7 @@ void print_symbol_events(const char *event_glob, unsigned type, + * Print the help text for the event symbols: + */ + void print_events(const char *event_glob, bool name_only, bool quiet_flag, +- bool long_desc, bool details_flag) ++ bool long_desc, bool details_flag, bool deprecated) + { + print_symbol_events(event_glob, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX, name_only); +@@ -2567,7 +2567,7 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag, + print_hwcache_events(event_glob, name_only); + + print_pmu_events(event_glob, name_only, quiet_flag, long_desc, +- details_flag); ++ details_flag, deprecated); + + if (event_glob != NULL) + return; +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 58c6730526f9..52be0b3b26f7 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -192,7 +192,7 @@ void parse_events_evlist_error(struct parse_events_state *parse_state, + int idx, const char *str); + + void print_events(const char *event_glob, bool name_only, bool quiet, +- bool long_desc, bool details_flag); ++ bool long_desc, bool details_flag, bool deprecated); + + struct event_symbol { + const char *symbol; +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 147989e2bff0..2d06db85c135 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -307,7 +307,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + char *long_desc, char *topic, + char *unit, char *perpkg, + char *metric_expr, +- char *metric_name) ++ char *metric_name, ++ char *deprecated) + { + struct parse_events_term *term; + struct perf_pmu_alias *alias; +@@ -324,6 +325,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + alias->unit[0] = '\0'; + alias->per_pkg = false; + alias->snapshot = false; ++ alias->deprecated = false; + + ret = parse_events_terms(&alias->terms, val); + if (ret) { +@@ -378,6 +380,9 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1; + alias->str = strdup(newval); + ++ if (deprecated) ++ alias->deprecated = true; ++ + if (!perf_pmu_merge_alias(alias, list)) + list_add_tail(&alias->list, list); + +@@ -399,7 +404,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI + rtrim(buf); + + return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + } + + static inline bool pmu_alias_info_file(char *name) +@@ -825,7 +830,8 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) + (char *)pe->long_desc, (char *)pe->topic, + (char *)pe->unit, (char *)pe->perpkg, + (char *)pe->metric_expr, +- (char *)pe->metric_name); ++ (char *)pe->metric_name, ++ (char *)pe->deprecated); + } + } + +@@ -1407,7 +1413,7 @@ static void wordwrap(char *s, int start, int max, int corr) + } + + void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, +- bool long_desc, bool details_flag) ++ bool long_desc, bool details_flag, bool deprecated) + { + struct perf_pmu *pmu; + struct perf_pmu_alias *alias; +@@ -1438,6 +1444,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, + format_alias(buf, sizeof(buf), pmu, alias); + bool is_cpu = !strcmp(pmu->name, "cpu"); + ++ if (alias->deprecated && !deprecated) ++ continue; ++ + if (event_glob != NULL && + !(strglobmatch_nocase(name, event_glob) || + (!is_cpu && strglobmatch_nocase(alias->name, +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index ea0e7c36eae9..a7f1d60c288b 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -55,6 +55,7 @@ struct perf_pmu_alias { + double scale; + bool per_pkg; + bool snapshot; ++ bool deprecated; + char *metric_expr; + char *metric_name; + }; +@@ -83,7 +84,8 @@ int perf_pmu__format_parse(char *dir, struct list_head *head); + struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); + + void print_pmu_events(const char *event_glob, bool name_only, bool quiet, +- bool long_desc, bool details_flag); ++ bool long_desc, bool details_flag, ++ bool deprecated); + bool pmu_have_event(const char *pname, const char *name); + + int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4); +-- +2.27.0 + diff --git a/patches/0152-perf-metricgroup-Fix-printing-event-names-of-metric-.patch b/patches/0152-perf-metricgroup-Fix-printing-event-names-of-metric-.patch new file mode 100644 index 0000000..75403d6 --- /dev/null +++ b/patches/0152-perf-metricgroup-Fix-printing-event-names-of-metric-.patch @@ -0,0 +1,151 @@ +From aa636dd0053413996f78efb463c8a4e1802930e2 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Wed, 20 Nov 2019 14:10:59 +0530 +Subject: [PATCH 035/201] perf metricgroup: Fix printing event names of metric + group with multiple events + +mainline inclusion +from mainline-v5.5-rc3 +commit eb573e746b9d4f0921dcb2449be3df41dae3caea +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eb573e746b9d4f0921dcb2449be3df41dae3caea + +------------------------------------------------------------------------ + +Commit f01642e4912b ("perf metricgroup: Support multiple events for +metricgroup") introduced support for multiple events in a metric group. +But with the current upstream, metric events names are not printed +properly + +In power9 platform: + +command:# ./perf stat --metric-only -M translation -C 0 -I 1000 sleep 2 + 1.000208486 + 2.000368863 + 2.001400558 + +Similarly in skylake platform: + +command:./perf stat --metric-only -M Power -I 1000 + 1.000579994 + 2.002189493 + +With current upstream version, issue is with event name comparison logic +in find_evsel_group(). Current logic is to compare events belonging to a +metric group to the events in perf_evlist. Since the break statement is +missing in the loop used for comparison between metric group and +perf_evlist events, the loop continues to execute even after getting a +pattern match, and end up in discarding the matches. + +Incase of single metric event belongs to metric group, its working fine, +because in case of single event once it compare all events it reaches to +end of perf_evlist. + +Example for single metric event in power9 platform: + +command:# ./perf stat --metric-only -M branches_per_inst -I 1000 sleep 1 + 1.000094653 0.2 + 1.001337059 0.0 + +This patch fixes the issue by making sure once we found all events +belongs to that metric event matched in find_evsel_group(), we +successfully break from that loop by adding corresponding condition. + +With this patch: +In power9 platform: + +command:# ./perf stat --metric-only -M translation -C 0 -I 1000 sleep 2 +result:# + time derat_4k_miss_rate_percent derat_4k_miss_ratio derat_miss_ratio derat_64k_miss_rate_percent derat_64k_miss_ratio dslb_miss_rate_percent islb_miss_rate_percent + 1.000135672 0.0 0.3 1.0 0.0 0.2 0.0 0.0 + 2.000380617 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + +command:# ./perf stat --metric-only -M Power -I 1000 + +Similarly in skylake platform: +result:# + time Turbo_Utilization C3_Core_Residency C6_Core_Residency C7_Core_Residency C2_Pkg_Residency C3_Pkg_Residency C6_Pkg_Residency C7_Pkg_Residency + 1.000563580 0.3 0.0 2.6 44.2 21.9 0.0 0.0 0.0 + 2.002235027 0.4 0.0 2.7 43.0 20.7 0.0 0.0 0.0 + +Committer testing: + + Before: + + [root@seventh ~]# perf stat --metric-only -M Power -I 1000 + # time + 1.000383223 + 2.001168182 + 3.001968545 + 4.002741200 + 5.003442022 + ^C 5.777687244 + + [root@seventh ~]# + + After the patch: + + [root@seventh ~]# perf stat --metric-only -M Power -I 1000 + # time Turbo_Utilization C3_Core_Residency C6_Core_Residency C7_Core_Residency C2_Pkg_Residency C3_Pkg_Residency C6_Pkg_Residency C7_Pkg_Residency + 1.000406577 0.4 0.1 1.4 97.0 0.0 0.0 0.0 0.0 + 2.001481572 0.3 0.0 0.6 97.9 0.0 0.0 0.0 0.0 + 3.002332585 0.2 0.0 1.0 97.5 0.0 0.0 0.0 0.0 + 4.003196624 0.2 0.0 0.3 98.6 0.0 0.0 0.0 0.0 + 5.004063851 0.3 0.0 0.7 97.7 0.0 0.0 0.0 0.0 + ^C 5.471260276 0.2 0.0 0.5 49.3 0.0 0.0 0.0 0.0 + + [root@seventh ~]# + [root@seventh ~]# dmesg | grep -i skylake + [ 0.187807] Performance Events: PEBS fmt3+, Skylake events, 32-deep LBR, full-width counters, Intel PMU driver. + [root@seventh ~]# + +Fixes: f01642e4912b ("perf metricgroup: Support multiple events for metricgroup") +Signed-off-by: Kajol Jain +Reviewed-by: Ravi Bangoria +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20191120084059.24458-1-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 375866dab75b..303f0fde6759 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -109,8 +109,11 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + if (!strcmp(ev->name, ids[i])) { + if (!metric_events[i]) + metric_events[i] = ev; ++ i++; ++ if (i == idnum) ++ break; + } else { +- if (++i == idnum) { ++ if (i + 1 == idnum) { + /* Discard the whole match and start again */ + i = 0; + memset(metric_events, 0, +@@ -130,7 +133,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + } + } + +- if (i != idnum - 1) { ++ if (i != idnum) { + /* Not whole match */ + return NULL; + } +-- +2.27.0 + diff --git a/patches/0153-tools-bitmap-Implement-bitmap_equal-operation-at-bit.patch b/patches/0153-tools-bitmap-Implement-bitmap_equal-operation-at-bit.patch new file mode 100644 index 0000000..9e3705e --- /dev/null +++ b/patches/0153-tools-bitmap-Implement-bitmap_equal-operation-at-bit.patch @@ -0,0 +1,118 @@ +From b91e36590cb2508bff91771222eb811dfde5ee77 Mon Sep 17 00:00:00 2001 +From: Alexey Budankov +Date: Tue, 3 Dec 2019 14:43:33 +0300 +Subject: [PATCH 036/201] tools bitmap: Implement bitmap_equal() operation at + bitmap API + +mainline inclusion +from mainline-v5.6-rc1 +commit 8812ad412f851216d6c39488a7e563ccc5c604cc +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8812ad412f851216d6c39488a7e563ccc5c604cc + +----------------------------------------------------------- + +Extend tools bitmap API with bitmap_equal() implementation. + +The implementation has been derived from the kernel. + +Extend tools bitmap API with bitmap_free() implementation for symmetry +with bitmap_alloc() function. + +Signed-off-by: Alexey Budankov +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/43757993-0b28-d8af-a6c7-ede12e3a6877@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo + + Conflicts: + tools/include/linux/bitmap.h +--- + tools/include/linux/bitmap.h | 30 ++++++++++++++++++++++++++++++ + tools/lib/bitmap.c | 15 +++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h +index e63662db131b..682a3f88db87 100644 +--- a/tools/include/linux/bitmap.h ++++ b/tools/include/linux/bitmap.h +@@ -15,6 +15,8 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); + int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, unsigned int bits); ++int __bitmap_equal(const unsigned long *bitmap1, ++ const unsigned long *bitmap2, unsigned int bits); + + #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) + +@@ -122,6 +124,15 @@ static inline unsigned long *bitmap_alloc(int nbits) + return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); + } + ++/* ++ * bitmap_free - Free bitmap ++ * @bitmap: pointer to bitmap ++ */ ++static inline void bitmap_free(unsigned long *bitmap) ++{ ++ free(bitmap); ++} ++ + /* + * bitmap_scnprintf - print bitmap list into buffer + * @bitmap: bitmap +@@ -147,4 +158,23 @@ static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, + return __bitmap_and(dst, src1, src2, nbits); + } + ++#ifdef __LITTLE_ENDIAN ++#define BITMAP_MEM_ALIGNMENT 8 ++#else ++#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long)) ++#endif ++#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1) ++#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) ++ ++static inline int bitmap_equal(const unsigned long *src1, ++ const unsigned long *src2, unsigned int nbits) ++{ ++ if (small_const_nbits(nbits)) ++ return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); ++ if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) && ++ IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT)) ++ return !memcmp(src1, src2, nbits / 8); ++ return __bitmap_equal(src1, src2, nbits); ++} ++ + #endif /* _PERF_BITOPS_H */ +diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c +index 38748b0e342f..e4a0db44d615 100644 +--- a/tools/lib/bitmap.c ++++ b/tools/lib/bitmap.c +@@ -73,3 +73,18 @@ int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, + BITMAP_LAST_WORD_MASK(bits)); + return result != 0; + } ++ ++int __bitmap_equal(const unsigned long *bitmap1, ++ const unsigned long *bitmap2, unsigned int bits) ++{ ++ unsigned int k, lim = bits/BITS_PER_LONG; ++ for (k = 0; k < lim; ++k) ++ if (bitmap1[k] != bitmap2[k]) ++ return 0; ++ ++ if (bits % BITS_PER_LONG) ++ if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) ++ return 0; ++ ++ return 1; ++} +-- +2.27.0 + diff --git a/patches/0154-perf-metricgroup-Fix-printing-event-names-of-metric-.patch b/patches/0154-perf-metricgroup-Fix-printing-event-names-of-metric-.patch new file mode 100644 index 0000000..f484ba0 --- /dev/null +++ b/patches/0154-perf-metricgroup-Fix-printing-event-names-of-metric-.patch @@ -0,0 +1,212 @@ +From 887e5e7550dda0f6c99d796a9bf81cbf2e128b31 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Fri, 21 Feb 2020 15:41:21 +0530 +Subject: [PATCH 037/201] perf metricgroup: Fix printing event names of metric + group with multiple events incase of overlapping events + +mainline inclusion +from mainline-v5.7-rc1 +commit 58fc90fda0cc983c11c5290c7a9e992b08ac4a5c +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=58fc90fda0cc983c11c5290c7a9e992b08ac4a5c + +------------------------------------------------------------------------ + +Commit f01642e4912b ("perf metricgroup: Support multiple events for +metricgroup") introduced support for multiple events in a metric group. +But with the current upstream, metric events names are not printed +properly incase we try to run multiple metric groups with overlapping +event. + +With current upstream version, incase of overlapping metric events issue +is, we always start our comparision logic from start. So, the events +which already matched with some metric group also take part in +comparision logic. Because of that when we have overlapping events, we +end up matching current metric group event with already matched one. + +For example, in skylake machine we have metric event CoreIPC and +Instructions. Both of them need 'inst_retired.any' event value. As +events in Instructions is subset of events in CoreIPC, they endup in +pointing to same 'inst_retired.any' value. + +In skylake platform: + +command:# ./perf stat -M CoreIPC,Instructions -C 0 sleep 1 + + Performance counter stats for 'CPU(s) 0': + + 1,254,992,790 inst_retired.any # 1254992790.0 + Instructions + # 1.3 CoreIPC + 977,172,805 cycles + 1,254,992,756 inst_retired.any + + 1.000802596 seconds time elapsed + +command:# sudo ./perf stat -M UPI,IPC sleep 1 + + Performance counter stats for 'sleep 1': + 948,650 uops_retired.retire_slots + 866,182 inst_retired.any # 0.7 IPC + 866,182 inst_retired.any + 1,175,671 cpu_clk_unhalted.thread + +Patch fixes the issue by adding a new bool pointer 'evlist_used' to keep +track of events which already matched with some group by setting it +true. So, we skip all used events in list when we start comparision +logic. Patch also make some changes in comparision logic, incase we get +a match miss, we discard the whole match and start again with first +event id in metric event. + +With this patch: + +In skylake platform: + +command:# ./perf stat -M CoreIPC,Instructions -C 0 sleep 1 + + Performance counter stats for 'CPU(s) 0': + + 3,348,415 inst_retired.any # 0.3 CoreIPC + 11,779,026 cycles + 3,348,381 inst_retired.any # 3348381.0 + Instructions + + 1.001649056 seconds time elapsed + +command:# ./perf stat -M UPI,IPC sleep 1 + + Performance counter stats for 'sleep 1': + + 1,023,148 uops_retired.retire_slots # 1.1 UPI + 924,976 inst_retired.any + 924,976 inst_retired.any # 0.6 IPC + 1,489,414 cpu_clk_unhalted.thread + + 1.003064672 seconds time elapsed + +Signed-off-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Jin Yao +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200221101121.28920-1-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 49 +++++++++++++++++++++-------------- + 1 file changed, 30 insertions(+), 19 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 303f0fde6759..9f6b0b0f7b59 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -99,13 +99,16 @@ struct egroup { + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + const char **ids, + int idnum, +- struct perf_evsel **metric_events) ++ struct perf_evsel **metric_events, ++ bool *evlist_used) + { + struct perf_evsel *ev; +- int i = 0; ++ int i = 0, j = 0; + bool leader_found; + + evlist__for_each_entry (perf_evlist, ev) { ++ if (evlist_used[j++]) ++ continue; + if (!strcmp(ev->name, ids[i])) { + if (!metric_events[i]) + metric_events[i] = ev; +@@ -113,22 +116,17 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + if (i == idnum) + break; + } else { +- if (i + 1 == idnum) { +- /* Discard the whole match and start again */ +- i = 0; +- memset(metric_events, 0, +- sizeof(struct evsel *) * idnum); +- continue; +- } +- +- if (!strcmp(ev->name, ids[i])) +- metric_events[i] = ev; +- else { +- /* Discard the whole match and start again */ +- i = 0; +- memset(metric_events, 0, +- sizeof(struct evsel *) * idnum); +- continue; ++ /* Discard the whole match and start again */ ++ i = 0; ++ memset(metric_events, 0, ++ sizeof(struct perf_evsel *) * idnum); ++ ++ if (!strcmp(ev->name, ids[i])) { ++ if (!metric_events[i]) ++ metric_events[i] = ev; ++ i++; ++ if (i == idnum) ++ break; + } + } + } +@@ -150,7 +148,10 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + !strcmp(ev->name, metric_events[i]->name)) { + ev->metric_leader = metric_events[i]; + } ++ j++; + } ++ ev = metric_events[i]; ++ evlist_used[ev->idx] = true; + } + + return metric_events[0]; +@@ -166,6 +167,13 @@ static int metricgroup__setup_events(struct list_head *groups, + int ret = 0; + struct egroup *eg; + struct perf_evsel *evsel; ++ bool *evlist_used; ++ ++ evlist_used = calloc(perf_evlist->nr_entries, sizeof(bool)); ++ if (!evlist_used) { ++ ret = -ENOMEM; ++ return ret; ++ } + + list_for_each_entry (eg, groups, nd) { + struct perf_evsel **metric_events; +@@ -176,7 +184,7 @@ static int metricgroup__setup_events(struct list_head *groups, + break; + } + evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum, +- metric_events); ++ metric_events, evlist_used); + if (!evsel) { + pr_debug("Cannot resolve %s: %s\n", + eg->metric_name, eg->metric_expr); +@@ -203,6 +211,9 @@ static int metricgroup__setup_events(struct list_head *groups, + expr->metric_events = metric_events; + list_add(&expr->nd, &me->head); + } ++ ++ free(evlist_used); ++ + return ret; + } + +-- +2.27.0 + diff --git a/patches/0155-perf-parse-events-Fix-an-old-style-declaration.patch b/patches/0155-perf-parse-events-Fix-an-old-style-declaration.patch new file mode 100644 index 0000000..738580f --- /dev/null +++ b/patches/0155-perf-parse-events-Fix-an-old-style-declaration.patch @@ -0,0 +1,47 @@ +From 52390925ed8b978cc74dc82655ebbddceb0a7b12 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Mon, 8 Jun 2020 22:36:10 -0700 +Subject: [PATCH 038/201] perf parse-events: Fix an old style declaration + +mainline inclusion +from mainline-v5.8-rc2 +commit ffaecd7d1f88a955f0b321749de8c0158f973afd +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ffaecd7d1f88a955f0b321749de8c0158f973afd + +------------------------------------------------------------------------ + +Fixes: a26e47162d76 (perf tools: Move ALLOC_LIST into a function) +Signed-off-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200609053610.206588-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/parse-events.y | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index ef4c83b07c22..b940b621b14e 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -27,7 +27,7 @@ do { \ + YYABORT; \ + } while (0) + +-static struct list_head* alloc_list() ++static struct list_head* alloc_list(void) + { + struct list_head *list; + +-- +2.27.0 + diff --git a/patches/0156-libbpf-fix-missing-__WORDSIZE-definition.patch b/patches/0156-libbpf-fix-missing-__WORDSIZE-definition.patch new file mode 100644 index 0000000..c04661e --- /dev/null +++ b/patches/0156-libbpf-fix-missing-__WORDSIZE-definition.patch @@ -0,0 +1,54 @@ +From 0ac7392379b31ec9b76fb42b083544cac8e4ba29 Mon Sep 17 00:00:00 2001 +From: Andrii Nakryiko +Date: Thu, 18 Jul 2019 10:30:21 -0700 +Subject: [PATCH 039/201] libbpf: fix missing __WORDSIZE definition + +mainline inclusion +from mainline-v5.3-rc3 +commit 8aa259b10a6a759c50137bbbf225df0c17ca5d27 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8aa259b10a6a759c50137bbbf225df0c17ca5d27 + +------------------------------------------------------------------------ + +hashmap.h depends on __WORDSIZE being defined. It is defined by +glibc/musl in different headers. It's an explicit goal for musl to be +"non-detectable" at compilation time, so instead include glibc header if +glibc is explicitly detected and fall back to musl header otherwise. + +Reported-by: Arnaldo Carvalho de Melo +Signed-off-by: Andrii Nakryiko +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexei Starovoitov +Cc: Andrii Nakryiko +Cc: Daniel Borkmann +Fixes: e3b924224028 ("libbpf: add resizable non-thread safe internal hashmap") +Link: https://lkml.kernel.org/r/20190718173021.2418606-1-andriin@fb.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/lib/bpf/hashmap.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +index ab97b9797100..bae8879cdf58 100644 +--- a/tools/lib/bpf/hashmap.h ++++ b/tools/lib/bpf/hashmap.h +@@ -10,6 +10,12 @@ + + #include + #include ++#ifdef __GLIBC__ ++#include ++#else ++#include ++#endif ++#include "libbpf_internal.h" + + static inline size_t hash_bits(size_t h, int bits) + { +-- +2.27.0 + diff --git a/patches/0157-libbpf-hashmap-Remove-unused-include.patch b/patches/0157-libbpf-hashmap-Remove-unused-include.patch new file mode 100644 index 0000000..b52c45d --- /dev/null +++ b/patches/0157-libbpf-hashmap-Remove-unused-include.patch @@ -0,0 +1,44 @@ +From e7f925737486dd8d1cd4c10f5f813632bf19f81b Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 15 May 2020 09:50:02 -0700 +Subject: [PATCH 040/201] libbpf, hashmap: Remove unused #include + +mainline inclusion +from mainline-v5.8-rc1 +commit f516acd5397fdbb77ef0aad0798d9ef7c3001d72 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f516acd5397fdbb77ef0aad0798d9ef7c3001d72 + +------------------------------------------------------------------------ + +Remove #include of libbpf_internal.h that is unused. + +Discussed in this thread: +https://lore.kernel.org/lkml/CAEf4BzZRmiEds_8R8g4vaAeWvJzPb4xYLnpF0X2VNY8oTzkphQ@mail.gmail.com/ + +Signed-off-by: Ian Rogers +Signed-off-by: Daniel Borkmann +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20200515165007.217120-3-irogers@google.com +Signed-off-by: hongrongxuan +--- + tools/lib/bpf/hashmap.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +index bae8879cdf58..e823b35e7371 100644 +--- a/tools/lib/bpf/hashmap.h ++++ b/tools/lib/bpf/hashmap.h +@@ -15,7 +15,6 @@ + #else + #include + #endif +-#include "libbpf_internal.h" + + static inline size_t hash_bits(size_t h, int bits) + { +-- +2.27.0 + diff --git a/patches/0158-libbpf-Define-__WORDSIZE-if-not-available.patch b/patches/0158-libbpf-Define-__WORDSIZE-if-not-available.patch new file mode 100644 index 0000000..36b5fea --- /dev/null +++ b/patches/0158-libbpf-Define-__WORDSIZE-if-not-available.patch @@ -0,0 +1,54 @@ +From 5095414bbfa881d0835506efffdc28a80aeb0a21 Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Tue, 9 Jun 2020 18:16:53 -0300 +Subject: [PATCH 041/201] libbpf: Define __WORDSIZE if not available + +mainline inclusion +from mainline-v5.8-rc1 +commit 8ca8d4a841730c02e77bf3c87bf658cc44f364b9 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8ca8d4a841730c02e77bf3c87bf658cc44f364b9 + +------------------------------------------------------------------------ + +Some systems, such as Android, don't have a define for __WORDSIZE, do it +in terms of __SIZEOF_LONG__, as done in perf since 2012: + + http://git.kernel.org/torvalds/c/3f34f6c0233ae055b5 + +For reference: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html + +I build tested it here and Andrii did some Travis CI build tests too. + +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Daniel Borkmann +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20200608161150.GA3073@kernel.org +Signed-off-by: hongrongxuan +--- + tools/lib/bpf/hashmap.h | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +index e823b35e7371..df59fd4fc95b 100644 +--- a/tools/lib/bpf/hashmap.h ++++ b/tools/lib/bpf/hashmap.h +@@ -10,10 +10,9 @@ + + #include + #include +-#ifdef __GLIBC__ +-#include +-#else +-#include ++#include ++#ifndef __WORDSIZE ++#define __WORDSIZE (__SIZEOF_LONG__ * 8) + #endif + + static inline size_t hash_bits(size_t h, int bits) +-- +2.27.0 + diff --git a/patches/0159-libbpf-Fix-libbpf-hashmap-on-I-LP32-architectures.patch b/patches/0159-libbpf-Fix-libbpf-hashmap-on-I-LP32-architectures.patch new file mode 100644 index 0000000..11e9ef7 --- /dev/null +++ b/patches/0159-libbpf-Fix-libbpf-hashmap-on-I-LP32-architectures.patch @@ -0,0 +1,60 @@ +From 9196accd36718701e49be67194b78de6af7fe699 Mon Sep 17 00:00:00 2001 +From: Jakub Bogusz +Date: Thu, 9 Jul 2020 15:57:23 -0700 +Subject: [PATCH 042/201] libbpf: Fix libbpf hashmap on (I)LP32 architectures + +mainline inclusion +from mainline-v5.8-rc5 +commit b2f9f1535bb93ee5fa2ea30ac1c26fa0d676154c +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b2f9f1535bb93ee5fa2ea30ac1c26fa0d676154c + +------------------------------------------------------------------------ + +On ILP32, 64-bit result was shifted by value calculated for 32-bit long type +and returned value was much outside hashmap capacity. +As advised by Andrii Nakryiko, this patch uses different hashing variant for +architectures with size_t shorter than long long. + +Fixes: e3b924224028 ("libbpf: add resizable non-thread safe internal hashmap") +Signed-off-by: Jakub Bogusz +Signed-off-by: Andrii Nakryiko +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20200709225723.1069937-1-andriin@fb.com +Signed-off-by: hongrongxuan +--- + tools/lib/bpf/hashmap.h | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +index df59fd4fc95b..e0af36b0e5d8 100644 +--- a/tools/lib/bpf/hashmap.h ++++ b/tools/lib/bpf/hashmap.h +@@ -11,14 +11,18 @@ + #include + #include + #include +-#ifndef __WORDSIZE +-#define __WORDSIZE (__SIZEOF_LONG__ * 8) +-#endif + + static inline size_t hash_bits(size_t h, int bits) + { + /* shuffle bits and return requested number of upper bits */ +- return (h * 11400714819323198485llu) >> (__WORDSIZE - bits); ++#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) ++ /* LP64 case */ ++ return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); ++#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__) ++ return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits); ++#else ++# error "Unsupported size_t size" ++#endif + } + + typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); +-- +2.27.0 + diff --git a/patches/0160-libbpf-hashmap-Fix-undefined-behavior-in-hash_bits.patch b/patches/0160-libbpf-hashmap-Fix-undefined-behavior-in-hash_bits.patch new file mode 100644 index 0000000..89d101e --- /dev/null +++ b/patches/0160-libbpf-hashmap-Fix-undefined-behavior-in-hash_bits.patch @@ -0,0 +1,75 @@ +From 045d2fb4dd250981ae4a1df07660bcd2972f73d3 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Thu, 29 Oct 2020 15:37:07 -0700 +Subject: [PATCH 043/201] libbpf, hashmap: Fix undefined behavior in hash_bits + +mainline inclusion +from mainline-v5.10-rc4 +commit 7a078d2d18801bba7bde7337a823d7342299acf7 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7a078d2d18801bba7bde7337a823d7342299acf7 + +------------------------------------------------------------------------ + +If bits is 0, the case when the map is empty, then the >> is the size of +the register which is undefined behavior - on x86 it is the same as a +shift by 0. + +Fix by handling the 0 case explicitly and guarding calls to hash_bits for +empty maps in hashmap__for_each_key_entry and hashmap__for_each_entry_safe. + +Fixes: e3b924224028 ("libbpf: add resizable non-thread safe internal hashmap") +Suggested-by: Andrii Nakryiko , +Signed-off-by: Ian Rogers +Signed-off-by: Daniel Borkmann +Acked-by: Andrii Nakryiko +Acked-by: Song Liu +Link: https://lore.kernel.org/bpf/20201029223707.494059-1-irogers@google.com +Signed-off-by: hongrongxuan +--- + tools/lib/bpf/hashmap.h | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h +index e0af36b0e5d8..6a3c3d8bb4ab 100644 +--- a/tools/lib/bpf/hashmap.h ++++ b/tools/lib/bpf/hashmap.h +@@ -15,6 +15,9 @@ + static inline size_t hash_bits(size_t h, int bits) + { + /* shuffle bits and return requested number of upper bits */ ++ if (bits == 0) ++ return 0; ++ + #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) + /* LP64 case */ + return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); +@@ -162,17 +165,17 @@ bool hashmap__find(const struct hashmap *map, const void *key, void **value); + * @key: key to iterate entries for + */ + #define hashmap__for_each_key_entry(map, cur, _key) \ +- for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ +- map->cap_bits); \ +- map->buckets ? map->buckets[bkt] : NULL; }); \ ++ for (cur = map->buckets \ ++ ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ ++ : NULL; \ + cur; \ + cur = cur->next) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) + + #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ +- for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ +- map->cap_bits); \ +- cur = map->buckets ? map->buckets[bkt] : NULL; }); \ ++ for (cur = map->buckets \ ++ ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ ++ : NULL; \ + cur && ({ tmp = cur->next; true; }); \ + cur = tmp) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) +-- +2.27.0 + diff --git a/patches/0161-perf-tools-Grab-a-copy-of-libbpf-s-hashmap.patch b/patches/0161-perf-tools-Grab-a-copy-of-libbpf-s-hashmap.patch new file mode 100644 index 0000000..27c6572 --- /dev/null +++ b/patches/0161-perf-tools-Grab-a-copy-of-libbpf-s-hashmap.patch @@ -0,0 +1,530 @@ +From 625cfee7500b6402a2b280e960bd84110db9ec7a Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 15 May 2020 15:17:29 -0700 +Subject: [PATCH 044/201] perf tools: Grab a copy of libbpf's hashmap + +mainline inclusion +from mainline-v5.8-rc1 +commit eee19501926d98c894f15c1644b815c7d1fbd187 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eee19501926d98c894f15c1644b815c7d1fbd187 + +------------------------------------------------------------------------ + +Allow use of hashmap in perf. Modify perf's check-headers.sh script to +check that the files are kept in sync, in the same way kernel headers +are checked. This will warn if they are out of sync at the start of a +perf build. + +Committer note: + +This starts out of synch as a fix went thru the bpf tree, namely the one +removing the needless libbpf_internal.h include in hashmap.h. + +There is also another change related to __WORDSIZE, that as is in +tools/lib/bpf/hashmap.h causes the tools/perf/ build to fail in systems +such as Alpine Linus, that uses the Musl libc, so we need an alternative +way of having __WORDSIZE available, use the one used by +tools/include/linux/bitops.h, that builds in all the systems I have +build containers for. + +These differences will be resolved at some point, so keep the warning in +check-headers.sh as a reminder. + +Signed-off-by: Ian Rogers +Acked-by: Andrii Nakryiko +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Alexei Starovoitov +Cc: Andi Kleen +Cc: Cong Wang +Cc: Daniel Borkmann +Cc: Jin Yao +Cc: Jiri Olsa +Cc: John Fastabend +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Martin KaFai Lau +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Stephane Eranian +Cc: Yonghong Song +Cc: bpf@vger.kernel.org +Cc: kp singh +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200515221732.44078-5-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/check-headers.sh | 4 + + tools/perf/util/Build | 4 + + tools/perf/util/hashmap.c | 238 ++++++++++++++++++++++++++++++++++++ + tools/perf/util/hashmap.h | 176 ++++++++++++++++++++++++++ + 4 files changed, 422 insertions(+) + create mode 100644 tools/perf/util/hashmap.c + create mode 100644 tools/perf/util/hashmap.h + +diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh +index c72cc73a6b09..79e3c3670655 100755 +--- a/tools/perf/check-headers.sh ++++ b/tools/perf/check-headers.sh +@@ -105,4 +105,8 @@ check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' + # diff non-symmetric files + check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl + ++# check duplicated library files ++check_2 tools/perf/util/hashmap.h tools/lib/bpf/hashmap.h ++check_2 tools/perf/util/hashmap.c tools/lib/bpf/hashmap.c ++ + cd tools/perf +diff --git a/tools/perf/util/Build b/tools/perf/util/Build +index f4148ecffeae..de3b99f927ac 100644 +--- a/tools/perf/util/Build ++++ b/tools/perf/util/Build +@@ -115,6 +115,10 @@ libperf-$(CONFIG_LIBELF) += symbol-elf.o + libperf-$(CONFIG_LIBELF) += probe-file.o + libperf-$(CONFIG_LIBELF) += probe-event.o + ++ifndef CONFIG_LIBBPF ++perf-y += hashmap.o ++endif ++ + ifndef CONFIG_LIBELF + libperf-y += symbol-minimal.o + endif +diff --git a/tools/perf/util/hashmap.c b/tools/perf/util/hashmap.c +new file mode 100644 +index 000000000000..a405dad068f5 +--- /dev/null ++++ b/tools/perf/util/hashmap.c +@@ -0,0 +1,238 @@ ++// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) ++ ++/* ++ * Generic non-thread safe hash map implementation. ++ * ++ * Copyright (c) 2019 Facebook ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "hashmap.h" ++ ++/* make sure libbpf doesn't use kernel-only integer typedefs */ ++#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 ++ ++/* start with 4 buckets */ ++#define HASHMAP_MIN_CAP_BITS 2 ++ ++static void hashmap_add_entry(struct hashmap_entry **pprev, ++ struct hashmap_entry *entry) ++{ ++ entry->next = *pprev; ++ *pprev = entry; ++} ++ ++static void hashmap_del_entry(struct hashmap_entry **pprev, ++ struct hashmap_entry *entry) ++{ ++ *pprev = entry->next; ++ entry->next = NULL; ++} ++ ++void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, void *ctx) ++{ ++ map->hash_fn = hash_fn; ++ map->equal_fn = equal_fn; ++ map->ctx = ctx; ++ ++ map->buckets = NULL; ++ map->cap = 0; ++ map->cap_bits = 0; ++ map->sz = 0; ++} ++ ++struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, ++ void *ctx) ++{ ++ struct hashmap *map = malloc(sizeof(struct hashmap)); ++ ++ if (!map) ++ return ERR_PTR(-ENOMEM); ++ hashmap__init(map, hash_fn, equal_fn, ctx); ++ return map; ++} ++ ++void hashmap__clear(struct hashmap *map) ++{ ++ struct hashmap_entry *cur, *tmp; ++ size_t bkt; ++ ++ hashmap__for_each_entry_safe(map, cur, tmp, bkt) { ++ free(cur); ++ } ++ free(map->buckets); ++ map->buckets = NULL; ++ map->cap = map->cap_bits = map->sz = 0; ++} ++ ++void hashmap__free(struct hashmap *map) ++{ ++ if (!map) ++ return; ++ ++ hashmap__clear(map); ++ free(map); ++} ++ ++size_t hashmap__size(const struct hashmap *map) ++{ ++ return map->sz; ++} ++ ++size_t hashmap__capacity(const struct hashmap *map) ++{ ++ return map->cap; ++} ++ ++static bool hashmap_needs_to_grow(struct hashmap *map) ++{ ++ /* grow if empty or more than 75% filled */ ++ return (map->cap == 0) || ((map->sz + 1) * 4 / 3 > map->cap); ++} ++ ++static int hashmap_grow(struct hashmap *map) ++{ ++ struct hashmap_entry **new_buckets; ++ struct hashmap_entry *cur, *tmp; ++ size_t new_cap_bits, new_cap; ++ size_t h, bkt; ++ ++ new_cap_bits = map->cap_bits + 1; ++ if (new_cap_bits < HASHMAP_MIN_CAP_BITS) ++ new_cap_bits = HASHMAP_MIN_CAP_BITS; ++ ++ new_cap = 1UL << new_cap_bits; ++ new_buckets = calloc(new_cap, sizeof(new_buckets[0])); ++ if (!new_buckets) ++ return -ENOMEM; ++ ++ hashmap__for_each_entry_safe(map, cur, tmp, bkt) { ++ h = hash_bits(map->hash_fn(cur->key, map->ctx), new_cap_bits); ++ hashmap_add_entry(&new_buckets[h], cur); ++ } ++ ++ map->cap = new_cap; ++ map->cap_bits = new_cap_bits; ++ free(map->buckets); ++ map->buckets = new_buckets; ++ ++ return 0; ++} ++ ++static bool hashmap_find_entry(const struct hashmap *map, ++ const void *key, size_t hash, ++ struct hashmap_entry ***pprev, ++ struct hashmap_entry **entry) ++{ ++ struct hashmap_entry *cur, **prev_ptr; ++ ++ if (!map->buckets) ++ return false; ++ ++ for (prev_ptr = &map->buckets[hash], cur = *prev_ptr; ++ cur; ++ prev_ptr = &cur->next, cur = cur->next) { ++ if (map->equal_fn(cur->key, key, map->ctx)) { ++ if (pprev) ++ *pprev = prev_ptr; ++ *entry = cur; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++int hashmap__insert(struct hashmap *map, const void *key, void *value, ++ enum hashmap_insert_strategy strategy, ++ const void **old_key, void **old_value) ++{ ++ struct hashmap_entry *entry; ++ size_t h; ++ int err; ++ ++ if (old_key) ++ *old_key = NULL; ++ if (old_value) ++ *old_value = NULL; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (strategy != HASHMAP_APPEND && ++ hashmap_find_entry(map, key, h, NULL, &entry)) { ++ if (old_key) ++ *old_key = entry->key; ++ if (old_value) ++ *old_value = entry->value; ++ ++ if (strategy == HASHMAP_SET || strategy == HASHMAP_UPDATE) { ++ entry->key = key; ++ entry->value = value; ++ return 0; ++ } else if (strategy == HASHMAP_ADD) { ++ return -EEXIST; ++ } ++ } ++ ++ if (strategy == HASHMAP_UPDATE) ++ return -ENOENT; ++ ++ if (hashmap_needs_to_grow(map)) { ++ err = hashmap_grow(map); ++ if (err) ++ return err; ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ } ++ ++ entry = malloc(sizeof(struct hashmap_entry)); ++ if (!entry) ++ return -ENOMEM; ++ ++ entry->key = key; ++ entry->value = value; ++ hashmap_add_entry(&map->buckets[h], entry); ++ map->sz++; ++ ++ return 0; ++} ++ ++bool hashmap__find(const struct hashmap *map, const void *key, void **value) ++{ ++ struct hashmap_entry *entry; ++ size_t h; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (!hashmap_find_entry(map, key, h, NULL, &entry)) ++ return false; ++ ++ if (value) ++ *value = entry->value; ++ return true; ++} ++ ++bool hashmap__delete(struct hashmap *map, const void *key, ++ const void **old_key, void **old_value) ++{ ++ struct hashmap_entry **pprev, *entry; ++ size_t h; ++ ++ h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); ++ if (!hashmap_find_entry(map, key, h, &pprev, &entry)) ++ return false; ++ ++ if (old_key) ++ *old_key = entry->key; ++ if (old_value) ++ *old_value = entry->value; ++ ++ hashmap_del_entry(pprev, entry); ++ free(entry); ++ map->sz--; ++ ++ return true; ++} ++ +diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h +new file mode 100644 +index 000000000000..df59fd4fc95b +--- /dev/null ++++ b/tools/perf/util/hashmap.h +@@ -0,0 +1,176 @@ ++/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ ++ ++/* ++ * Generic non-thread safe hash map implementation. ++ * ++ * Copyright (c) 2019 Facebook ++ */ ++#ifndef __LIBBPF_HASHMAP_H ++#define __LIBBPF_HASHMAP_H ++ ++#include ++#include ++#include ++#ifndef __WORDSIZE ++#define __WORDSIZE (__SIZEOF_LONG__ * 8) ++#endif ++ ++static inline size_t hash_bits(size_t h, int bits) ++{ ++ /* shuffle bits and return requested number of upper bits */ ++ return (h * 11400714819323198485llu) >> (__WORDSIZE - bits); ++} ++ ++typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); ++typedef bool (*hashmap_equal_fn)(const void *key1, const void *key2, void *ctx); ++ ++struct hashmap_entry { ++ const void *key; ++ void *value; ++ struct hashmap_entry *next; ++}; ++ ++struct hashmap { ++ hashmap_hash_fn hash_fn; ++ hashmap_equal_fn equal_fn; ++ void *ctx; ++ ++ struct hashmap_entry **buckets; ++ size_t cap; ++ size_t cap_bits; ++ size_t sz; ++}; ++ ++#define HASHMAP_INIT(hash_fn, equal_fn, ctx) { \ ++ .hash_fn = (hash_fn), \ ++ .equal_fn = (equal_fn), \ ++ .ctx = (ctx), \ ++ .buckets = NULL, \ ++ .cap = 0, \ ++ .cap_bits = 0, \ ++ .sz = 0, \ ++} ++ ++void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, void *ctx); ++struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, ++ hashmap_equal_fn equal_fn, ++ void *ctx); ++void hashmap__clear(struct hashmap *map); ++void hashmap__free(struct hashmap *map); ++ ++size_t hashmap__size(const struct hashmap *map); ++size_t hashmap__capacity(const struct hashmap *map); ++ ++/* ++ * Hashmap insertion strategy: ++ * - HASHMAP_ADD - only add key/value if key doesn't exist yet; ++ * - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise, ++ * update value; ++ * - HASHMAP_UPDATE - update value, if key already exists; otherwise, do ++ * nothing and return -ENOENT; ++ * - HASHMAP_APPEND - always add key/value pair, even if key already exists. ++ * This turns hashmap into a multimap by allowing multiple values to be ++ * associated with the same key. Most useful read API for such hashmap is ++ * hashmap__for_each_key_entry() iteration. If hashmap__find() is still ++ * used, it will return last inserted key/value entry (first in a bucket ++ * chain). ++ */ ++enum hashmap_insert_strategy { ++ HASHMAP_ADD, ++ HASHMAP_SET, ++ HASHMAP_UPDATE, ++ HASHMAP_APPEND, ++}; ++ ++/* ++ * hashmap__insert() adds key/value entry w/ various semantics, depending on ++ * provided strategy value. If a given key/value pair replaced already ++ * existing key/value pair, both old key and old value will be returned ++ * through old_key and old_value to allow calling code do proper memory ++ * management. ++ */ ++int hashmap__insert(struct hashmap *map, const void *key, void *value, ++ enum hashmap_insert_strategy strategy, ++ const void **old_key, void **old_value); ++ ++static inline int hashmap__add(struct hashmap *map, ++ const void *key, void *value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_ADD, NULL, NULL); ++} ++ ++static inline int hashmap__set(struct hashmap *map, ++ const void *key, void *value, ++ const void **old_key, void **old_value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_SET, ++ old_key, old_value); ++} ++ ++static inline int hashmap__update(struct hashmap *map, ++ const void *key, void *value, ++ const void **old_key, void **old_value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_UPDATE, ++ old_key, old_value); ++} ++ ++static inline int hashmap__append(struct hashmap *map, ++ const void *key, void *value) ++{ ++ return hashmap__insert(map, key, value, HASHMAP_APPEND, NULL, NULL); ++} ++ ++bool hashmap__delete(struct hashmap *map, const void *key, ++ const void **old_key, void **old_value); ++ ++bool hashmap__find(const struct hashmap *map, const void *key, void **value); ++ ++/* ++ * hashmap__for_each_entry - iterate over all entries in hashmap ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @bkt: integer used as a bucket loop cursor ++ */ ++#define hashmap__for_each_entry(map, cur, bkt) \ ++ for (bkt = 0; bkt < map->cap; bkt++) \ ++ for (cur = map->buckets[bkt]; cur; cur = cur->next) ++ ++/* ++ * hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe ++ * against removals ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @tmp: struct hashmap_entry * used as a temporary next cursor storage ++ * @bkt: integer used as a bucket loop cursor ++ */ ++#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \ ++ for (bkt = 0; bkt < map->cap; bkt++) \ ++ for (cur = map->buckets[bkt]; \ ++ cur && ({tmp = cur->next; true; }); \ ++ cur = tmp) ++ ++/* ++ * hashmap__for_each_key_entry - iterate over entries associated with given key ++ * @map: hashmap to iterate ++ * @cur: struct hashmap_entry * used as a loop cursor ++ * @key: key to iterate entries for ++ */ ++#define hashmap__for_each_key_entry(map, cur, _key) \ ++ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ ++ map->cap_bits); \ ++ map->buckets ? map->buckets[bkt] : NULL; }); \ ++ cur; \ ++ cur = cur->next) \ ++ if (map->equal_fn(cur->key, (_key), map->ctx)) ++ ++#define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ ++ for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ ++ map->cap_bits); \ ++ cur = map->buckets ? map->buckets[bkt] : NULL; }); \ ++ cur && ({ tmp = cur->next; true; }); \ ++ cur = tmp) \ ++ if (map->equal_fn(cur->key, (_key), map->ctx)) ++ ++#endif /* __LIBBPF_HASHMAP_H */ +-- +2.27.0 + diff --git a/patches/0162-perf-tools-Sync-hashmap.h-with-libbpf-s.patch b/patches/0162-perf-tools-Sync-hashmap.h-with-libbpf-s.patch new file mode 100644 index 0000000..1f39a0a --- /dev/null +++ b/patches/0162-perf-tools-Sync-hashmap.h-with-libbpf-s.patch @@ -0,0 +1,71 @@ +From 7661750ff202b9382e81b0c2de267f029be4a61f Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Fri, 17 Jul 2020 09:35:18 -0300 +Subject: [PATCH 045/201] perf tools: Sync hashmap.h with libbpf's + +mainline inclusion +from mainline-v5.8-rc6 +commit 94fddb7ad019ad9f14d33cd0a6cd159a52a082b8 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8aa259b10a6a759c50137bbbf225df0c17ca5d27 + +------------------------------------------------------------------------ + +To pick up the changes in: + + b2f9f1535bb9 ("libbpf: Fix libbpf hashmap on (I)LP32 architectures") + +Silencing this warning: + + Warning: Kernel ABI header at 'tools/perf/util/hashmap.h' differs from latest version at 'tools/lib/bpf/hashmap.h' + diff -u tools/perf/util/hashmap.h tools/lib/bpf/hashmap.h + +I'll eventually update the warning to remove the "Kernel ABI" part +and instead state libbpf when noticing that the original is at +"tools/lib/something". + +Cc: Adrian Hunter +Cc: Alexei Starovoitov +Cc: Andrii Nakryiko +Cc: Jakub Bogusz +Cc: Jiri Olsa +Cc: Namhyung Kim +Ian Rogers +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/hashmap.h | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h +index df59fd4fc95b..e0af36b0e5d8 100644 +--- a/tools/perf/util/hashmap.h ++++ b/tools/perf/util/hashmap.h +@@ -11,14 +11,18 @@ + #include + #include + #include +-#ifndef __WORDSIZE +-#define __WORDSIZE (__SIZEOF_LONG__ * 8) +-#endif + + static inline size_t hash_bits(size_t h, int bits) + { + /* shuffle bits and return requested number of upper bits */ +- return (h * 11400714819323198485llu) >> (__WORDSIZE - bits); ++#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) ++ /* LP64 case */ ++ return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); ++#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__) ++ return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits); ++#else ++# error "Unsupported size_t size" ++#endif + } + + typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx); +-- +2.27.0 + diff --git a/patches/0163-perf-tools-Update-copy-of-libbpf-s-hashmap.c.patch b/patches/0163-perf-tools-Update-copy-of-libbpf-s-hashmap.c.patch new file mode 100644 index 0000000..c9bc161 --- /dev/null +++ b/patches/0163-perf-tools-Update-copy-of-libbpf-s-hashmap.c.patch @@ -0,0 +1,81 @@ +From 4585d686a89dbea92f4d25ad72f249079bc17205 Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Wed, 18 Nov 2020 08:32:33 -0300 +Subject: [PATCH 046/201] perf tools: Update copy of libbpf's hashmap.c + +mainline inclusion +from mainline-v5.10-rc6 +commit 3b13eaf0ba1d5ab59368e23ff5e5350f51c1a352 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3b13eaf0ba1d5ab59368e23ff5e5350f51c1a352 + +------------------------------------------------------------------------ + +To pick the changes in: + + 7a078d2d18801bba ("libbpf, hashmap: Fix undefined behavior in hash_bits") + +That don't entail any changes in tools/perf. + +This addresses this perf build warning: + + Warning: Kernel ABI header at 'tools/perf/util/hashmap.h' differs from latest version at 'tools/lib/bpf/hashmap.h' + diff -u tools/perf/util/hashmap.h tools/lib/bpf/hashmap.h + +Not a kernel ABI, its just that this uses the mechanism in place for +checking kernel ABI files drift. + +Cc: Adrian Hunter +Cc: Daniel Borkmann +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Namhyung Kim +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/hashmap.h | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h +index e0af36b0e5d8..6a3c3d8bb4ab 100644 +--- a/tools/perf/util/hashmap.h ++++ b/tools/perf/util/hashmap.h +@@ -15,6 +15,9 @@ + static inline size_t hash_bits(size_t h, int bits) + { + /* shuffle bits and return requested number of upper bits */ ++ if (bits == 0) ++ return 0; ++ + #if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__) + /* LP64 case */ + return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits); +@@ -162,17 +165,17 @@ bool hashmap__find(const struct hashmap *map, const void *key, void **value); + * @key: key to iterate entries for + */ + #define hashmap__for_each_key_entry(map, cur, _key) \ +- for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ +- map->cap_bits); \ +- map->buckets ? map->buckets[bkt] : NULL; }); \ ++ for (cur = map->buckets \ ++ ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ ++ : NULL; \ + cur; \ + cur = cur->next) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) + + #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ +- for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\ +- map->cap_bits); \ +- cur = map->buckets ? map->buckets[bkt] : NULL; }); \ ++ for (cur = map->buckets \ ++ ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ ++ : NULL; \ + cur && ({ tmp = cur->next; true; }); \ + cur = tmp) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) +-- +2.27.0 + diff --git a/patches/0164-perf-jevents-Support-metric-constraint.patch b/patches/0164-perf-jevents-Support-metric-constraint.patch new file mode 100644 index 0000000..73a287f --- /dev/null +++ b/patches/0164-perf-jevents-Support-metric-constraint.patch @@ -0,0 +1,163 @@ +From a9c52df71f4eb8655717014fe266527a572e5c82 Mon Sep 17 00:00:00 2001 +From: Kan Liang +Date: Mon, 24 Feb 2020 13:59:20 -0800 +Subject: [PATCH 047/201] perf jevents: Support metric constraint + +mainline inclusion +from mainline-v5.7-rc1 +commit 03fe02b113888576dc90c3e918d8e1a76b1ceb63 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=03fe02b113888576dc90c3e918d8e1a76b1ceb63 + +---------------------------------------------------------------------- + +A new field "MetricConstraint" is introduced in JSON event list. + +Extend jevents to parse the field and save the value in +metric_constraint. + +Signed-off-by: Kan Liang +Acked-by: Jiri Olsa +Cc: Andi Kleen +Cc: Jin Yao +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/1582581564-184429-2-git-send-email-kan.liang@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 19 +++++++++++++------ + tools/perf/pmu-events/jevents.h | 2 +- + tools/perf/pmu-events/pmu-events.h | 1 + + 3 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index a1eff577f002..6bf2237fef2d 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -324,7 +324,7 @@ static int print_events_table_entry(void *data, char *name, char *event, + char *pmu, char *unit, char *perpkg, + char *metric_expr, + char *metric_name, char *metric_group, +- char *deprecated) ++ char *deprecated, char *metric_constraint) + { + struct perf_entry_data *pd = data; + FILE *outfp = pd->outfp; +@@ -358,6 +358,8 @@ static int print_events_table_entry(void *data, char *name, char *event, + fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group); + if (deprecated) + fprintf(outfp, "\t.deprecated = \"%s\",\n", deprecated); ++ if (metric_constraint) ++ fprintf(outfp, "\t.metric_constraint = \"%s\",\n", metric_constraint); + fprintf(outfp, "},\n"); + + return 0; +@@ -376,6 +378,7 @@ struct event_struct { + char *metric_name; + char *metric_group; + char *deprecated; ++ char *metric_constraint; + }; + + #define ADD_EVENT_FIELD(field) do { if (field) { \ +@@ -423,7 +426,7 @@ static int save_arch_std_events(void *data, char *name, char *event, + char *desc, char *long_desc, char *pmu, + char *unit, char *perpkg, char *metric_expr, + char *metric_name, char *metric_group, +- char *deprecated) ++ char *deprecated, char *metric_constraint) + { + struct event_struct *es; + +@@ -487,7 +490,7 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc, + char **name, char **long_desc, char **pmu, char **filter, + char **perpkg, char **unit, char **metric_expr, char **metric_name, + char **metric_group, unsigned long long eventcode, +- char **deprecated) ++ char **deprecated, char **metric_constraint) + { + /* try to find matching event from arch standard values */ + struct event_struct *es; +@@ -516,7 +519,7 @@ int json_events(const char *fn, + char *pmu, char *unit, char *perpkg, + char *metric_expr, + char *metric_name, char *metric_group, +- char *deprecated), ++ char *deprecated, char *metric_constraint), + void *data) + { + int err; +@@ -546,6 +549,7 @@ int json_events(const char *fn, + char *metric_name = NULL; + char *metric_group = NULL; + char *deprecated = NULL; ++ char *metric_constraint = NULL; + char *arch_std = NULL; + unsigned long long eventcode = 0; + struct msrmap *msr = NULL; +@@ -630,6 +634,8 @@ int json_events(const char *fn, + addfield(map, &metric_name, "", "", val); + } else if (json_streq(map, field, "MetricGroup")) { + addfield(map, &metric_group, "", "", val); ++ } else if (json_streq(map, field, "MetricConstraint")) { ++ addfield(map, &metric_constraint, "", "", val); + } else if (json_streq(map, field, "MetricExpr")) { + addfield(map, &metric_expr, "", "", val); + for (s = metric_expr; *s; s++) +@@ -671,13 +677,13 @@ int json_events(const char *fn, + &long_desc, &pmu, &filter, &perpkg, + &unit, &metric_expr, &metric_name, + &metric_group, eventcode, +- &deprecated); ++ &deprecated, &metric_constraint); + if (err) + goto free_strings; + } + err = func(data, name, real_event(name, event), desc, long_desc, + pmu, unit, perpkg, metric_expr, metric_name, +- metric_group, deprecated); ++ metric_group, deprecated, metric_constraint); + free_strings: + free(event); + free(desc); +@@ -692,6 +698,7 @@ int json_events(const char *fn, + free(metric_expr); + free(metric_name); + free(metric_group); ++ free(metric_constraint); + free(arch_std); + + if (err) +diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h +index 5cda49a42143..2afc8304529e 100644 +--- a/tools/perf/pmu-events/jevents.h ++++ b/tools/perf/pmu-events/jevents.h +@@ -8,7 +8,7 @@ int json_events(const char *fn, + char *pmu, + char *unit, char *perpkg, char *metric_expr, + char *metric_name, char *metric_group, +- char *deprecated), ++ char *deprecated, char *metric_constraint), + void *data); + char *get_cpu_str(void); + +diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h +index caeb577d36c9..53e76d5d5b37 100644 +--- a/tools/perf/pmu-events/pmu-events.h ++++ b/tools/perf/pmu-events/pmu-events.h +@@ -18,6 +18,7 @@ struct pmu_event { + const char *metric_name; + const char *metric_group; + const char *deprecated; ++ const char *metric_constraint; + }; + + /* +-- +2.27.0 + diff --git a/patches/0165-perf-metricgroup-Factor-out-metricgroup__add_metric_.patch b/patches/0165-perf-metricgroup-Factor-out-metricgroup__add_metric_.patch new file mode 100644 index 0000000..563f174 --- /dev/null +++ b/patches/0165-perf-metricgroup-Factor-out-metricgroup__add_metric_.patch @@ -0,0 +1,125 @@ +From a2ceca18eb350e991b34f4aac6512293e0a9d707 Mon Sep 17 00:00:00 2001 +From: Kan Liang +Date: Mon, 24 Feb 2020 13:59:21 -0800 +Subject: [PATCH 048/201] perf metricgroup: Factor out + metricgroup__add_metric_weak_group() + +mainline inclusion +from mainline-v5.7-rc1 +commit f742634ab47f59160a85ddc502418556b21953c2 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f742634ab47f59160a85ddc502418556b21953c2 + +---------------------------------------------------------------------- + +Factor out metricgroup__add_metric_weak_group() which add metrics into a +weak group. The change can improve code readability. Because following +patch will introduce a function which add standalone metrics. + +Signed-off-by: Kan Liang +Acked-by: Jiri Olsa +Cc: Andi Kleen +Cc: Jin Yao +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/1582581564-184429-3-git-send-email-kan.liang@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 57 ++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 24 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 9f6b0b0f7b59..8951c6f6593b 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -420,13 +420,42 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + strlist__delete(metriclist); + } + ++static void metricgroup__add_metric_weak_group(struct strbuf *events, ++ const char **ids, ++ int idnum) ++{ ++ bool no_group = false; ++ int i; ++ ++ for (i = 0; i < idnum; i++) { ++ pr_debug("found event %s\n", ids[i]); ++ /* ++ * Duration time maps to a software event and can make ++ * groups not count. Always use it outside a ++ * group. ++ */ ++ if (!strcmp(ids[i], "duration_time")) { ++ if (i > 0) ++ strbuf_addf(events, "}:W,"); ++ strbuf_addf(events, "duration_time"); ++ no_group = true; ++ continue; ++ } ++ strbuf_addf(events, "%s%s", ++ i == 0 || no_group ? "{" : ",", ++ ids[i]); ++ no_group = false; ++ } ++ if (!no_group) ++ strbuf_addf(events, "}:W"); ++} ++ + static int metricgroup__add_metric(const char *metric, struct strbuf *events, + struct list_head *group_list) + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); + struct pmu_event *pe; +- int ret = -EINVAL; +- int i, j; ++ int i, ret = -EINVAL; + + if (!map) + return 0; +@@ -443,7 +472,6 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + const char **ids; + int idnum; + struct egroup *eg; +- bool no_group = false; + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + +@@ -452,27 +480,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + continue; + if (events->len > 0) + strbuf_addf(events, ","); +- for (j = 0; j < idnum; j++) { +- pr_debug("found event %s\n", ids[j]); +- /* +- * Duration time maps to a software event and can make +- * groups not count. Always use it outside a +- * group. +- */ +- if (!strcmp(ids[j], "duration_time")) { +- if (j > 0) +- strbuf_addf(events, "}:W,"); +- strbuf_addf(events, "duration_time"); +- no_group = true; +- continue; +- } +- strbuf_addf(events, "%s%s", +- j == 0 || no_group ? "{" : ",", +- ids[j]); +- no_group = false; +- } +- if (!no_group) +- strbuf_addf(events, "}:W"); ++ ++ metricgroup__add_metric_weak_group(events, ids, idnum); + + eg = malloc(sizeof(struct egroup)); + if (!eg) { +-- +2.27.0 + diff --git a/patches/0166-perf-util-Factor-out-sysctl__nmi_watchdog_enabled.patch b/patches/0166-perf-util-Factor-out-sysctl__nmi_watchdog_enabled.patch new file mode 100644 index 0000000..c466a6d --- /dev/null +++ b/patches/0166-perf-util-Factor-out-sysctl__nmi_watchdog_enabled.patch @@ -0,0 +1,112 @@ +From 88ef54c8b0a53893de4781bc27fd92b930d5670b Mon Sep 17 00:00:00 2001 +From: Kan Liang +Date: Mon, 24 Feb 2020 13:59:22 -0800 +Subject: [PATCH 049/201] perf util: Factor out sysctl__nmi_watchdog_enabled() + +mainline inclusion +from mainline-v5.7-rc1 +commit 2a14c1bf017f48a17c8c0ba26a22625363e77cc7 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2a14c1bf017f48a17c8c0ba26a22625363e77cc7 + +---------------------------------------------------------------------- + +The NMI watchdog status is required for metric group constraint +examination. Factor out sysctl__nmi_watchdog_enabled() to retrieve the +NMI watchdog status. + +Users may count more than one metric group each time. If so, the NMI +watchdog status may be retrieved several times. To reduce the overhead, +cache the NMI watchdog status. + +Replace the NMI watchdog status checking in print_footer() by +sysctl__nmi_watchdog_enabled(). + +Suggested-by: Andi Kleen +Signed-off-by: Kan Liang +Acked-by: Jiri Olsa +Cc: Andi Kleen +Cc: Jin Yao +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/1582581564-184429-4-git-send-email-kan.liang@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 5 +---- + tools/perf/util/util.c | 18 ++++++++++++++++++ + tools/perf/util/util.h | 2 ++ + 3 files changed, 21 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index c96c0715171f..0d8943ead576 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1800,7 +1800,6 @@ static void print_footer(struct perf_stat_config *config) + { + double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; + FILE *output = config->output; +- int n; + + if (!null_run) + fprintf(output, "\n"); +@@ -1834,9 +1833,7 @@ static void print_footer(struct perf_stat_config *config) + } + fprintf(output, "\n\n"); + +- if (print_free_counters_hint && +- sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && +- n > 0) ++ if (print_free_counters_hint && sysctl__nmi_watchdog_enabled()) + fprintf(output, + "Some events weren't counted. Try disabling the NMI watchdog:\n" + " echo 0 > /proc/sys/kernel/nmi_watchdog\n" +diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c +index eac5b858a371..935e2be276d5 100644 +--- a/tools/perf/util/util.c ++++ b/tools/perf/util/util.c +@@ -75,6 +75,24 @@ int sysctl__max_stack(void) + return sysctl_perf_event_max_stack; + } + ++bool sysctl__nmi_watchdog_enabled(void) ++{ ++ static bool cached; ++ static bool nmi_watchdog; ++ int value; ++ ++ if (cached) ++ return nmi_watchdog; ++ ++ if (sysctl__read_int("kernel/nmi_watchdog", &value) < 0) ++ return false; ++ ++ nmi_watchdog = (value > 0) ? true : false; ++ cached = true; ++ ++ return nmi_watchdog; ++} ++ + bool test_attr__enabled; + + bool perf_host = true; +diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h +index 2efec9e77753..bd39aad17eea 100644 +--- a/tools/perf/util/util.h ++++ b/tools/perf/util/util.h +@@ -47,6 +47,8 @@ int __pure cacheline_size(void); + + int sysctl__max_stack(void); + ++bool sysctl__nmi_watchdog_enabled(void); ++ + int fetch_kernel_version(unsigned int *puint, + char *str, size_t str_sz); + #define KVER_VERSION(x) (((x) >> 16) & 0xff) +-- +2.27.0 + diff --git a/patches/0167-perf-metricgroup-Support-metric-constraint.patch b/patches/0167-perf-metricgroup-Support-metric-constraint.patch new file mode 100644 index 0000000..4e09045 --- /dev/null +++ b/patches/0167-perf-metricgroup-Support-metric-constraint.patch @@ -0,0 +1,138 @@ +From f7fceacb6e8e14742426d7eda0cb9b0f09f5b312 Mon Sep 17 00:00:00 2001 +From: Kan Liang +Date: Mon, 24 Feb 2020 13:59:23 -0800 +Subject: [PATCH 050/201] perf metricgroup: Support metric constraint + +mainline inclusion +from mainline-v5.7-rc1 +commit ab483d8bc8acb83f0103bc38ef8f2c27d98ffd1b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ab483d8bc8acb83f0103bc38ef8f2c27d98ffd1b + +---------------------------------------------------------------------- + +Some metric groups have metric constraints. A metric group can be +scheduled as a group only when some constraints are applied. For +example, Page_Walks_Utilization has a metric constraint, +"NO_NMI_WATCHDOG". + +When NMI watchdog is disabled, the metric group can be scheduled as a +group. Otherwise, splitting the metric group into standalone metrics. + +Add a new function, metricgroup__has_constraint(), to check whether all +constraints are applied. If not, splitting the metric group into +standalone metrics. + +Currently, only one constraint, "NO_NMI_WATCHDOG", is checked. Print a +warning for the metric group with the constraint, when NMI WATCHDOG is +enabled. + +Signed-off-by: Kan Liang +Acked-by: Jiri Olsa +Cc: Andi Kleen +Cc: Jin Yao +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/1582581564-184429-5-git-send-email-kan.liang@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 54 ++++++++++++++++++++++++++++++++++- + 1 file changed, 53 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 8951c6f6593b..4baa9f2040ec 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include "util.h" + + struct metric_event *metricgroup__lookup(struct rblist *metric_events, + struct perf_evsel *evsel, +@@ -450,6 +452,49 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, + strbuf_addf(events, "}:W"); + } + ++static void metricgroup__add_metric_non_group(struct strbuf *events, ++ const char **ids, ++ int idnum) ++{ ++ int i; ++ ++ for (i = 0; i < idnum; i++) ++ strbuf_addf(events, ",%s", ids[i]); ++} ++ ++static void metricgroup___watchdog_constraint_hint(const char *name, bool foot) ++{ ++ static bool violate_nmi_constraint; ++ ++ if (!foot) { ++ pr_warning("Splitting metric group %s into standalone metrics.\n", name); ++ violate_nmi_constraint = true; ++ return; ++ } ++ ++ if (!violate_nmi_constraint) ++ return; ++ ++ pr_warning("Try disabling the NMI watchdog to comply NO_NMI_WATCHDOG metric constraint:\n" ++ " echo 0 > /proc/sys/kernel/nmi_watchdog\n" ++ " perf stat ...\n" ++ " echo 1 > /proc/sys/kernel/nmi_watchdog\n"); ++} ++ ++static bool metricgroup__has_constraint(struct pmu_event *pe) ++{ ++ if (!pe->metric_constraint) ++ return false; ++ ++ if (!strcmp(pe->metric_constraint, "NO_NMI_WATCHDOG") && ++ sysctl__nmi_watchdog_enabled()) { ++ metricgroup___watchdog_constraint_hint(pe->metric_name, false); ++ return true; ++ } ++ ++ return false; ++} ++ + static int metricgroup__add_metric(const char *metric, struct strbuf *events, + struct list_head *group_list) + { +@@ -481,7 +526,10 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + if (events->len > 0) + strbuf_addf(events, ","); + +- metricgroup__add_metric_weak_group(events, ids, idnum); ++ if (metricgroup__has_constraint(pe)) ++ metricgroup__add_metric_non_group(events, ids, idnum); ++ else ++ metricgroup__add_metric_weak_group(events, ids, idnum); + + eg = malloc(sizeof(struct egroup)); + if (!eg) { +@@ -523,6 +571,10 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events, + } + } + free(nlist); ++ ++ if (!ret) ++ metricgroup___watchdog_constraint_hint(NULL, true); ++ + return ret; + } + +-- +2.27.0 + diff --git a/patches/0168-perf-vendor-events-intel-Add-NO_NMI_WATCHDOG-metric-.patch b/patches/0168-perf-vendor-events-intel-Add-NO_NMI_WATCHDOG-metric-.patch new file mode 100644 index 0000000..c144026 --- /dev/null +++ b/patches/0168-perf-vendor-events-intel-Add-NO_NMI_WATCHDOG-metric-.patch @@ -0,0 +1,187 @@ +From 6a06ffa3cbe8297a580a72f5b24c6720adeb87b9 Mon Sep 17 00:00:00 2001 +From: Kan Liang +Date: Mon, 24 Feb 2020 13:59:24 -0800 +Subject: [PATCH 051/201] perf vendor events intel: Add NO_NMI_WATCHDOG metric + constraint + +mainline inclusion +from mainline-v5.7-rc1 +commit b95fcd2c1c25bd14f55d5d6ab268b3ab00b8a774 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b95fcd2c1c25bd14f55d5d6ab268b3ab00b8a774 + +---------------------------------------------------------------------- + +Add NO_NMI_WATCHDOG metric constraint to Page_Walks_Utilization for Sky Lake +and Cascade Lake. + +Committer testing: + +On a Lenovo T480S, Intel(R) Core(TM) i7-8650U Kaby Lake, that looking at x86's +mapfile.csv file is a: + + $ grep -w skylake tools/perf/pmu-events/arch/x86/mapfile.csv + GenuineIntel-6-[4589]E,v24,skylake,core + $ + +So uses the constraint added in this patch in this file: + + tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json + +Before: + + # perf stat -a -M Page_Walks_Utilization sleep 2 + + Performance counter stats for 'system wide': + + itlb_misses.walk_pending (0.00%) + dtlb_load_misses.walk_pending (0.00%) + dtlb_store_misses.walk_pending (0.00%) + ept.walk_pending (0.00%) + cycles (0.00%) + + 2.001750514 seconds time elapsed + + Some events weren't counted. Try disabling the NMI watchdog: + echo 0 > /proc/sys/kernel/nmi_watchdog + perf stat ... + echo 1 > /proc/sys/kernel/nmi_watchdog + The events in group usually have to be from the same PMU. Try reorganizing the group. + # + +After: + + # perf stat -a -M Page_Walks_Utilization sleep 2 + Splitting metric group Page_Walks_Utilization into standalone metrics. + Try disabling the NMI watchdog to comply NO_NMI_WATCHDOG metric constraint: + echo 0 > /proc/sys/kernel/nmi_watchdog + perf stat ... + echo 1 > /proc/sys/kernel/nmi_watchdog + , + Performance counter stats for 'system wide': + + 36,883,102 itlb_misses.walk_pending # 0.1 Page_Walks_Utilization (79.99%) + 123,104,146 dtlb_load_misses.walk_pending (80.02%) + 13,720,795 dtlb_store_misses.walk_pending (79.99%) + 0 ept.walk_pending (79.99%) + 1,519,948,400 cycles (80.01%) + + 2.002170780 seconds time elapsed + + # + +Before and after, if we disable the nmi_watchdog we get: + + # echo 0 > /proc/sys/kernel/nmi_watchdog + # perf stat -a -M Page_Walks_Utilization sleep 2 + + Performance counter stats for 'system wide': + + 33,721,658 itlb_misses.walk_pending # 0.1 Page_Walks_Utilization + 84,070,996 dtlb_load_misses.walk_pending + 9,816,071 dtlb_store_misses.walk_pending + 0 ept.walk_pending + 704,920,899 cycles + + 2.002331670 seconds time elapsed + + # + + More information about the metric expressions: + + # perf stat -v -a -M Page_Walks_Utilization sleep 2 + Using CPUID GenuineIntel-6-8E-A + metric expr ( itlb_misses.walk_pending + dtlb_load_misses.walk_pending + dtlb_store_misses.walk_pending + ept.walk_pending ) / ( 2 * cycles ) for Page_Walks_Utilization + found event itlb_misses.walk_pending + found event dtlb_load_misses.walk_pending + found event dtlb_store_misses.walk_pending + found event ept.walk_pending + found event cycles + adding {itlb_misses.walk_pending,dtlb_load_misses.walk_pending,dtlb_store_misses.walk_pending,ept.walk_pending,cycles}:W + -> cpu/umask=0x10,(null)=0x186a3,event=0x85/ + -> cpu/umask=0x10,(null)=0x1e8483,event=0x8/ + -> cpu/umask=0x10,(null)=0x1e8483,event=0x49/ + -> cpu/umask=0x10,(null)=0x1e8483,event=0x4f/ + itlb_misses.walk_pending: 8085772 16010162799 16010162799 + dtlb_load_misses.walk_pending: 28134579 16010162799 16010162799 + dtlb_store_misses.walk_pending: 7276535 16010162799 16010162799 + ept.walk_pending: 2 16010162799 16010162799 + cycles: 315140605 16010162799 16010162799 + + Performance counter stats for 'system wide': + + 8,085,772 itlb_misses.walk_pending # 0.1 Page_Walks_Utilization + 28,134,579 dtlb_load_misses.walk_pending + 7,276,535 dtlb_store_misses.walk_pending + 2 ept.walk_pending + 315,140,605 cycles + + 2.002333181 seconds time elapsed + + # + +Signed-off-by: Kan Liang +Acked-by: Jiri Olsa +Tested-by: Arnaldo Carvalho de Melo +Cc: Andi Kleen +Cc: Jin Yao +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/1582581564-184429-6-git-send-email-kan.liang@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json | 3 ++- + tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json | 3 ++- + tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json | 3 ++- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json +index 36c903faed0b..13a703c91db8 100644 +--- a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json ++++ b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json +@@ -87,7 +87,8 @@ + "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses", + "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles) )", + "MetricGroup": "TLB", +- "MetricName": "Page_Walks_Utilization" ++ "MetricName": "Page_Walks_Utilization", ++ "MetricConstraint": "NO_NMI_WATCHDOG" + }, + { + "BriefDescription": "Average CPU Utilization", +diff --git a/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json +index 71e9737f4614..91a2422d2ffc 100644 +--- a/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json ++++ b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json +@@ -87,7 +87,8 @@ + "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses", + "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles) )", + "MetricGroup": "TLB", +- "MetricName": "Page_Walks_Utilization" ++ "MetricName": "Page_Walks_Utilization", ++ "MetricConstraint": "NO_NMI_WATCHDOG" + }, + { + "BriefDescription": "Average CPU Utilization", +diff --git a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json +index 71e9737f4614..91a2422d2ffc 100644 +--- a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json ++++ b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json +@@ -87,7 +87,8 @@ + "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses", + "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * (( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else cycles) )", + "MetricGroup": "TLB", +- "MetricName": "Page_Walks_Utilization" ++ "MetricName": "Page_Walks_Utilization", ++ "MetricConstraint": "NO_NMI_WATCHDOG" + }, + { + "BriefDescription": "Average CPU Utilization", +-- +2.27.0 + diff --git a/patches/0169-perf-expr-Add-expr.c-object.patch b/patches/0169-perf-expr-Add-expr.c-object.patch new file mode 100644 index 0000000..62cc573 --- /dev/null +++ b/patches/0169-perf-expr-Add-expr.c-object.patch @@ -0,0 +1,108 @@ +From 394191d5b78ee88a058463b156c75919c8969005 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 28 Feb 2020 10:36:12 +0100 +Subject: [PATCH 052/201] perf expr: Add expr.c object + +mainline inclusion +from mainline-v5.7-rc1 +commit 576a65b6974ddc830a89b6feb6823bd6b5914bde +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=576a65b6974ddc830a89b6feb6823bd6b5914bde + +---------------------------------------------------------------------- + +Add generic expr code into new expr.c object. + +The expr.c object will be mainly used in following change that will get +rid of the manual flex code, + +Signed-off-by: Jiri Olsa +Reviewed-by: Andi Kleen +Cc: Alexander Shishkin +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200228093616.67125-2-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/Build +--- + tools/perf/util/Build | 1 + + tools/perf/util/expr.c | 19 +++++++++++++++++++ + tools/perf/util/expr.y | 15 --------------- + 3 files changed, 20 insertions(+), 15 deletions(-) + create mode 100644 tools/perf/util/expr.c + +diff --git a/tools/perf/util/Build b/tools/perf/util/Build +index de3b99f927ac..a7d2bb7edb2d 100644 +--- a/tools/perf/util/Build ++++ b/tools/perf/util/Build +@@ -106,6 +106,7 @@ libperf-y += drv_configs.o + libperf-y += units.o + libperf-y += time-utils.o + libperf-y += expr-bison.o ++libperf-y += expr.o + libperf-y += branch.o + libperf-y += mem2node.o + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +new file mode 100644 +index 000000000000..816b23b2068a +--- /dev/null ++++ b/tools/perf/util/expr.c +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include "expr.h" ++ ++/* Caller must make sure id is allocated */ ++void expr__add_id(struct parse_ctx *ctx, const char *name, double val) ++{ ++ int idx; ++ ++ assert(ctx->num_ids < MAX_PARSE_ID); ++ idx = ctx->num_ids++; ++ ctx->ids[idx].name = name; ++ ctx->ids[idx].val = val; ++} ++ ++void expr__ctx_init(struct parse_ctx *ctx) ++{ ++ ctx->num_ids = 0; ++} +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index e7bd19c384ae..5f75e27d1bd8 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -167,21 +167,6 @@ static int expr__lex(YYSTYPE *res, const char **pp) + return tok; + } + +-/* Caller must make sure id is allocated */ +-void expr__add_id(struct parse_ctx *ctx, const char *name, double val) +-{ +- int idx; +- assert(ctx->num_ids < MAX_PARSE_ID); +- idx = ctx->num_ids++; +- ctx->ids[idx].name = name; +- ctx->ids[idx].val = val; +-} +- +-void expr__ctx_init(struct parse_ctx *ctx) +-{ +- ctx->num_ids = 0; +-} +- + static bool already_seen(const char *val, const char *one, const char **other, + int num_other) + { +-- +2.27.0 + diff --git a/patches/0170-perf-expr-Move-expr-lexer-to-flex.patch b/patches/0170-perf-expr-Move-expr-lexer-to-flex.patch new file mode 100644 index 0000000..bce893c --- /dev/null +++ b/patches/0170-perf-expr-Move-expr-lexer-to-flex.patch @@ -0,0 +1,562 @@ +From b0eeeeadefa2356dd425e2fbd721688688bc4f96 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 28 Feb 2020 10:36:13 +0100 +Subject: [PATCH 053/201] perf expr: Move expr lexer to flex + +mainline inclusion +from mainline-v5.7-rc1 +commit 26226a97724d1671d553b8eb0cd95b0a5557cfb2 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=26226a97724d1671d553b8eb0cd95b0a5557cfb2 + +---------------------------------------------------------------------- + +Adding expr flex code instead of the manual parser code. So it's easily +extensible in upcoming changes. + +The new flex code is in flex.l object and gets compiled like all the +other flexers we use. It's defined as flex reentrant parser. + +It's used by both expr__parse and expr__find_other interfaces by +separating the starting point. + +There's no intended change of functionality ;-) the test expr is +passing. + +Signed-off-by: Jiri Olsa +Reviewed-by: Andi Kleen +Cc: Alexander Shishkin +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200228093616.67125-3-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/Build +--- + tools/perf/util/Build | 10 ++- + tools/perf/util/expr.c | 93 +++++++++++++++++++++++ + tools/perf/util/expr.h | 2 - + tools/perf/util/expr.l | 114 +++++++++++++++++++++++++++ + tools/perf/util/expr.y | 169 ++++++++--------------------------------- + 5 files changed, 247 insertions(+), 141 deletions(-) + create mode 100644 tools/perf/util/expr.l + +diff --git a/tools/perf/util/Build b/tools/perf/util/Build +index a7d2bb7edb2d..543c73313fda 100644 +--- a/tools/perf/util/Build ++++ b/tools/perf/util/Build +@@ -105,6 +105,7 @@ libperf-y += vsprintf.o + libperf-y += drv_configs.o + libperf-y += units.o + libperf-y += time-utils.o ++libperf-y += expr-flex.o + libperf-y += expr-bison.o + libperf-y += expr.o + libperf-y += branch.o +@@ -171,9 +172,13 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y + $(call rule_mkdir) + $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + ++$(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c ++ $(call rule_mkdir) ++ $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) util/expr.l ++ + $(OUTPUT)util/expr-bison.c: util/expr.y + $(call rule_mkdir) +- $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr__ ++ $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + + $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c + $(call rule_mkdir) +@@ -185,12 +190,14 @@ $(OUTPUT)util/pmu-bison.c: util/pmu.y + + CFLAGS_parse-events-flex.o += -w + CFLAGS_pmu-flex.o += -w ++CFLAGS_expr-flex.o += -w + CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w + CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + + $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c + $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c ++$(OUTPUT)util/expr.o: $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-bison.c + + CFLAGS_bitmap.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" + CFLAGS_find_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" +@@ -198,6 +205,7 @@ CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET + CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" + CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" + CFLAGS_parse-events.o += -Wno-redundant-decls ++CFLAGS_expr.o += -Wno-redundant-decls + CFLAGS_header.o += -include $(OUTPUT)PERF-VERSION-FILE + + $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 816b23b2068a..b39fd39f10ec 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -1,6 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 ++#include + #include + #include "expr.h" ++#include "expr-bison.h" ++#define YY_EXTRA_TYPE int ++#include "expr-flex.h" ++ ++#ifdef PARSER_DEBUG ++extern int expr_debug; ++#endif + + /* Caller must make sure id is allocated */ + void expr__add_id(struct parse_ctx *ctx, const char *name, double val) +@@ -17,3 +25,88 @@ void expr__ctx_init(struct parse_ctx *ctx) + { + ctx->num_ids = 0; + } ++ ++static int ++__expr__parse(double *val, struct parse_ctx *ctx, const char *expr, ++ int start) ++{ ++ YY_BUFFER_STATE buffer; ++ void *scanner; ++ int ret; ++ ++ ret = expr_lex_init_extra(start, &scanner); ++ if (ret) ++ return ret; ++ ++ buffer = expr__scan_string(expr, scanner); ++ ++#ifdef PARSER_DEBUG ++ expr_debug = 1; ++#endif ++ ++ ret = expr_parse(val, ctx, scanner); ++ ++ expr__flush_buffer(buffer, scanner); ++ expr__delete_buffer(buffer, scanner); ++ expr_lex_destroy(scanner); ++ return ret; ++} ++ ++int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp) ++{ ++ return __expr__parse(final_val, ctx, *pp, EXPR_PARSE); ++} ++ ++static bool ++already_seen(const char *val, const char *one, const char **other, ++ int num_other) ++{ ++ int i; ++ ++ if (one && !strcasecmp(one, val)) ++ return true; ++ for (i = 0; i < num_other; i++) ++ if (!strcasecmp(other[i], val)) ++ return true; ++ return false; ++} ++ ++int expr__find_other(const char *p, const char *one, const char ***other, ++ int *num_other) ++{ ++ int err, i = 0, j = 0; ++ struct parse_ctx ctx; ++ ++ expr__ctx_init(&ctx); ++ err = __expr__parse(NULL, &ctx, p, EXPR_OTHER); ++ if (err) ++ return -1; ++ ++ *other = malloc((ctx.num_ids + 1) * sizeof(char *)); ++ if (!*other) ++ return -ENOMEM; ++ ++ for (i = 0, j = 0; i < ctx.num_ids; i++) { ++ const char *str = ctx.ids[i].name; ++ ++ if (already_seen(str, one, *other, j)) ++ continue; ++ ++ str = strdup(str); ++ if (!str) ++ goto out; ++ (*other)[j++] = str; ++ } ++ (*other)[j] = NULL; ++ ++out: ++ if (i != ctx.num_ids) { ++ while (--j) ++ free((char *) (*other)[i]); ++ free(*other); ++ err = -1; ++ } ++ ++ *num_other = j; ++ return err; ++} +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 046160831f90..9332796e6649 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -17,9 +17,7 @@ struct parse_ctx { + + void expr__ctx_init(struct parse_ctx *ctx); + void expr__add_id(struct parse_ctx *ctx, const char *id, double val); +-#ifndef IN_EXPR_Y + int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp); +-#endif + int expr__find_other(const char *p, const char *one, const char ***other, + int *num_other); + +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +new file mode 100644 +index 000000000000..1928f2a3dddc +--- /dev/null ++++ b/tools/perf/util/expr.l +@@ -0,0 +1,114 @@ ++%option prefix="expr_" ++%option reentrant ++%option bison-bridge ++ ++%{ ++#include ++#include "expr.h" ++#include "expr-bison.h" ++ ++char *expr_get_text(yyscan_t yyscanner); ++YYSTYPE *expr_get_lval(yyscan_t yyscanner); ++ ++static int __value(YYSTYPE *yylval, char *str, int base, int token) ++{ ++ u64 num; ++ ++ errno = 0; ++ num = strtoull(str, NULL, base); ++ if (errno) ++ return EXPR_ERROR; ++ ++ yylval->num = num; ++ return token; ++} ++ ++static int value(yyscan_t scanner, int base) ++{ ++ YYSTYPE *yylval = expr_get_lval(scanner); ++ char *text = expr_get_text(scanner); ++ ++ return __value(yylval, text, base, NUMBER); ++} ++ ++/* ++ * Allow @ instead of / to be able to specify pmu/event/ without ++ * conflicts with normal division. ++ */ ++static char *normalize(char *str) ++{ ++ char *ret = str; ++ char *dst = str; ++ ++ while (*str) { ++ if (*str == '@') ++ *dst++ = '/'; ++ else if (*str == '\\') ++ *dst++ = *++str; ++ else ++ *dst++ = *str; ++ str++; ++ } ++ ++ *dst = 0x0; ++ return ret; ++} ++ ++static int str(yyscan_t scanner, int token) ++{ ++ YYSTYPE *yylval = expr_get_lval(scanner); ++ char *text = expr_get_text(scanner); ++ ++ yylval->str = normalize(strdup(text)); ++ if (!yylval->str) ++ return EXPR_ERROR; ++ ++ yylval->str = normalize(yylval->str); ++ return token; ++} ++%} ++ ++number [0-9]+ ++ ++sch [-,=] ++spec \\{sch} ++sym [0-9a-zA-Z_\.:@]+ ++symbol {spec}*{sym}*{spec}*{sym}* ++ ++%% ++ { ++ int start_token; ++ ++ start_token = parse_events_get_extra(yyscanner); ++ ++ if (start_token) { ++ parse_events_set_extra(NULL, yyscanner); ++ return start_token; ++ } ++ } ++ ++max { return MAX; } ++min { return MIN; } ++if { return IF; } ++else { return ELSE; } ++#smt_on { return SMT_ON; } ++{number} { return value(yyscanner, 10); } ++{symbol} { return str(yyscanner, ID); } ++"|" { return '|'; } ++"^" { return '^'; } ++"&" { return '&'; } ++"-" { return '-'; } ++"+" { return '+'; } ++"*" { return '*'; } ++"/" { return '/'; } ++"%" { return '%'; } ++"(" { return '('; } ++")" { return ')'; } ++"," { return ','; } ++. { } ++%% ++ ++int expr_wrap(void *scanner __maybe_unused) ++{ ++ return 1; ++} +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 5f75e27d1bd8..c020d794ccc3 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -1,5 +1,7 @@ + /* Simple expression parser */ + %{ ++#define YYDEBUG 1 ++#include + #include "util.h" + #include "util/debug.h" + #define IN_EXPR_Y 1 +@@ -7,23 +9,23 @@ + #include "smt.h" + #include + +-#define MAXIDLEN 256 + %} + + %define api.pure full + + %parse-param { double *final_val } + %parse-param { struct parse_ctx *ctx } +-%parse-param { const char **pp } +-%lex-param { const char **pp } ++%parse-param {void *scanner} ++%lex-param {void* scanner} + + %union { +- double num; +- char id[MAXIDLEN+1]; ++ double num; ++ char *str; + } + ++%token EXPR_PARSE EXPR_OTHER EXPR_ERROR + %token NUMBER +-%token ID ++%token ID + %token MIN MAX IF ELSE SMT_ON + %left MIN MAX IF + %left '|' +@@ -35,11 +37,9 @@ + %type expr if_expr + + %{ +-static int expr__lex(YYSTYPE *res, const char **pp); +- +-static void expr__error(double *final_val __maybe_unused, ++static void expr_error(double *final_val __maybe_unused, + struct parse_ctx *ctx __maybe_unused, +- const char **pp __maybe_unused, ++ void *scanner, + const char *s) + { + pr_debug("%s\n", s); +@@ -61,6 +61,27 @@ static int lookup_id(struct parse_ctx *ctx, char *id, double *val) + %} + %% + ++start: ++EXPR_PARSE all_expr ++| ++EXPR_OTHER all_other ++ ++all_other: all_other other ++| ++ ++other: ID ++{ ++ if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) { ++ pr_err("failed: way too many variables"); ++ YYABORT; ++ } ++ ++ ctx->ids[ctx->num_ids++].name = $1; ++} ++| ++MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' ++ ++ + all_expr: if_expr { *final_val = $1; } + ; + +@@ -91,131 +112,3 @@ expr: NUMBER + ; + + %% +- +-static int expr__symbol(YYSTYPE *res, const char *p, const char **pp) +-{ +- char *dst = res->id; +- const char *s = p; +- +- if (*p == '#') +- *dst++ = *p++; +- +- while (isalnum(*p) || *p == '_' || *p == '.' || *p == ':' || *p == '@' || *p == '\\') { +- if (p - s >= MAXIDLEN) +- return -1; +- /* +- * Allow @ instead of / to be able to specify pmu/event/ without +- * conflicts with normal division. +- */ +- if (*p == '@') +- *dst++ = '/'; +- else if (*p == '\\') +- *dst++ = *++p; +- else +- *dst++ = *p; +- p++; +- } +- *dst = 0; +- *pp = p; +- dst = res->id; +- switch (dst[0]) { +- case 'm': +- if (!strcmp(dst, "min")) +- return MIN; +- if (!strcmp(dst, "max")) +- return MAX; +- break; +- case 'i': +- if (!strcmp(dst, "if")) +- return IF; +- break; +- case 'e': +- if (!strcmp(dst, "else")) +- return ELSE; +- break; +- case '#': +- if (!strcasecmp(dst, "#smt_on")) +- return SMT_ON; +- break; +- } +- return ID; +-} +- +-static int expr__lex(YYSTYPE *res, const char **pp) +-{ +- int tok; +- const char *s; +- const char *p = *pp; +- +- while (isspace(*p)) +- p++; +- s = p; +- switch (*p++) { +- case '#': +- case 'a' ... 'z': +- case 'A' ... 'Z': +- return expr__symbol(res, p - 1, pp); +- case '0' ... '9': case '.': +- res->num = strtod(s, (char **)&p); +- tok = NUMBER; +- break; +- default: +- tok = *s; +- break; +- } +- *pp = p; +- return tok; +-} +- +-static bool already_seen(const char *val, const char *one, const char **other, +- int num_other) +-{ +- int i; +- +- if (one && !strcasecmp(one, val)) +- return true; +- for (i = 0; i < num_other; i++) +- if (!strcasecmp(other[i], val)) +- return true; +- return false; +-} +- +-int expr__find_other(const char *p, const char *one, const char ***other, +- int *num_otherp) +-{ +- const char *orig = p; +- int err = -1; +- int num_other; +- +- *other = malloc((EXPR_MAX_OTHER + 1) * sizeof(char *)); +- if (!*other) +- return -1; +- +- num_other = 0; +- for (;;) { +- YYSTYPE val; +- int tok = expr__lex(&val, &p); +- if (tok == 0) { +- err = 0; +- break; +- } +- if (tok == ID && !already_seen(val.id, one, *other, num_other)) { +- if (num_other >= EXPR_MAX_OTHER - 1) { +- pr_debug("Too many extra events in %s\n", orig); +- break; +- } +- (*other)[num_other] = strdup(val.id); +- if (!(*other)[num_other]) +- return -1; +- num_other++; +- } +- } +- (*other)[num_other] = NULL; +- *num_otherp = num_other; +- if (err) { +- *num_otherp = 0; +- free(*other); +- *other = NULL; +- } +- return err; +-} +-- +2.27.0 + diff --git a/patches/0171-perf-expr-Increase-EXPR_MAX_OTHER-to-support-metrics.patch b/patches/0171-perf-expr-Increase-EXPR_MAX_OTHER-to-support-metrics.patch new file mode 100644 index 0000000..8eaead2 --- /dev/null +++ b/patches/0171-perf-expr-Increase-EXPR_MAX_OTHER-to-support-metrics.patch @@ -0,0 +1,56 @@ +From 1050f33c27e8ae8ce290d4d712a155054c3656c4 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 28 Feb 2020 10:36:14 +0100 +Subject: [PATCH 054/201] perf expr: Increase EXPR_MAX_OTHER to support metrics + with more than 15 variables + +mainline inclusion +from mainline-v5.7-rc1 +commit 58ca707636dc44c8803a098fb68129f64272f151 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=58ca707636dc44c8803a098fb68129f64272f151 + +---------------------------------------------------------------------- + +We have metrics that define more than 15 variables, like +Branch_Misprediction_Cost. Increasing the allowed variables count to 20. + +As Andy pointed out, we can't go too high in here, because some of the +code has O(n^2) complexity (already_seen) and we might want to do some +other changes (like using hash tables) before increasing the maximum +even more. + +Signed-off-by: Jiri Olsa +Reviewed-by: Andi Kleen +Cc: Alexander Shishkin +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200228093616.67125-4-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 9332796e6649..df0a17df0cef 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -2,7 +2,7 @@ + #ifndef PARSE_CTX_H + #define PARSE_CTX_H 1 + +-#define EXPR_MAX_OTHER 15 ++#define EXPR_MAX_OTHER 20 + #define MAX_PARSE_ID EXPR_MAX_OTHER + + struct parse_id { +-- +2.27.0 + diff --git a/patches/0172-perf-expr-Straighten-expr__parse-expr__find_other-in.patch b/patches/0172-perf-expr-Straighten-expr__parse-expr__find_other-in.patch new file mode 100644 index 0000000..c611e44 --- /dev/null +++ b/patches/0172-perf-expr-Straighten-expr__parse-expr__find_other-in.patch @@ -0,0 +1,132 @@ +From 767e415d346635928ad64ef12a1bbb8bf35d3192 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 28 Feb 2020 10:36:15 +0100 +Subject: [PATCH 055/201] perf expr: Straighten + expr__parse()/expr__find_other() interface + +mainline inclusion +from mainline-v5.7-rc1 +commit 0f9b1e124bb29719eb1572db74b7893bd616f938 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0f9b1e124bb29719eb1572db74b7893bd616f938 + +---------------------------------------------------------------------- + +Now that we have a flex parser we don't need to update the parsed string +pointer, so the interface can just be passed the pointer to the +expression instead of a pointer to pointer. + +Signed-off-by: Jiri Olsa +Reviewed-by: Andi Kleen +Cc: Alexander Shishkin +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200228093616.67125-5-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 6 +++--- + tools/perf/util/expr.c | 8 ++++---- + tools/perf/util/expr.h | 4 ++-- + tools/perf/util/stat-shadow.c | 4 +--- + 4 files changed, 10 insertions(+), 12 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 9acc1e80b936..153977e91e78 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -8,7 +8,7 @@ static int test(struct parse_ctx *ctx, const char *e, double val2) + { + double val; + +- if (expr__parse(&val, ctx, &e)) ++ if (expr__parse(&val, ctx, e)) + TEST_ASSERT_VAL("parse test failed", 0); + TEST_ASSERT_VAL("unexpected value", val == val2); + return 0; +@@ -42,11 +42,11 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + return ret; + + p = "FOO/0"; +- ret = expr__parse(&val, &ctx, &p); ++ ret = expr__parse(&val, &ctx, p); + TEST_ASSERT_VAL("division by zero", ret == 1); + + p = "BAR/"; +- ret = expr__parse(&val, &ctx, &p); ++ ret = expr__parse(&val, &ctx, p); + TEST_ASSERT_VAL("missing operand", ret == 1); + + TEST_ASSERT_VAL("find other", +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index b39fd39f10ec..45b25530db5b 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -52,9 +52,9 @@ __expr__parse(double *val, struct parse_ctx *ctx, const char *expr, + return ret; + } + +-int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp) ++int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr) + { +- return __expr__parse(final_val, ctx, *pp, EXPR_PARSE); ++ return __expr__parse(final_val, ctx, expr, EXPR_PARSE); + } + + static bool +@@ -71,14 +71,14 @@ already_seen(const char *val, const char *one, const char **other, + return false; + } + +-int expr__find_other(const char *p, const char *one, const char ***other, ++int expr__find_other(const char *expr, const char *one, const char ***other, + int *num_other) + { + int err, i = 0, j = 0; + struct parse_ctx ctx; + + expr__ctx_init(&ctx); +- err = __expr__parse(NULL, &ctx, p, EXPR_OTHER); ++ err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER); + if (err) + return -1; + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index df0a17df0cef..9377538f4097 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -17,8 +17,8 @@ struct parse_ctx { + + void expr__ctx_init(struct parse_ctx *ctx); + void expr__add_id(struct parse_ctx *ctx, const char *id, double val); +-int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp); +-int expr__find_other(const char *p, const char *one, const char ***other, ++int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr); ++int expr__find_other(const char *expr, const char *one, const char ***other, + int *num_other); + + #endif +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index c9d92c1dac0e..4651e76dfd5e 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -777,9 +777,7 @@ static void generic_metric(struct perf_stat_config *config, + } + + if (!metric_events[i]) { +- const char *p = metric_expr; +- +- if (expr__parse(&ratio, &pctx, &p) == 0) { ++ if (expr__parse(&ratio, &pctx, metric_expr) == 0) { + char *unit; + char metric_bf[64]; + +-- +2.27.0 + diff --git a/patches/0173-perf-expr-Make-expr__parse-return-1-on-error.patch b/patches/0173-perf-expr-Make-expr__parse-return-1-on-error.patch new file mode 100644 index 0000000..855238e --- /dev/null +++ b/patches/0173-perf-expr-Make-expr__parse-return-1-on-error.patch @@ -0,0 +1,70 @@ +From 118a571d1fc8498e12ed2f2eeac50774616a16b1 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 28 Feb 2020 10:36:16 +0100 +Subject: [PATCH 056/201] perf expr: Make expr__parse() return -1 on error + +mainline inclusion +from mainline-v5.7-rc1 +commit d942815a76463fa53b81d3d1c064f76bb3f80ead +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d942815a76463fa53b81d3d1c064f76bb3f80ead + +---------------------------------------------------------------------- + +To match the error value of the expr__find_other function, so all +exported expr functions return the same values: +0 on success, -1 on error. + +Signed-off-by: Jiri Olsa +Reviewed-by: Andi Kleen +Cc: Alexander Shishkin +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200228093616.67125-6-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 4 ++-- + tools/perf/util/expr.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 153977e91e78..9fd4ba83fbe0 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -43,11 +43,11 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + + p = "FOO/0"; + ret = expr__parse(&val, &ctx, p); +- TEST_ASSERT_VAL("division by zero", ret == 1); ++ TEST_ASSERT_VAL("division by zero", ret == -1); + + p = "BAR/"; + ret = expr__parse(&val, &ctx, p); +- TEST_ASSERT_VAL("missing operand", ret == 1); ++ TEST_ASSERT_VAL("missing operand", ret == -1); + + TEST_ASSERT_VAL("find other", + expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0); +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 45b25530db5b..fd192ddf93c1 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -54,7 +54,7 @@ __expr__parse(double *val, struct parse_ctx *ctx, const char *expr, + + int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr) + { +- return __expr__parse(final_val, ctx, expr, EXPR_PARSE); ++ return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0; + } + + static bool +-- +2.27.0 + diff --git a/patches/0174-perf-expr-Fix-memory-leaks-in-metric-bison.patch b/patches/0174-perf-expr-Fix-memory-leaks-in-metric-bison.patch new file mode 100644 index 0000000..7360759 --- /dev/null +++ b/patches/0174-perf-expr-Fix-memory-leaks-in-metric-bison.patch @@ -0,0 +1,60 @@ +From d7238f2e842192c64a8c45640aa092201b369937 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Tue, 12 May 2020 17:03:18 -0700 +Subject: [PATCH 057/201] perf expr: Fix memory leaks in metric bison + +mainline inclusion +from mainline-v5.8-rc1 +commit 6365757894d5e7ada8a1d074a21fdaf2973dd5ae +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6365757894d5e7ada8a1d074a21fdaf2973dd5ae + +---------------------------------------------------------------------- + +Add a destructor for strings to reclaim memory in the event of errors. +Free the ID given for a lookup, it was previously strdup-ed in the lex +code. + +Signed-off-by: Ian Rogers +Reviewed-by: Andi Kleen +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200513000318.15166-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.y | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index c020d794ccc3..5b1b02f3fafa 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -26,6 +26,7 @@ + %token EXPR_PARSE EXPR_OTHER EXPR_ERROR + %token NUMBER + %token ID ++%destructor { free ($$); } + %token MIN MAX IF ELSE SMT_ON + %left MIN MAX IF + %left '|' +@@ -93,8 +94,10 @@ if_expr: + expr: NUMBER + | ID { if (lookup_id(ctx, $1, &$$) < 0) { + pr_debug("%s not found\n", $1); ++ free($1); + YYABORT; + } ++ free($1); + } + | expr '|' expr { $$ = (long)$1 | (long)$3; } + | expr '&' expr { $$ = (long)$1 & (long)$3; } +-- +2.27.0 + diff --git a/patches/0175-perf-expr-Fix-copy-paste-mistake.patch b/patches/0175-perf-expr-Fix-copy-paste-mistake.patch new file mode 100644 index 0000000..6c5d366 --- /dev/null +++ b/patches/0175-perf-expr-Fix-copy-paste-mistake.patch @@ -0,0 +1,52 @@ +From 5b9896ba53ce9227752c306b7fe2fa2b66513426 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 15 Mar 2020 16:56:09 +0100 +Subject: [PATCH 058/201] perf expr: Fix copy/paste mistake + +mainline inclusion +from mainline-v5.7-rc1 +commit 59a08b4b3b1a9374adacd13cd7544c03e5582e0e +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=59a08b4b3b1a9374adacd13cd7544c03e5582e0e + +---------------------------------------------------------------------- + +Copy/paste leftover from recent refactor. + +Fixes: 26226a97724d ("perf expr: Move expr lexer to flex") +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20200315155609.603948-1-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.l | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index 1928f2a3dddc..eaad29243c23 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -79,10 +79,10 @@ symbol {spec}*{sym}*{spec}*{sym}* + { + int start_token; + +- start_token = parse_events_get_extra(yyscanner); ++ start_token = expr_get_extra(yyscanner); + + if (start_token) { +- parse_events_set_extra(NULL, yyscanner); ++ expr_set_extra(NULL, yyscanner); + return start_token; + } + } +-- +2.27.0 + diff --git a/patches/0176-perf-expr-Add-expr_-prefix-for-parse_ctx-and-parse_i.patch b/patches/0176-perf-expr-Add-expr_-prefix-for-parse_ctx-and-parse_i.patch new file mode 100644 index 0000000..2bf2911 --- /dev/null +++ b/patches/0176-perf-expr-Add-expr_-prefix-for-parse_ctx-and-parse_i.patch @@ -0,0 +1,199 @@ +From be0b4351cde5abe0a3e15fa179848131aef5b4b9 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 2 Apr 2020 02:03:34 +0530 +Subject: [PATCH 059/201] perf expr: Add expr_ prefix for parse_ctx and + parse_id + +mainline inclusion +from mainline-v5.8-rc1 +commit aecce63e2b98f28606b063949cca06facf215d6c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aecce63e2b98f28606b063949cca06facf215d6c + +---------------------------------------------------------------------- + +Adding expr_ prefix for parse_ctx and parse_id, to straighten out the +expr* namespace. + +There's no functional change. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Benjamin Herrenschmidt +Cc: Greg Kroah-Hartman +Cc: Jin Yao +Cc: Joe Mario +Cc: Kajol Jain +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Mamatha Inamdar +Cc: Mark Rutland +Cc: Michael Ellerman +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sukadev Bhattiprolu +Cc: Thomas Gleixner +Cc: linuxppc-dev@lists.ozlabs.org +Link: http://lore.kernel.org/lkml/20200401203340.31402-2-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 4 ++-- + tools/perf/util/expr.c | 10 +++++----- + tools/perf/util/expr.h | 12 ++++++------ + tools/perf/util/expr.y | 6 +++--- + tools/perf/util/stat-shadow.c | 2 +- + 5 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 9fd4ba83fbe0..279cc9876b72 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -4,7 +4,7 @@ + #include "tests.h" + #include + +-static int test(struct parse_ctx *ctx, const char *e, double val2) ++static int test(struct expr_parse_ctx *ctx, const char *e, double val2) + { + double val; + +@@ -20,7 +20,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + const char **other; + double val; + int i, ret; +- struct parse_ctx ctx; ++ struct expr_parse_ctx ctx; + int num_other; + + expr__ctx_init(&ctx); +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index fd192ddf93c1..c8ccc548a585 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -11,7 +11,7 @@ extern int expr_debug; + #endif + + /* Caller must make sure id is allocated */ +-void expr__add_id(struct parse_ctx *ctx, const char *name, double val) ++void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) + { + int idx; + +@@ -21,13 +21,13 @@ void expr__add_id(struct parse_ctx *ctx, const char *name, double val) + ctx->ids[idx].val = val; + } + +-void expr__ctx_init(struct parse_ctx *ctx) ++void expr__ctx_init(struct expr_parse_ctx *ctx) + { + ctx->num_ids = 0; + } + + static int +-__expr__parse(double *val, struct parse_ctx *ctx, const char *expr, ++__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + int start) + { + YY_BUFFER_STATE buffer; +@@ -52,7 +52,7 @@ __expr__parse(double *val, struct parse_ctx *ctx, const char *expr, + return ret; + } + +-int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr) ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr) + { + return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0; + } +@@ -75,7 +75,7 @@ int expr__find_other(const char *expr, const char *one, const char ***other, + int *num_other) + { + int err, i = 0, j = 0; +- struct parse_ctx ctx; ++ struct expr_parse_ctx ctx; + + expr__ctx_init(&ctx); + err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER); +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 9377538f4097..b9e53f2b5844 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -5,19 +5,19 @@ + #define EXPR_MAX_OTHER 20 + #define MAX_PARSE_ID EXPR_MAX_OTHER + +-struct parse_id { ++struct expr_parse_id { + const char *name; + double val; + }; + +-struct parse_ctx { ++struct expr_parse_ctx { + int num_ids; +- struct parse_id ids[MAX_PARSE_ID]; ++ struct expr_parse_id ids[MAX_PARSE_ID]; + }; + +-void expr__ctx_init(struct parse_ctx *ctx); +-void expr__add_id(struct parse_ctx *ctx, const char *id, double val); +-int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr); ++void expr__ctx_init(struct expr_parse_ctx *ctx); ++void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr); + int expr__find_other(const char *expr, const char *one, const char ***other, + int *num_other); + +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 5b1b02f3fafa..2764b196edc3 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -14,7 +14,7 @@ + %define api.pure full + + %parse-param { double *final_val } +-%parse-param { struct parse_ctx *ctx } ++%parse-param { struct expr_parse_ctx *ctx } + %parse-param {void *scanner} + %lex-param {void* scanner} + +@@ -39,14 +39,14 @@ + + %{ + static void expr_error(double *final_val __maybe_unused, +- struct parse_ctx *ctx __maybe_unused, ++ struct expr_parse_ctx *ctx __maybe_unused, + void *scanner, + const char *s) + { + pr_debug("%s\n", s); + } + +-static int lookup_id(struct parse_ctx *ctx, char *id, double *val) ++static int lookup_id(struct expr_parse_ctx *ctx, char *id, double *val) + { + int i; + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 4651e76dfd5e..682334eacff0 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -729,7 +729,7 @@ static void generic_metric(struct perf_stat_config *config, + struct runtime_stat *st) + { + print_metric_t print_metric = out->print_metric; +- struct parse_ctx pctx; ++ struct expr_parse_ctx pctx; + double ratio, scale; + int i; + void *ctxp = out->ctx; +-- +2.27.0 + diff --git a/patches/0177-perf-expr-Add-expr_scanner_ctx-object.patch b/patches/0177-perf-expr-Add-expr_scanner_ctx-object.patch new file mode 100644 index 0000000..b35a1e1 --- /dev/null +++ b/patches/0177-perf-expr-Add-expr_scanner_ctx-object.patch @@ -0,0 +1,119 @@ +From 4d059ad799bb7ef10eb6dc7ea47cc1e8e7f5abb5 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Thu, 2 Apr 2020 02:03:35 +0530 +Subject: [PATCH 060/201] perf expr: Add expr_scanner_ctx object + +mainline inclusion +from mainline-v5.8-rc1 +commit 871f9f599db8d9d2387c0717e712af405290edea +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=871f9f599db8d9d2387c0717e712af405290edea + +---------------------------------------------------------------------- + +Add the expr_scanner_ctx object to hold user data for the expr scanner. +Currently it holds only start_token, Kajol Jain will use it to hold 24x7 +runtime param. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Benjamin Herrenschmidt +Cc: Greg Kroah-Hartman +Cc: Jin Yao +Cc: Joe Mario +Cc: Kajol Jain +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Mamatha Inamdar +Cc: Mark Rutland +Cc: Michael Ellerman +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sukadev Bhattiprolu +Cc: Thomas Gleixner +Cc: linuxppc-dev@lists.ozlabs.org +Link: http://lore.kernel.org/lkml/20200401203340.31402-3-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 6 ++++-- + tools/perf/util/expr.h | 4 ++++ + tools/perf/util/expr.l | 10 +++++----- + 3 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index c8ccc548a585..c3382d58cf40 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -3,7 +3,6 @@ + #include + #include "expr.h" + #include "expr-bison.h" +-#define YY_EXTRA_TYPE int + #include "expr-flex.h" + + #ifdef PARSER_DEBUG +@@ -30,11 +29,14 @@ static int + __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + int start) + { ++ struct expr_scanner_ctx scanner_ctx = { ++ .start_token = start, ++ }; + YY_BUFFER_STATE buffer; + void *scanner; + int ret; + +- ret = expr_lex_init_extra(start, &scanner); ++ ret = expr_lex_init_extra(&scanner_ctx, &scanner); + if (ret) + return ret; + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index b9e53f2b5844..0938ad166ece 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -15,6 +15,10 @@ struct expr_parse_ctx { + struct expr_parse_id ids[MAX_PARSE_ID]; + }; + ++struct expr_scanner_ctx { ++ int start_token; ++}; ++ + void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr); +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index eaad29243c23..2582c2464938 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -76,13 +76,13 @@ sym [0-9a-zA-Z_\.:@]+ + symbol {spec}*{sym}*{spec}*{sym}* + + %% +- { +- int start_token; ++ struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); + +- start_token = expr_get_extra(yyscanner); ++ { ++ int start_token = sctx->start_token; + +- if (start_token) { +- expr_set_extra(NULL, yyscanner); ++ if (sctx->start_token) { ++ sctx->start_token = 0; + return start_token; + } + } +-- +2.27.0 + diff --git a/patches/0178-perf-metrictroup-Split-the-metricgroup__add_metric-f.patch b/patches/0178-perf-metrictroup-Split-the-metricgroup__add_metric-f.patch new file mode 100644 index 0000000..8071ae4 --- /dev/null +++ b/patches/0178-perf-metrictroup-Split-the-metricgroup__add_metric-f.patch @@ -0,0 +1,133 @@ +From 052632aaedcbfdcac4e2a397dcfbb6fad817b24b Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 2 Apr 2020 02:03:36 +0530 +Subject: [PATCH 061/201] perf metrictroup: Split the metricgroup__add_metric + function + +mainline inclusion +from mainline-v5.8-rc1 +commit 47352aba40035ab3fdc50dd03a94456feabed7d8 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=47352aba40035ab3fdc50dd03a94456feabed7d8 + +---------------------------------------------------------------------- + +This patch refactors metricgroup__add_metric function where some part of +it move to function metricgroup__add_metric_param. No logic change. + +Signed-off-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Benjamin Herrenschmidt +Cc: Greg Kroah-Hartman +Cc: Jin Yao +Cc: Joe Mario +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Mamatha Inamdar +Cc: Mark Rutland +Cc: Michael Ellerman +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sukadev Bhattiprolu +Cc: Thomas Gleixner +Cc: linuxppc-dev@lists.ozlabs.org +Link: http://lore.kernel.org/lkml/20200401203340.31402-4-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 60 ++++++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 25 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 4baa9f2040ec..792fecca72e0 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -495,6 +495,39 @@ static bool metricgroup__has_constraint(struct pmu_event *pe) + return false; + } + ++static int __metricgroup__add_metric(struct strbuf *events, ++ struct list_head *group_list, struct pmu_event *pe) ++{ ++ ++ const char **ids; ++ int idnum; ++ struct egroup *eg; ++ ++ if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum) < 0) ++ return -EINVAL; ++ ++ if (events->len > 0) ++ strbuf_addf(events, ","); ++ ++ if (metricgroup__has_constraint(pe)) ++ metricgroup__add_metric_non_group(events, ids, idnum); ++ else ++ metricgroup__add_metric_weak_group(events, ids, idnum); ++ ++ eg = malloc(sizeof(*eg)); ++ if (!eg) ++ return -ENOMEM; ++ ++ eg->ids = ids; ++ eg->idnum = idnum; ++ eg->metric_name = pe->metric_name; ++ eg->metric_expr = pe->metric_expr; ++ eg->metric_unit = pe->unit; ++ list_add_tail(&eg->nd, group_list); ++ ++ return 0; ++} ++ + static int metricgroup__add_metric(const char *metric, struct strbuf *events, + struct list_head *group_list) + { +@@ -514,35 +547,12 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + continue; + if (match_metric(pe->metric_group, metric) || + match_metric(pe->metric_name, metric)) { +- const char **ids; +- int idnum; +- struct egroup *eg; + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + +- if (expr__find_other(pe->metric_expr, +- NULL, &ids, &idnum) < 0) +- continue; +- if (events->len > 0) +- strbuf_addf(events, ","); +- +- if (metricgroup__has_constraint(pe)) +- metricgroup__add_metric_non_group(events, ids, idnum); +- else +- metricgroup__add_metric_weak_group(events, ids, idnum); +- +- eg = malloc(sizeof(struct egroup)); +- if (!eg) { +- ret = -ENOMEM; ++ ret = __metricgroup__add_metric(events, group_list, pe); ++ if (ret == -ENOMEM) + break; +- } +- eg->ids = ids; +- eg->idnum = idnum; +- eg->metric_name = pe->metric_name; +- eg->metric_expr = pe->metric_expr; +- eg->metric_unit = pe->unit; +- list_add_tail(&eg->nd, group_list); +- ret = 0; + } + } + return ret; +-- +2.27.0 + diff --git a/patches/0179-perf-metricgroups-Enhance-JSON-metric-infrastructure.patch b/patches/0179-perf-metricgroups-Enhance-JSON-metric-infrastructure.patch new file mode 100644 index 0000000..80f50fb --- /dev/null +++ b/patches/0179-perf-metricgroups-Enhance-JSON-metric-infrastructure.patch @@ -0,0 +1,450 @@ +From 9e94b0c96739f13fbe54fcb75d18c328f255ed75 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 2 Apr 2020 02:03:37 +0530 +Subject: [PATCH 062/201] perf metricgroups: Enhance JSON/metric infrastructure + to handle "?" + +mainline inclusion +from mainline-v5.8-rc1 +commit 1e1a873dc67fc748cc319a27603f33db91027730 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e1a873dc67fc748cc319a27603f33db91027730 + +---------------------------------------------------------------------- + +Patch enhances current metric infrastructure to handle "?" in the metric +expression. The "?" can be use for parameters whose value not known +while creating metric events and which can be replace later at runtime +to the proper value. It also add flexibility to create multiple events +out of single metric event added in JSON file. + +Patch adds function 'arch_get_runtimeparam' which is a arch specific +function, returns the count of metric events need to be created. By +default it return 1. + +This infrastructure needed for hv_24x7 socket/chip level events. +"hv_24x7" chip level events needs specific chip-id to which the data is +requested. Function 'arch_get_runtimeparam' implemented in header.c +which extract number of sockets from sysfs file "sockets" under +"/sys/devices/hv_24x7/interface/". + +With this patch basically we are trying to create as many metric events +as define by runtime_param. + +For that one loop is added in function 'metricgroup__add_metric', which +create multiple events at run time depend on return value of +'arch_get_runtimeparam' and merge that event in 'group_list'. + +To achieve that we are actually passing this parameter value as part of +`expr__find_other` function and changing "?" present in metric +expression with this value. + +As in our JSON file, there gonna be single metric event, and out of +which we are creating multiple events. + +To understand which data count belongs to which parameter value, +we also printing param value in generic_metric function. + +For example, + + command:# ./perf stat -M PowerBUS_Frequency -C 0 -I 1000 + 1.000101867 9,356,933 hv_24x7/pm_pb_cyc,chip=0/ # 2.3 GHz PowerBUS_Frequency_0 + 1.000101867 9,366,134 hv_24x7/pm_pb_cyc,chip=1/ # 2.3 GHz PowerBUS_Frequency_1 + 2.000314878 9,365,868 hv_24x7/pm_pb_cyc,chip=0/ # 2.3 GHz PowerBUS_Frequency_0 + 2.000314878 9,366,092 hv_24x7/pm_pb_cyc,chip=1/ # 2.3 GHz PowerBUS_Frequency_1 + +So, here _0 and _1 after PowerBUS_Frequency specify parameter value. + +Signed-off-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Benjamin Herrenschmidt +Cc: Greg Kroah-Hartman +Cc: Jin Yao +Cc: Joe Mario +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Mamatha Inamdar +Cc: Mark Rutland +Cc: Michael Ellerman +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sukadev Bhattiprolu +Cc: Thomas Gleixner +Cc: linuxppc-dev@lists.ozlabs.org +Link: http://lore.kernel.org/lkml/20200401203340.31402-5-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.h +--- + tools/perf/arch/powerpc/util/header.c | 8 ++++++++ + tools/perf/tests/expr.c | 8 ++++---- + tools/perf/util/expr.c | 11 ++++++----- + tools/perf/util/expr.h | 5 +++-- + tools/perf/util/expr.l | 27 +++++++++++++++++++------- + tools/perf/util/metricgroup.c | 28 ++++++++++++++++++++++++--- + tools/perf/util/metricgroup.h | 2 ++ + tools/perf/util/stat-shadow.c | 17 ++++++++++------ + 8 files changed, 79 insertions(+), 27 deletions(-) + +diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c +index e46be9ef5a68..0a3816692252 100644 +--- a/tools/perf/arch/powerpc/util/header.c ++++ b/tools/perf/arch/powerpc/util/header.c +@@ -8,6 +8,8 @@ + #include + #include "header.h" + #include "util.h" ++#include "metricgroup.h" ++#include + + #define mfspr(rn) ({unsigned long rval; \ + asm volatile("mfspr %0," __stringify(rn) \ +@@ -45,3 +47,9 @@ get_cpuid_str(struct perf_pmu *pmu __maybe_unused) + + return bufp; + } ++ ++int arch_get_runtimeparam(void) ++{ ++ int count; ++ return sysfs__read_int("/devices/hv_24x7/interface/sockets", &count) < 0 ? 1 : count; ++} +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 279cc9876b72..e7706d93b9fe 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -8,7 +8,7 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2) + { + double val; + +- if (expr__parse(&val, ctx, e)) ++ if (expr__parse(&val, ctx, e, 1)) + TEST_ASSERT_VAL("parse test failed", 0); + TEST_ASSERT_VAL("unexpected value", val == val2); + return 0; +@@ -42,15 +42,15 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + return ret; + + p = "FOO/0"; +- ret = expr__parse(&val, &ctx, p); ++ ret = expr__parse(&val, &ctx, p, 1); + TEST_ASSERT_VAL("division by zero", ret == -1); + + p = "BAR/"; +- ret = expr__parse(&val, &ctx, p); ++ ret = expr__parse(&val, &ctx, p, 1); + TEST_ASSERT_VAL("missing operand", ret == -1); + + TEST_ASSERT_VAL("find other", +- expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0); ++ expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other, 1) == 0); + TEST_ASSERT_VAL("find other", num_other == 3); + TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR")); + TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index c3382d58cf40..aa631e37ad1e 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -27,10 +27,11 @@ void expr__ctx_init(struct expr_parse_ctx *ctx) + + static int + __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, +- int start) ++ int start, int runtime) + { + struct expr_scanner_ctx scanner_ctx = { + .start_token = start, ++ .runtime = runtime, + }; + YY_BUFFER_STATE buffer; + void *scanner; +@@ -54,9 +55,9 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + return ret; + } + +-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr) ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime) + { +- return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0; ++ return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; + } + + static bool +@@ -74,13 +75,13 @@ already_seen(const char *val, const char *one, const char **other, + } + + int expr__find_other(const char *expr, const char *one, const char ***other, +- int *num_other) ++ int *num_other, int runtime) + { + int err, i = 0, j = 0; + struct expr_parse_ctx ctx; + + expr__ctx_init(&ctx); +- err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER); ++ err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime); + if (err) + return -1; + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 0938ad166ece..87d627bb699b 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -17,12 +17,13 @@ struct expr_parse_ctx { + + struct expr_scanner_ctx { + int start_token; ++ int runtime; + }; + + void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); +-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr); ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime); + int expr__find_other(const char *expr, const char *one, const char ***other, +- int *num_other); ++ int *num_other, int runtime); + + #endif +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index 2582c2464938..74b9b59b1aa5 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -35,7 +35,7 @@ static int value(yyscan_t scanner, int base) + * Allow @ instead of / to be able to specify pmu/event/ without + * conflicts with normal division. + */ +-static char *normalize(char *str) ++static char *normalize(char *str, int runtime) + { + char *ret = str; + char *dst = str; +@@ -45,6 +45,19 @@ static char *normalize(char *str) + *dst++ = '/'; + else if (*str == '\\') + *dst++ = *++str; ++ else if (*str == '?') { ++ char *paramval; ++ int i = 0; ++ int size = asprintf(¶mval, "%d", runtime); ++ ++ if (size < 0) ++ *dst++ = '0'; ++ else { ++ while (i < size) ++ *dst++ = paramval[i++]; ++ free(paramval); ++ } ++ } + else + *dst++ = *str; + str++; +@@ -54,16 +67,16 @@ static char *normalize(char *str) + return ret; + } + +-static int str(yyscan_t scanner, int token) ++static int str(yyscan_t scanner, int token, int runtime) + { + YYSTYPE *yylval = expr_get_lval(scanner); + char *text = expr_get_text(scanner); + +- yylval->str = normalize(strdup(text)); ++ yylval->str = normalize(strdup(text), runtime); + if (!yylval->str) + return EXPR_ERROR; + +- yylval->str = normalize(yylval->str); ++ yylval->str = normalize(yylval->str, runtime); + return token; + } + %} +@@ -72,8 +85,8 @@ number [0-9]+ + + sch [-,=] + spec \\{sch} +-sym [0-9a-zA-Z_\.:@]+ +-symbol {spec}*{sym}*{spec}*{sym}* ++sym [0-9a-zA-Z_\.:@?]+ ++symbol {spec}*{sym}*{spec}*{sym}*{spec}*{sym} + + %% + struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); +@@ -93,7 +106,7 @@ if { return IF; } + else { return ELSE; } + #smt_on { return SMT_ON; } + {number} { return value(yyscanner, 10); } +-{symbol} { return str(yyscanner, ID); } ++{symbol} { return str(yyscanner, ID, sctx->runtime); } + "|" { return '|'; } + "^" { return '^'; } + "&" { return '&'; } +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 792fecca72e0..b4fe2e2f3ca4 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -96,6 +96,7 @@ struct egroup { + const char *metric_name; + const char *metric_expr; + const char *metric_unit; ++ int runtime; + }; + + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, +@@ -211,6 +212,7 @@ static int metricgroup__setup_events(struct list_head *groups, + expr->metric_name = eg->metric_name; + expr->metric_unit = eg->metric_unit; + expr->metric_events = metric_events; ++ expr->runtime = eg->runtime; + list_add(&expr->nd, &me->head); + } + +@@ -495,15 +497,20 @@ static bool metricgroup__has_constraint(struct pmu_event *pe) + return false; + } + ++int __weak arch_get_runtimeparam(void) ++{ ++ return 1; ++} ++ + static int __metricgroup__add_metric(struct strbuf *events, +- struct list_head *group_list, struct pmu_event *pe) ++ struct list_head *group_list, struct pmu_event *pe, int runtime) + { + + const char **ids; + int idnum; + struct egroup *eg; + +- if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum) < 0) ++ if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum, runtime) < 0) + return -EINVAL; + + if (events->len > 0) +@@ -523,6 +530,7 @@ static int __metricgroup__add_metric(struct strbuf *events, + eg->metric_name = pe->metric_name; + eg->metric_expr = pe->metric_expr; + eg->metric_unit = pe->unit; ++ eg->runtime = runtime; + list_add_tail(&eg->nd, group_list); + + return 0; +@@ -550,7 +558,21 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + +- ret = __metricgroup__add_metric(events, group_list, pe); ++ if (!strstr(pe->metric_expr, "?")) { ++ ret = __metricgroup__add_metric(events, group_list, pe, 1); ++ } else { ++ int j, count; ++ ++ count = arch_get_runtimeparam(); ++ ++ /* This loop is added to create multiple ++ * events depend on count value and add ++ * those events to group_list. ++ */ ++ ++ for (j = 0; j < count; j++) ++ ret = __metricgroup__add_metric(events, group_list, pe, j); ++ } + if (ret == -ENOMEM) + break; + } +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 9c6e6913f905..f2a17a05eb81 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -22,6 +22,7 @@ struct metric_expr { + const char *metric_name; + const char *metric_unit; + struct perf_evsel **metric_events; ++ int runtime; + }; + + struct metric_event *metricgroup__lookup(struct rblist *metric_events, +@@ -34,4 +35,5 @@ int metricgroup__parse_groups(const struct option *opt, + void metricgroup__print(bool metrics, bool groups, char *filter, + bool raw, bool details); + bool metricgroup__has_metric(const char *metric); ++int arch_get_runtimeparam(void); + #endif +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 682334eacff0..dfa33d1bce53 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -336,7 +336,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) + metric_events = counter->metric_events; + if (!metric_events) { + if (expr__find_other(counter->metric_expr, counter->name, +- &metric_names, &num_metric_names) < 0) ++ &metric_names, &num_metric_names, 1) < 0) + continue; + + metric_events = calloc(sizeof(struct perf_evsel *), +@@ -723,6 +723,7 @@ static void generic_metric(struct perf_stat_config *config, + char *name, + const char *metric_name, + const char *metric_unit, ++ int runtime, + double avg, + int cpu, + struct perf_stat_output_ctx *out, +@@ -777,7 +778,7 @@ static void generic_metric(struct perf_stat_config *config, + } + + if (!metric_events[i]) { +- if (expr__parse(&ratio, &pctx, metric_expr) == 0) { ++ if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { + char *unit; + char metric_bf[64]; + +@@ -786,9 +787,13 @@ static void generic_metric(struct perf_stat_config *config, + &unit, &scale) >= 0) { + ratio *= scale; + } +- +- scnprintf(metric_bf, sizeof(metric_bf), ++ if (strstr(metric_expr, "?")) ++ scnprintf(metric_bf, sizeof(metric_bf), ++ "%s %s_%d", unit, metric_name, runtime); ++ else ++ scnprintf(metric_bf, sizeof(metric_bf), + "%s %s", unit, metric_name); ++ + print_metric(config, ctxp, NULL, "%8.1f", + metric_bf, ratio); + } else { +@@ -1022,7 +1027,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + print_metric(config, ctxp, NULL, NULL, name, 0); + } else if (evsel->metric_expr) { + generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, +- evsel->metric_name, NULL, avg, cpu, out, st); ++ evsel->metric_name, NULL, 1, avg, cpu, out, st); + } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { + char unit = 'M'; + char unit_buf[10]; +@@ -1051,7 +1056,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + out->new_line(config, ctxp); + generic_metric(config, mexp->metric_expr, mexp->metric_events, + evsel->name, mexp->metric_name, +- mexp->metric_unit, avg, cpu, out, st); ++ mexp->metric_unit, mexp->runtime, avg, cpu, out, st); + } + } + if (num == 0) +-- +2.27.0 + diff --git a/patches/0180-perf-tests-expr-Added-test-for-runtime-param-in-metr.patch b/patches/0180-perf-tests-expr-Added-test-for-runtime-param-in-metr.patch new file mode 100644 index 0000000..a9625b2 --- /dev/null +++ b/patches/0180-perf-tests-expr-Added-test-for-runtime-param-in-metr.patch @@ -0,0 +1,69 @@ +From 74604ca3049109ef42ef4ed352b712f47de6898f Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 2 Apr 2020 02:03:38 +0530 +Subject: [PATCH 063/201] perf tests expr: Added test for runtime param in + metric expression + +mainline inclusion +from mainline-v5.8-rc1 +commit 9022608ec5babbb0fa631234098d52895e7e34d8 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9022608ec5babbb0fa631234098d52895e7e34d8 + +---------------------------------------------------------------------- + +Added test case for parsing "?" in metric expression. + +Signed-off-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anju T Sudhakar +Cc: Benjamin Herrenschmidt +Cc: Greg Kroah-Hartman +Cc: Jin Yao +Cc: Joe Mario +Cc: Kan Liang +Cc: Madhavan Srinivasan +Cc: Mamatha Inamdar +Cc: Mark Rutland +Cc: Michael Ellerman +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sukadev Bhattiprolu +Cc: Thomas Gleixner +Cc: linuxppc-dev@lists.ozlabs.org +Link: http://lore.kernel.org/lkml/20200401203340.31402-6-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index e7706d93b9fe..d7f74094f935 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -57,6 +57,14 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); + TEST_ASSERT_VAL("find other", other[3] == NULL); + ++ TEST_ASSERT_VAL("find other", ++ expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", NULL, ++ &other, &num_other, 3) == 0); ++ TEST_ASSERT_VAL("find other", num_other == 2); ++ TEST_ASSERT_VAL("find other", !strcmp(other[0], "EVENT1,param=3/")); ++ TEST_ASSERT_VAL("find other", !strcmp(other[1], "EVENT2,param=3/")); ++ TEST_ASSERT_VAL("find other", other[2] == NULL); ++ + for (i = 0; i < num_other; i++) + free((void *)other[i]); + free((void *)other); +-- +2.27.0 + diff --git a/patches/0181-perf-jevents-Add-some-test-events.patch b/patches/0181-perf-jevents-Add-some-test-events.patch new file mode 100644 index 0000000..0119c28 --- /dev/null +++ b/patches/0181-perf-jevents-Add-some-test-events.patch @@ -0,0 +1,122 @@ +From f4a40e041840155d7afdda97249fdcf394814905 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:13 +0800 +Subject: [PATCH 064/201] perf jevents: Add some test events + +mainline inclusion +from mainline-v5.7-rc1 +commit c52db67a74b3a9b834af4588489cfea22ec280a3 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c52db67a74b3a9b834af4588489cfea22ec280a3 + +---------------------------------------------------------------------- + +Add some test PMU events. The events are randomly chosen from x86 and +arm64 JSONs. The events include CPU and uncore events. + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../pmu-events/arch/test/test_cpu/branch.json | 12 +++++++++ + .../pmu-events/arch/test/test_cpu/other.json | 26 +++++++++++++++++++ + .../pmu-events/arch/test/test_cpu/uncore.json | 21 +++++++++++++++ + 3 files changed, 59 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/branch.json + create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/other.json + create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/uncore.json + +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/branch.json b/tools/perf/pmu-events/arch/test/test_cpu/branch.json +new file mode 100644 +index 000000000000..93ddfd8053ca +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/test_cpu/branch.json +@@ -0,0 +1,12 @@ ++[ ++ { ++ "EventName": "bp_l1_btb_correct", ++ "EventCode": "0x8a", ++ "BriefDescription": "L1 BTB Correction." ++ }, ++ { ++ "EventName": "bp_l2_btb_correct", ++ "EventCode": "0x8b", ++ "BriefDescription": "L2 BTB Correction." ++ } ++] +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/other.json b/tools/perf/pmu-events/arch/test/test_cpu/other.json +new file mode 100644 +index 000000000000..7d53d7ecd723 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/test_cpu/other.json +@@ -0,0 +1,26 @@ ++[ ++ { ++ "EventCode": "0x6", ++ "Counter": "0,1", ++ "UMask": "0x80", ++ "EventName": "SEGMENT_REG_LOADS.ANY", ++ "SampleAfterValue": "200000", ++ "BriefDescription": "Number of segment register loads." ++ }, ++ { ++ "EventCode": "0x9", ++ "Counter": "0,1", ++ "UMask": "0x20", ++ "EventName": "DISPATCH_BLOCKED.ANY", ++ "SampleAfterValue": "200000", ++ "BriefDescription": "Memory cluster signals to block micro-op dispatch for any reason" ++ }, ++ { ++ "EventCode": "0x3A", ++ "Counter": "0,1", ++ "UMask": "0x0", ++ "EventName": "EIST_TRANS", ++ "SampleAfterValue": "200000", ++ "BriefDescription": "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions" ++ } ++] +\ No newline at end of file +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_cpu/uncore.json +new file mode 100644 +index 000000000000..d0a890cc814d +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/test_cpu/uncore.json +@@ -0,0 +1,21 @@ ++[ ++ { ++ "EventCode": "0x02", ++ "EventName": "uncore_hisi_ddrc.flux_wcmd", ++ "BriefDescription": "DDRC write commands", ++ "PublicDescription": "DDRC write commands", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "Unit": "CBO", ++ "EventCode": "0x22", ++ "UMask": "0x81", ++ "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION", ++ "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.", ++ "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.", ++ "Counter": "0,1", ++ "CounterMask": "0", ++ "Invert": "0", ++ "EdgeDetect": "0" ++ } ++] +-- +2.27.0 + diff --git a/patches/0182-perf-jevents-Support-test-events-folder.patch b/patches/0182-perf-jevents-Support-test-events-folder.patch new file mode 100644 index 0000000..ec41cfd --- /dev/null +++ b/patches/0182-perf-jevents-Support-test-events-folder.patch @@ -0,0 +1,169 @@ +From 37a0ab8d2dd9fc5edd3091d2c5843dd327875398 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:14 +0800 +Subject: [PATCH 065/201] perf jevents: Support test events folder + +mainline inclusion +from mainline-v5.7-rc1 +commit d84478088780acdecfcf50a0e52b71cc4ab7c520 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d84478088780acdecfcf50a0e52b71cc4ab7c520 + +---------------------------------------------------------------------- + +With the goal of supporting pmu-events test case, introduce support for +a test events folder. + +These test events can be used for testing generation of pmu-event tables +and alias creation for any arch. + +When running the pmu-events test case, these test events will be used as +the platform-agnostic events, so aliases can be created per-PMU and +validated against known expected values. + +To support the test events, add a "testcpu" entry in pmu_events_map[]. +The pmu-events test will be able to lookup the events map for "testcpu", +to verify the generated tables against expected values. + +The resultant generated pmu-events.c will now look like the following: + + struct pmu_event pme_ampere_emag[] = { + { + .name = "ldrex_spec", + .event = "event=0x6c", + .desc = "Exclusive operation spe...", + .topic = "intrinsic", + .long_desc = "Exclusive operation ...", + }, + ... + }; + + struct pmu_event pme_test_cpu[] = { + { + .name = "uncore_hisi_ddrc.flux_wcmd", + .event = "event=0x2", + .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ", + .topic = "uncore", + .long_desc = "DDRC write commands", + .pmu = "hisi_sccl,ddrc", + }, + { + .name = "unc_cbo_xsnp_response.miss_eviction", + .event = "umask=0x81,event=0x22", + .desc = "Unit: uncore_cbox A cross-core snoop resulted ...", + .topic = "uncore", + .long_desc = "A cross-core snoop resulted from L3 ...", + .pmu = "uncore_cbox", + }, + { + .name = "eist_trans", + .event = "umask=0x0,period=200000,event=0x3a", + .desc = "Number of Enhanced Intel SpeedStep(R) ...", + .topic = "other", + }, + { + .name = 0, + }, + }; + + struct pmu_events_map pmu_events_map[] = { + ... + { + .cpuid = "0x00000000500f0000", + .version = "v1", + .type = "core", + .table = pme_ampere_emag + }, + ... + { + .cpuid = "testcpu", + .version = "v1", + .type = "core", + .table = pme_test_cpu, + }, + { + .cpuid = 0, + .version = 0, + .type = 0, + .table = 0, + }, + }; + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 6bf2237fef2d..1f7d4c53631d 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -772,6 +772,19 @@ static void print_mapping_table_suffix(FILE *outfp) + fprintf(outfp, "};\n"); + } + ++static void print_mapping_test_table(FILE *outfp) ++{ ++ /* ++ * Print the terminating, NULL entry. ++ */ ++ fprintf(outfp, "{\n"); ++ fprintf(outfp, "\t.cpuid = \"testcpu\",\n"); ++ fprintf(outfp, "\t.version = \"v1\",\n"); ++ fprintf(outfp, "\t.type = \"core\",\n"); ++ fprintf(outfp, "\t.table = pme_test_cpu,\n"); ++ fprintf(outfp, "},\n"); ++} ++ + static int process_mapfile(FILE *outfp, char *fpath) + { + int n = 16384; +@@ -849,6 +862,7 @@ static int process_mapfile(FILE *outfp, char *fpath) + } + + out: ++ print_mapping_test_table(outfp); + print_mapping_table_suffix(outfp); + fclose(mapfp); + free(line); +@@ -1169,6 +1183,22 @@ int main(int argc, char *argv[]) + goto empty_map; + } + ++ sprintf(ldirname, "%s/test", start_dirname); ++ ++ rc = nftw(ldirname, process_one_file, maxfds, 0); ++ if (rc && verbose) { ++ pr_info("%s: Error walking file tree %s rc=%d for test\n", ++ prog, ldirname, rc); ++ goto empty_map; ++ } else if (rc < 0) { ++ /* Make build fail */ ++ free_arch_std_events(); ++ ret = 1; ++ goto out_free_mapfile; ++ } else if (rc) { ++ goto empty_map; ++ } ++ + if (close_table) + print_events_table_suffix(eventsfp); + +-- +2.27.0 + diff --git a/patches/0183-perf-pmu-Refactor-pmu_add_cpu_aliases.patch b/patches/0183-perf-pmu-Refactor-pmu_add_cpu_aliases.patch new file mode 100644 index 0000000..0a5dcd9 --- /dev/null +++ b/patches/0183-perf-pmu-Refactor-pmu_add_cpu_aliases.patch @@ -0,0 +1,114 @@ +From 11fb15685ec24cd84117e1c2a961838614bfff2a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:15 +0800 +Subject: [PATCH 066/201] perf pmu: Refactor pmu_add_cpu_aliases() + +mainline inclusion +from mainline-v5.7-rc1 +commit e45ad701e784e0eed8a07b537b47afb302c59dab +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e45ad701e784e0eed8a07b537b47afb302c59dab + +---------------------------------------------------------------------- + +Create pmu_add_cpu_aliases_map() from pmu_add_cpu_aliases(), so the caller +can pass the map; the pmu-events test would use this since there would +be no CPUID matching to a mapfile there. + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/pmu.c +--- + tools/perf/util/pmu.c | 21 +++++++++++++-------- + tools/perf/util/pmu.h | 3 +++ + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 2d06db85c135..7053b0c5cdae 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -18,7 +18,6 @@ + #include "parse-events.h" + #include "cpumap.h" + #include "header.h" +-#include "pmu-events/pmu-events.h" + #include "cache.h" + #include "string2.h" + +@@ -791,16 +790,11 @@ static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + * to the current running CPU. Then, add all PMU events from that table + * as aliases. + */ +-static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) ++void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, ++ struct pmu_events_map *map) + { + int i; +- struct pmu_events_map *map; + const char *name = pmu->name; +- +- map = perf_pmu__find_map(pmu); +- if (!map) +- return; +- + /* + * Found a matching PMU events table. Create aliases + */ +@@ -835,6 +829,17 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) + } + } + ++static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) ++{ ++ struct pmu_events_map *map; ++ ++ map = perf_pmu__find_map(pmu); ++ if (!map) ++ return; ++ ++ pmu_add_cpu_aliases_map(head, pmu, map); ++} ++ + struct perf_event_attr * __weak + perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) + { +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index a7f1d60c288b..acb6f0ebae08 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -8,6 +8,7 @@ + #include + #include "evsel.h" + #include "parse-events.h" ++#include "pmu-events/pmu-events.h" + + enum { + PERF_PMU_FORMAT_VALUE_CONFIG, +@@ -93,6 +94,8 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, + int perf_pmu__test(void); + + struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); ++void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, ++ struct pmu_events_map *map); + + struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); + +-- +2.27.0 + diff --git a/patches/0184-perf-test-Add-pmu-events-test.patch b/patches/0184-perf-test-Add-pmu-events-test.patch new file mode 100644 index 0000000..7a96eac --- /dev/null +++ b/patches/0184-perf-test-Add-pmu-events-test.patch @@ -0,0 +1,343 @@ +From 7f689e44b98883f5a5a8609cf2d179cb9e03addb Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:16 +0800 +Subject: [PATCH 067/201] perf test: Add pmu-events test + +mainline inclusion +from mainline-v5.7-rc1 +commit a6c925fd3aa2aba043a73b0ad57ffd296e1c42c9 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a6c925fd3aa2aba043a73b0ad57ffd296e1c42c9 + +---------------------------------------------------------------------- + +The initial test will verify that the test tables in generated pmu-events.c +match against known, expected values. + +For known events added in pmu-events/arch/test, we need to add an entry +in test_cpu_aliases_events[] or test_uncore_events[]. + +A sample run is as follows for x86: + + john@linux-3c19:~/linux> tools/perf/perf test -vv 10 + 10: PMU event aliases : + --- start --- + test child forked, pid 5316 + testing event table bp_l1_btb_correct: pass + testing event table bp_l2_btb_correct: pass + testing event table segment_reg_loads.any: pass + testing event table dispatch_blocked.any: pass + testing event table eist_trans: pass + testing event table uncore_hisi_ddrc.flux_wcmd: pass + testing event table unc_cbo_xsnp_response.miss_eviction: pass + test child finished with 0 + ---- end ---- + PMU event aliases: Ok + +Signed-off-by: John Garry +Tested-by: Arnaldo Carvalho de Melo +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +[ Fixup test_cpu_events[] and test_uncore_events[] sentinels to initialize one of its members to NULL, fixing the build in older compilers ] +Link: http://lore.kernel.org/lkml/1584442939-8911-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/Build | 1 + + tools/perf/tests/builtin-test.c | 4 + + tools/perf/tests/pmu-events.c | 233 ++++++++++++++++++++++++++++++++ + tools/perf/tests/tests.h | 1 + + 4 files changed, 239 insertions(+) + create mode 100644 tools/perf/tests/pmu-events.c + +diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build +index e8fc36ed0979..d28758661fb7 100644 +--- a/tools/perf/tests/Build ++++ b/tools/perf/tests/Build +@@ -12,6 +12,7 @@ perf-y += evsel-roundtrip-name.o + perf-y += evsel-tp-sched.o + perf-y += fdarray.o + perf-y += pmu.o ++perf-y += pmu-events.o + perf-y += hists_common.o + perf-y += hists_link.o + perf-y += hists_filter.o +diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c +index c71d19185ab3..729b6235ae43 100644 +--- a/tools/perf/tests/builtin-test.c ++++ b/tools/perf/tests/builtin-test.c +@@ -69,6 +69,10 @@ static struct test generic_tests[] = { + .desc = "Parse perf pmu format", + .func = test__pmu, + }, ++ { ++ .desc = "PMU events", ++ .func = test__pmu_events, ++ }, + { + .desc = "DSO data read", + .func = test__dso_data, +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +new file mode 100644 +index 000000000000..12fc29746a09 +--- /dev/null ++++ b/tools/perf/tests/pmu-events.c +@@ -0,0 +1,233 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include "parse-events.h" ++#include "pmu.h" ++#include "tests.h" ++#include ++#include ++#include ++ ++#include "debug.h" ++#include "../pmu-events/pmu-events.h" ++ ++struct perf_pmu_test_event { ++ struct pmu_event event; ++}; ++static struct perf_pmu_test_event test_cpu_events[] = { ++ { ++ .event = { ++ .name = "bp_l1_btb_correct", ++ .event = "event=0x8a", ++ .desc = "L1 BTB Correction", ++ .topic = "branch", ++ }, ++ }, ++ { ++ .event = { ++ .name = "bp_l2_btb_correct", ++ .event = "event=0x8b", ++ .desc = "L2 BTB Correction", ++ .topic = "branch", ++ }, ++ }, ++ { ++ .event = { ++ .name = "segment_reg_loads.any", ++ .event = "umask=0x80,period=200000,event=0x6", ++ .desc = "Number of segment register loads", ++ .topic = "other", ++ }, ++ }, ++ { ++ .event = { ++ .name = "dispatch_blocked.any", ++ .event = "umask=0x20,period=200000,event=0x9", ++ .desc = "Memory cluster signals to block micro-op dispatch for any reason", ++ .topic = "other", ++ }, ++ }, ++ { ++ .event = { ++ .name = "eist_trans", ++ .event = "umask=0x0,period=200000,event=0x3a", ++ .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", ++ .topic = "other", ++ }, ++ }, ++ { /* sentinel */ ++ .event = { ++ .name = NULL, ++ }, ++ }, ++}; ++ ++static struct perf_pmu_test_event test_uncore_events[] = { ++ { ++ .event = { ++ .name = "uncore_hisi_ddrc.flux_wcmd", ++ .event = "event=0x2", ++ .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ", ++ .topic = "uncore", ++ .long_desc = "DDRC write commands", ++ .pmu = "hisi_sccl,ddrc", ++ }, ++ }, ++ { ++ .event = { ++ .name = "unc_cbo_xsnp_response.miss_eviction", ++ .event = "umask=0x81,event=0x22", ++ .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .topic = "uncore", ++ .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .pmu = "uncore_cbox", ++ }, ++ }, ++ { /* sentinel */ ++ .event = { ++ .name = NULL, ++ }, ++ } ++}; ++ ++const int total_test_events_size = ARRAY_SIZE(test_uncore_events); ++ ++static bool is_same(const char *reference, const char *test) ++{ ++ if (!reference && !test) ++ return true; ++ ++ if (reference && !test) ++ return false; ++ ++ if (!reference && test) ++ return false; ++ ++ return !strcmp(reference, test); ++} ++ ++static struct pmu_events_map *__test_pmu_get_events_map(void) ++{ ++ struct pmu_events_map *map; ++ ++ for (map = &pmu_events_map[0]; map->cpuid; map++) { ++ if (!strcmp(map->cpuid, "testcpu")) ++ return map; ++ } ++ ++ pr_err("could not find test events map\n"); ++ ++ return NULL; ++} ++ ++/* Verify generated events from pmu-events.c is as expected */ ++static int __test_pmu_event_table(void) ++{ ++ struct pmu_events_map *map = __test_pmu_get_events_map(); ++ struct pmu_event *table; ++ int map_events = 0, expected_events; ++ ++ /* ignore 2x sentinels */ ++ expected_events = ARRAY_SIZE(test_cpu_events) + ++ ARRAY_SIZE(test_uncore_events) - 2; ++ ++ if (!map) ++ return -1; ++ ++ for (table = map->table; table->name; table++) { ++ struct perf_pmu_test_event *test; ++ struct pmu_event *te; ++ bool found = false; ++ ++ if (table->pmu) ++ test = &test_uncore_events[0]; ++ else ++ test = &test_cpu_events[0]; ++ ++ te = &test->event; ++ ++ for (; te->name; test++, te = &test->event) { ++ if (strcmp(table->name, te->name)) ++ continue; ++ found = true; ++ map_events++; ++ ++ if (!is_same(table->desc, te->desc)) { ++ pr_debug2("testing event table %s: mismatched desc, %s vs %s\n", ++ table->name, table->desc, te->desc); ++ return -1; ++ } ++ ++ if (!is_same(table->topic, te->topic)) { ++ pr_debug2("testing event table %s: mismatched topic, %s vs %s\n", ++ table->name, table->topic, ++ te->topic); ++ return -1; ++ } ++ ++ if (!is_same(table->long_desc, te->long_desc)) { ++ pr_debug2("testing event table %s: mismatched long_desc, %s vs %s\n", ++ table->name, table->long_desc, ++ te->long_desc); ++ return -1; ++ } ++ ++ if (!is_same(table->unit, te->unit)) { ++ pr_debug2("testing event table %s: mismatched unit, %s vs %s\n", ++ table->name, table->unit, ++ te->unit); ++ return -1; ++ } ++ ++ if (!is_same(table->perpkg, te->perpkg)) { ++ pr_debug2("testing event table %s: mismatched perpkg, %s vs %s\n", ++ table->name, table->perpkg, ++ te->perpkg); ++ return -1; ++ } ++ ++ if (!is_same(table->metric_expr, te->metric_expr)) { ++ pr_debug2("testing event table %s: mismatched metric_expr, %s vs %s\n", ++ table->name, table->metric_expr, ++ te->metric_expr); ++ return -1; ++ } ++ ++ if (!is_same(table->metric_name, te->metric_name)) { ++ pr_debug2("testing event table %s: mismatched metric_name, %s vs %s\n", ++ table->name, table->metric_name, ++ te->metric_name); ++ return -1; ++ } ++ ++ if (!is_same(table->deprecated, te->deprecated)) { ++ pr_debug2("testing event table %s: mismatched deprecated, %s vs %s\n", ++ table->name, table->deprecated, ++ te->deprecated); ++ return -1; ++ } ++ ++ pr_debug("testing event table %s: pass\n", table->name); ++ } ++ ++ if (!found) { ++ pr_err("testing event table: could not find event %s\n", ++ table->name); ++ return -1; ++ } ++ } ++ ++ if (map_events != expected_events) { ++ pr_err("testing event table: found %d, but expected %d\n", ++ map_events, expected_events); ++ return -1; ++ } ++ ++ return 0; ++} ++int test__pmu_events(struct test *test __maybe_unused, ++ int subtest __maybe_unused) ++{ ++ if (__test_pmu_event_table()) ++ return -1; ++ ++ return 0; ++} +diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h +index 591621b4d564..7c01a7812d21 100644 +--- a/tools/perf/tests/tests.h ++++ b/tools/perf/tests/tests.h +@@ -49,6 +49,7 @@ int test__perf_evsel__roundtrip_name_test(struct test *test, int subtest); + int test__perf_evsel__tp_sched_test(struct test *test, int subtest); + int test__syscall_openat_tp_fields(struct test *test, int subtest); + int test__pmu(struct test *test, int subtest); ++int test__pmu_events(struct test *test, int subtest); + int test__attr(struct test *test, int subtest); + int test__dso_data(struct test *test, int subtest); + int test__dso_data_cache(struct test *test, int subtest); +-- +2.27.0 + diff --git a/patches/0185-perf-pmu-Add-is_pmu_core.patch b/patches/0185-perf-pmu-Add-is_pmu_core.patch new file mode 100644 index 0000000..55cfeae --- /dev/null +++ b/patches/0185-perf-pmu-Add-is_pmu_core.patch @@ -0,0 +1,67 @@ +From 020fdb75674fe4846546b65e819c92c2837fca86 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:17 +0800 +Subject: [PATCH 068/201] perf pmu: Add is_pmu_core() + +mainline inclusion +from mainline-v5.7-rc1 +commit d504fae93dd61b734aefc403c7653d958aef655a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d504fae93dd61b734aefc403c7653d958aef655a + +---------------------------------------------------------------------- + +Add a function to decide whether a PMU is a core PMU. + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-6-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 5 +++++ + tools/perf/util/pmu.h | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 7053b0c5cdae..5f91e68dca66 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -1417,6 +1417,11 @@ static void wordwrap(char *s, int start, int max, int corr) + } + } + ++bool is_pmu_core(const char *name) ++{ ++ return !strcmp(name, "cpu") || is_arm_pmu_core(name); ++} ++ + void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, + bool long_desc, bool details_flag, bool deprecated) + { +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index acb6f0ebae08..32db09d5b2b8 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -84,6 +84,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head); + + struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); + ++bool is_pmu_core(const char *name); + void print_pmu_events(const char *event_glob, bool name_only, bool quiet, + bool long_desc, bool details_flag, + bool deprecated); +-- +2.27.0 + diff --git a/patches/0186-perf-pmu-Make-pmu_uncore_alias_match-public.patch b/patches/0186-perf-pmu-Make-pmu_uncore_alias_match-public.patch new file mode 100644 index 0000000..45946c7 --- /dev/null +++ b/patches/0186-perf-pmu-Make-pmu_uncore_alias_match-public.patch @@ -0,0 +1,65 @@ +From c6e974eafd409282375fa753ac456c6235a27522 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:18 +0800 +Subject: [PATCH 069/201] perf pmu: Make pmu_uncore_alias_match() public + +mainline inclusion +from mainline-v5.7-rc1 +commit 5b9a50001b2c23f90f2a21db4763f3a9599588c4 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5b9a50001b2c23f90f2a21db4763f3a9599588c4 + +---------------------------------------------------------------------- + +The perf pmu-events test will want to use pmu_uncore_alias_match(), so +make it public. + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-7-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 2 +- + tools/perf/util/pmu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 5f91e68dca66..7eefbebbf990 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -745,7 +745,7 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) + return map; + } + +-static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) ++bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + { + char *tmp = NULL, *tok, *str; + bool res; +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 32db09d5b2b8..79f167db4a33 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -99,6 +99,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, + struct pmu_events_map *map); + + struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); ++bool pmu_uncore_alias_match(const char *pmu_name, const char *name); + + int perf_pmu__convert_scale(const char *scale, char **end, double *sval); + +-- +2.27.0 + diff --git a/patches/0187-perf-test-Test-pmu-events-aliases.patch b/patches/0187-perf-test-Test-pmu-events-aliases.patch new file mode 100644 index 0000000..26063e4 --- /dev/null +++ b/patches/0187-perf-test-Test-pmu-events-aliases.patch @@ -0,0 +1,313 @@ +From 3f1220d13738b5f0d899f47d76bf1fc18e25d860 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 17 Mar 2020 19:02:19 +0800 +Subject: [PATCH 070/201] perf test: Test pmu-events aliases + +mainline inclusion +from mainline-v5.7-rc1 +commit 956a78356c24c1ac3becf854135dc065b6b74265 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=956a78356c24c1ac3becf854135dc065b6b74265 + +---------------------------------------------------------------------- + +Add creating event aliases to the pmu-events test. + +So currently we verify that the generated pmu-events.c is as expected for +some test events. Now test that we generate aliases as expected for those +events during normal operation. + +For that, we cycle through each HW PMU in the system, and use the test +events to create aliases, and verify those against known, expected values. + +For core PMUs, we should create an alias for every event in +test_cpu_events[]. + +However, for uncore PMUs, they need to be matched by the pmu_event.pmu +member, so use test_uncore_events[]; so check the match beforehand with +pmu_uncore_alias_match(). + +A sample run is as follows for my x86 machine: + + john@linux-3c19:~/linux> tools/perf/perf test -vv 10 + 10: PMU events : + --- start --- + + ... + + testing PMU uncore_arb aliases: no events to match + testing PMU cstate_pkg aliases: no events to match + skipping testing PMU breakpoint + testing aliases PMU uncore_cbox_1: matched event unc_cbo_xsnp_response.miss_eviction + testing PMU uncore_cbox_1 aliases: pass + testing PMU power aliases: no events to match + testing aliases PMU cpu: matched event bp_l1_btb_correct + testing aliases PMU cpu: matched event bp_l2_btb_correct + testing aliases PMU cpu: matched event segment_reg_loads.any + testing aliases PMU cpu: matched event dispatch_blocked.any + testing aliases PMU cpu: matched event eist_trans + testing PMU cpu aliases: pass + testing PMU intel_pt aliases: no events to match + skipping testing PMU software + skipping testing PMU intel_bts + testing PMU uncore_imc aliases: no events to match + testing aliases PMU uncore_cbox_0: matched event unc_cbo_xsnp_response.miss_eviction + testing PMU uncore_cbox_0 aliases: pass + testing PMU cstate_core aliases: no events to match + skipping testing PMU tracepoint + testing PMU msr aliases: no events to match + test child finished with 0 + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: James Clark +Cc: Joakim Zhang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1584442939-8911-8-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/pmu-events.c +--- + tools/perf/tests/pmu-events.c | 148 +++++++++++++++++++++++++++++++++- + 1 file changed, 147 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 12fc29746a09..c1f5aeec3a41 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -5,13 +5,24 @@ + #include + #include + #include +- ++#include "util.h" + #include "debug.h" + #include "../pmu-events/pmu-events.h" + + struct perf_pmu_test_event { + struct pmu_event event; ++ ++ /* extra events for aliases */ ++ const char *alias_str; ++ ++ /* ++ * Note: For when PublicDescription does not exist in the JSON, we ++ * will have no long_desc in pmu_event.long_desc, but long_desc may ++ * be set in the alias. ++ */ ++ const char *alias_long_desc; + }; ++ + static struct perf_pmu_test_event test_cpu_events[] = { + { + .event = { +@@ -20,6 +31,8 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .desc = "L1 BTB Correction", + .topic = "branch", + }, ++ .alias_str = "event=0x8a", ++ .alias_long_desc = "L1 BTB Correction", + }, + { + .event = { +@@ -28,6 +41,8 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .desc = "L2 BTB Correction", + .topic = "branch", + }, ++ .alias_str = "event=0x8b", ++ .alias_long_desc = "L2 BTB Correction", + }, + { + .event = { +@@ -36,6 +51,8 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .desc = "Number of segment register loads", + .topic = "other", + }, ++ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6", ++ .alias_long_desc = "Number of segment register loads", + }, + { + .event = { +@@ -44,6 +61,8 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .desc = "Memory cluster signals to block micro-op dispatch for any reason", + .topic = "other", + }, ++ .alias_str = "umask=0x20,(null)=0x30d40,event=0x9", ++ .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason", + }, + { + .event = { +@@ -52,6 +71,8 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", + .topic = "other", + }, ++ .alias_str = "umask=0,(null)=0x30d40,event=0x3a", ++ .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", + }, + { /* sentinel */ + .event = { +@@ -70,6 +91,8 @@ static struct perf_pmu_test_event test_uncore_events[] = { + .long_desc = "DDRC write commands", + .pmu = "hisi_sccl,ddrc", + }, ++ .alias_str = "event=0x2", ++ .alias_long_desc = "DDRC write commands", + }, + { + .event = { +@@ -80,6 +103,8 @@ static struct perf_pmu_test_event test_uncore_events[] = { + .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", + .pmu = "uncore_cbox", + }, ++ .alias_str = "umask=0x81,event=0x22", ++ .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", + }, + { /* sentinel */ + .event = { +@@ -223,11 +248,132 @@ static int __test_pmu_event_table(void) + + return 0; + } ++ ++static struct perf_pmu_alias *find_alias(const char *test_event, struct list_head *aliases) ++{ ++ struct perf_pmu_alias *alias; ++ ++ list_for_each_entry(alias, aliases, list) ++ if (!strcmp(test_event, alias->name)) ++ return alias; ++ ++ return NULL; ++} ++ ++/* Verify aliases are as expected */ ++static int __test__pmu_event_aliases(char *pmu_name, int *count) ++{ ++ struct perf_pmu_test_event *test; ++ struct pmu_event *te; ++ struct perf_pmu *pmu; ++ LIST_HEAD(aliases); ++ int res = 0; ++ bool use_uncore_table; ++ struct pmu_events_map *map = __test_pmu_get_events_map(); ++ ++ if (!map) ++ return -1; ++ ++ if (is_pmu_core(pmu_name)) { ++ test = &test_cpu_events[0]; ++ use_uncore_table = false; ++ } else { ++ test = &test_uncore_events[0]; ++ use_uncore_table = true; ++ } ++ ++ pmu = zalloc(sizeof(*pmu)); ++ if (!pmu) ++ return -1; ++ ++ pmu->name = pmu_name; ++ ++ pmu_add_cpu_aliases_map(&aliases, pmu, map); ++ ++ for (te = &test->event; te->name; test++, te = &test->event) { ++ struct perf_pmu_alias *alias = find_alias(te->name, &aliases); ++ ++ if (!alias) { ++ bool uncore_match = pmu_uncore_alias_match(pmu_name, ++ te->pmu); ++ ++ if (use_uncore_table && !uncore_match) { ++ pr_debug3("testing aliases PMU %s: skip matching alias %s\n", ++ pmu_name, te->name); ++ continue; ++ } ++ ++ pr_debug2("testing aliases PMU %s: no alias, alias_table->name=%s\n", ++ pmu_name, te->name); ++ res = -1; ++ break; ++ } ++ ++ if (!is_same(alias->desc, te->desc)) { ++ pr_debug2("testing aliases PMU %s: mismatched desc, %s vs %s\n", ++ pmu_name, alias->desc, te->desc); ++ res = -1; ++ break; ++ } ++ ++ if (!is_same(alias->long_desc, test->alias_long_desc)) { ++ pr_debug2("testing aliases PMU %s: mismatched long_desc, %s vs %s\n", ++ pmu_name, alias->long_desc, ++ test->alias_long_desc); ++ res = -1; ++ break; ++ } ++ ++ if (!is_same(alias->str, test->alias_str)) { ++ pr_debug2("testing aliases PMU %s: mismatched str, %s vs %s\n", ++ pmu_name, alias->str, test->alias_str); ++ res = -1; ++ break; ++ } ++ ++ if (!is_same(alias->topic, te->topic)) { ++ pr_debug2("testing aliases PMU %s: mismatched topic, %s vs %s\n", ++ pmu_name, alias->topic, te->topic); ++ res = -1; ++ break; ++ } ++ ++ (*count)++; ++ pr_debug2("testing aliases PMU %s: matched event %s\n", ++ pmu_name, alias->name); ++ } ++ ++ free(pmu); ++ return res; ++} ++ + int test__pmu_events(struct test *test __maybe_unused, + int subtest __maybe_unused) + { ++ struct perf_pmu *pmu = NULL; ++ + if (__test_pmu_event_table()) + return -1; + ++ while ((pmu = perf_pmu__scan(pmu)) != NULL) { ++ int count = 0; ++ ++ if (list_empty(&pmu->format)) { ++ pr_debug2("skipping testing PMU %s\n", pmu->name); ++ continue; ++ } ++ ++ if (__test__pmu_event_aliases(pmu->name, &count)) { ++ pr_debug("testing PMU %s aliases: failed\n", pmu->name); ++ return -1; ++ } ++ ++ if (count == 0) ++ pr_debug3("testing PMU %s aliases: no events to match\n", ++ pmu->name); ++ else ++ pr_debug("testing PMU %s aliases: pass\n", pmu->name); ++ } ++ + return 0; + } +-- +2.27.0 + diff --git a/patches/0188-perf-expr-Allow-for-unlimited-escaped-characters-in-.patch b/patches/0188-perf-expr-Allow-for-unlimited-escaped-characters-in-.patch new file mode 100644 index 0000000..bddd484 --- /dev/null +++ b/patches/0188-perf-expr-Allow-for-unlimited-escaped-characters-in-.patch @@ -0,0 +1,61 @@ +From 305bfee3d03a50055518a3831a790798fee0bd7f Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 1 May 2020 10:33:22 -0700 +Subject: [PATCH 071/201] perf expr: Allow for unlimited escaped characters in + a symbol + +mainline inclusion +from mainline-v5.8-rc1 +commit 5b3141d02645a36ccf9f08a67e08e8186dfef12c +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5b3141d02645a36ccf9f08a67e08e8186dfef12c + +---------------------------------------------------------------------- + +Current expression allows 2 escaped '-,=' characters. However, some +metrics require more, for example Haswell DRAM_BW_Use. + +Fixes: 26226a97724d (perf expr: Move expr lexer to flex) +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Tested-by: Kajol Jain +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Haiyan Song +Cc: Jin Yao +Cc: John Garry +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Song Liu +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200501173333.227162-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.l | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index 74b9b59b1aa5..73db6a9ef97e 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -86,7 +86,7 @@ number [0-9]+ + sch [-,=] + spec \\{sch} + sym [0-9a-zA-Z_\.:@?]+ +-symbol {spec}*{sym}*{spec}*{sym}*{spec}*{sym} ++symbol ({spec}|{sym})+ + + %% + struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); +-- +2.27.0 + diff --git a/patches/0189-perf-expr-Allow-to-be-an-other-token.patch b/patches/0189-perf-expr-Allow-to-be-an-other-token.patch new file mode 100644 index 0000000..acf2ede --- /dev/null +++ b/patches/0189-perf-expr-Allow-to-be-an-other-token.patch @@ -0,0 +1,58 @@ +From 9126755cf32c45235b7a4154c830a9a1e6fa43a4 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 1 May 2020 10:33:25 -0700 +Subject: [PATCH 072/201] perf expr: Allow ',' to be an other token + +mainline inclusion +from mainline-v5.8-rc1 +commit cb59fa793e3c837ea6843dcec3bd6a0ea649f06b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cb59fa793e3c837ea6843dcec3bd6a0ea649f06b + +---------------------------------------------------------------------- + +Corrects parse errors in expr__find_other of expressions with min. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Haiyan Song +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Song Liu +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200501173333.227162-5-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.y | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 2764b196edc3..74c9195860c5 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -80,7 +80,7 @@ other: ID + ctx->ids[ctx->num_ids++].name = $1; + } + | +-MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' ++MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' + + + all_expr: if_expr { *final_val = $1; } +-- +2.27.0 + diff --git a/patches/0190-perf-expr-Increase-max-other.patch b/patches/0190-perf-expr-Increase-max-other.patch new file mode 100644 index 0000000..d216628 --- /dev/null +++ b/patches/0190-perf-expr-Increase-max-other.patch @@ -0,0 +1,59 @@ +From 0a1805781415cdde112ceebd08d6b5b1de887257 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 1 May 2020 10:33:26 -0700 +Subject: [PATCH 073/201] perf expr: Increase max other + +mainline inclusion +from mainline-v5.8-rc1 +commit f59d3f84a03c54bc394ba9727bf15818e4f86286 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f59d3f84a03c54bc394ba9727bf15818e4f86286 + +---------------------------------------------------------------------- + +Large metrics such as Branch_Misprediction_Cost_SMT on x86 broadwell +need more space. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Haiyan Song +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Song Liu +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200501173333.227162-6-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 87d627bb699b..40fc452b0f2b 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -2,7 +2,7 @@ + #ifndef PARSE_CTX_H + #define PARSE_CTX_H 1 + +-#define EXPR_MAX_OTHER 20 ++#define EXPR_MAX_OTHER 64 + #define MAX_PARSE_ID EXPR_MAX_OTHER + + struct expr_parse_id { +-- +2.27.0 + diff --git a/patches/0191-perf-expr-Parse-numbers-as-doubles.patch b/patches/0191-perf-expr-Parse-numbers-as-doubles.patch new file mode 100644 index 0000000..4331c25 --- /dev/null +++ b/patches/0191-perf-expr-Parse-numbers-as-doubles.patch @@ -0,0 +1,100 @@ +From aa1a1e03838793bba152e39f27bffbf05d03b143 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 1 May 2020 10:33:27 -0700 +Subject: [PATCH 074/201] perf expr: Parse numbers as doubles + +mainline inclusion +from mainline-v5.8-rc1 +commit 7db2fd0b211394be8b4c7caadc943d0d7ca86357 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7db2fd0b211394be8b4c7caadc943d0d7ca86357 + +---------------------------------------------------------------------- + +This is expected in expr.y and metrics use floating point values such as +x86 broadwell IFetch_Line_Utilization. + +Fixes: 26226a97724d (perf expr: Move expr lexer to flex) +Signed-off-by: Ian Rogers +Tested-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Haiyan Song +Cc: Jin Yao +Cc: John Garry +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Song Liu +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200501173333.227162-7-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.l | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index 73db6a9ef97e..ceab11bea6f9 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -10,12 +10,12 @@ + char *expr_get_text(yyscan_t yyscanner); + YYSTYPE *expr_get_lval(yyscan_t yyscanner); + +-static int __value(YYSTYPE *yylval, char *str, int base, int token) ++static double __value(YYSTYPE *yylval, char *str, int token) + { +- u64 num; ++ double num; + + errno = 0; +- num = strtoull(str, NULL, base); ++ num = strtod(str, NULL); + if (errno) + return EXPR_ERROR; + +@@ -23,12 +23,12 @@ static int __value(YYSTYPE *yylval, char *str, int base, int token) + return token; + } + +-static int value(yyscan_t scanner, int base) ++static int value(yyscan_t scanner) + { + YYSTYPE *yylval = expr_get_lval(scanner); + char *text = expr_get_text(scanner); + +- return __value(yylval, text, base, NUMBER); ++ return __value(yylval, text, NUMBER); + } + + /* +@@ -81,7 +81,7 @@ static int str(yyscan_t scanner, int token, int runtime) + } + %} + +-number [0-9]+ ++number [0-9]*\.?[0-9]+ + + sch [-,=] + spec \\{sch} +@@ -105,7 +105,7 @@ min { return MIN; } + if { return IF; } + else { return ELSE; } + #smt_on { return SMT_ON; } +-{number} { return value(yyscanner, 10); } ++{number} { return value(yyscanner); } + {symbol} { return str(yyscanner, ID, sctx->runtime); } + "|" { return '|'; } + "^" { return '^'; } +-- +2.27.0 + diff --git a/patches/0192-perf-test-Improve-pmu-event-metric-testing.patch b/patches/0192-perf-test-Improve-pmu-event-metric-testing.patch new file mode 100644 index 0000000..b976e71 --- /dev/null +++ b/patches/0192-perf-test-Improve-pmu-event-metric-testing.patch @@ -0,0 +1,311 @@ +From 44fb932a73686d9d773162e3a9c912b1caf4ce3c Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 13 May 2020 14:29:33 -0700 +Subject: [PATCH 075/201] perf test: Improve pmu event metric testing + +mainline inclusion +from mainline-v5.8-rc1 +commit 06392aaad592cadf4335617a2bb8e45722e3df33 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=06392aaad592cadf4335617a2bb8e45722e3df33 + +---------------------------------------------------------------------- + +Break pmu-events test into 2 and add a test to verify that all pmu +metric expressions simply parse. Try to parse all metric ids/events, +skip/warn if metrics for the current architecture fail to parse. To +support warning for a skip, and an ability for a subtest to describe why +it skips. + +Tested on power9, skylakex, haswell, broadwell, westmere, sandybridge and +ivybridge. + +May skip/warn on other architectures if metrics are invalid. In +particular s390 is untested, but its expressions are trivial. The +untested architectures with expressions are power8, cascadelakex, +tremontx, skylake, jaketown, ivytown and variants of haswell and +broadwell. + +v3. addresses review comments from John Garry , +Jiri Olsa and Arnaldo Carvalho de Melo +. +v2. changes the commit message as event parsing errors no longer cause +the test to fail. + +Committer notes: + +Check the return value of strtod() to fix the build in systems where +that function is declared with attribute warn_unused_result. + +Signed-off-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jin Yao +Cc: Jiri Olsa +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200513212933.41273-1-irogers@google.com +[ split from a larger patch ] +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/pmu-events.c +--- + tools/perf/tests/builtin-test.c | 7 ++ + tools/perf/tests/pmu-events.c | 170 ++++++++++++++++++++++++++++++-- + tools/perf/tests/tests.h | 3 + + 3 files changed, 174 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c +index 729b6235ae43..1925f170478c 100644 +--- a/tools/perf/tests/builtin-test.c ++++ b/tools/perf/tests/builtin-test.c +@@ -72,6 +72,13 @@ static struct test generic_tests[] = { + { + .desc = "PMU events", + .func = test__pmu_events, ++ .subtest = { ++ .skip_if_fail = false, ++ .get_nr = test__pmu_events_subtest_get_nr, ++ .get_desc = test__pmu_events_subtest_get_desc, ++ .skip_reason = test__pmu_events_subtest_skip_reason, ++ }, ++ + }, + { + .desc = "DSO data read", +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index c1f5aeec3a41..233806382300 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 ++#include "math.h" + #include "parse-events.h" + #include "pmu.h" + #include "tests.h" +@@ -8,6 +9,9 @@ + #include "util.h" + #include "debug.h" + #include "../pmu-events/pmu-events.h" ++#include "util/evlist.h" ++#include "util/expr.h" ++#include "util/parse-events.h" + + struct perf_pmu_test_event { + struct pmu_event event; +@@ -144,7 +148,7 @@ static struct pmu_events_map *__test_pmu_get_events_map(void) + } + + /* Verify generated events from pmu-events.c is as expected */ +-static int __test_pmu_event_table(void) ++static int test_pmu_event_table(void) + { + struct pmu_events_map *map = __test_pmu_get_events_map(); + struct pmu_event *table; +@@ -347,14 +351,11 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + return res; + } + +-int test__pmu_events(struct test *test __maybe_unused, +- int subtest __maybe_unused) ++ ++static int test_aliases(void) + { + struct perf_pmu *pmu = NULL; + +- if (__test_pmu_event_table()) +- return -1; +- + while ((pmu = perf_pmu__scan(pmu)) != NULL) { + int count = 0; + +@@ -377,3 +378,160 @@ int test__pmu_events(struct test *test __maybe_unused, + + return 0; + } ++ ++static bool is_number(const char *str) ++{ ++ char *end_ptr; ++ double v; ++ ++ errno = 0; ++ v = strtod(str, &end_ptr); ++ (void)v; // We're not interested in this value, only if it is valid ++ return errno == 0 && end_ptr != str; ++} ++ ++static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) ++{ ++ struct parse_events_error error; ++ struct perf_evlist *evlist; ++ int ret; ++ ++ /* Numbers are always valid. */ ++ if (is_number(id)) ++ return 0; ++ ++ evlist = perf_evlist__new(); ++ memset(&error, 0, sizeof(error)); ++ ret = parse_events(evlist, id, &error); ++ if (ret && same_cpu) { ++ pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", ++ pe->metric_name, id, pe->metric_expr); ++ pr_warning("Error string '%s' help '%s'\n", error.str, ++ error.help); ++ } else if (ret) { ++ pr_debug3("Parse event failed, but for an event that may not be supported by this CPU.\nid '%s' metric '%s' expr '%s'\n", ++ id, pe->metric_name, pe->metric_expr); ++ ret = 0; ++ } ++ perf_evlist__delete(evlist); ++ free(error.str); ++ free(error.help); ++ return ret; ++} ++ ++static void expr_failure(const char *msg, ++ const struct pmu_events_map *map, ++ const struct pmu_event *pe) ++{ ++ pr_debug("%s for map %s %s %s\n", ++ msg, map->cpuid, map->version, map->type); ++ pr_debug("On metric %s\n", pe->metric_name); ++ pr_debug("On expression %s\n", pe->metric_expr); ++} ++ ++static int test_parsing(void) ++{ ++ struct pmu_events_map *cpus_map = perf_pmu__find_map(NULL); ++ struct pmu_events_map *map; ++ struct pmu_event *pe; ++ int i, j, k; ++ const char **ids; ++ int idnum; ++ int ret = 0; ++ struct expr_parse_ctx ctx; ++ double result; ++ ++ i = 0; ++ for (;;) { ++ map = &pmu_events_map[i++]; ++ if (!map->table) ++ break; ++ j = 0; ++ for (;;) { ++ pe = &map->table[j++]; ++ if (!pe->name && !pe->metric_group && !pe->metric_name) ++ break; ++ if (!pe->metric_expr) ++ continue; ++ if (expr__find_other(pe->metric_expr, NULL, ++ &ids, &idnum, 0) < 0) { ++ expr_failure("Parse other failed", map, pe); ++ ret++; ++ continue; ++ } ++ expr__ctx_init(&ctx); ++ ++ /* ++ * Add all ids with a made up value. The value may ++ * trigger divide by zero when subtracted and so try to ++ * make them unique. ++ */ ++ for (k = 0; k < idnum; k++) ++ expr__add_id(&ctx, ids[k], k + 1); ++ ++ for (k = 0; k < idnum; k++) { ++ if (check_parse_id(ids[k], map == cpus_map, pe)) ++ ret++; ++ } ++ ++ if (expr__parse(&result, &ctx, pe->metric_expr, 0)) { ++ expr_failure("Parse failed", map, pe); ++ ret++; ++ } ++ for (k = 0; k < idnum; k++) ++ zfree(&ids[k]); ++ free(ids); ++ } ++ } ++ /* TODO: fail when not ok */ ++ return ret == 0 ? TEST_OK : TEST_SKIP; ++} ++ ++static const struct { ++ int (*func)(void); ++ const char *desc; ++} pmu_events_testcase_table[] = { ++ { ++ .func = test_pmu_event_table, ++ .desc = "PMU event table sanity", ++ }, ++ { ++ .func = test_aliases, ++ .desc = "PMU event map aliases", ++ }, ++ { ++ .func = test_parsing, ++ .desc = "Parsing of PMU event table metrics", ++ }, ++}; ++ ++const char *test__pmu_events_subtest_get_desc(int subtest) ++{ ++ if (subtest < 0 || ++ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table)) ++ return NULL; ++ return pmu_events_testcase_table[subtest].desc; ++} ++ ++const char *test__pmu_events_subtest_skip_reason(int subtest) ++{ ++ if (subtest < 0 || ++ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table)) ++ return NULL; ++ if (pmu_events_testcase_table[subtest].func != test_parsing) ++ return NULL; ++ return "some metrics failed"; ++} ++ ++int test__pmu_events_subtest_get_nr(void) ++{ ++ return (int)ARRAY_SIZE(pmu_events_testcase_table); ++} ++ ++int test__pmu_events(struct test *test __maybe_unused, int subtest) ++{ ++ if (subtest < 0 || ++ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table)) ++ return TEST_FAIL; ++ return pmu_events_testcase_table[subtest].func(); ++} +diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h +index 7c01a7812d21..7d2997c9fca7 100644 +--- a/tools/perf/tests/tests.h ++++ b/tools/perf/tests/tests.h +@@ -50,6 +50,9 @@ int test__perf_evsel__tp_sched_test(struct test *test, int subtest); + int test__syscall_openat_tp_fields(struct test *test, int subtest); + int test__pmu(struct test *test, int subtest); + int test__pmu_events(struct test *test, int subtest); ++const char *test__pmu_events_subtest_get_desc(int subtest); ++const char *test__pmu_events_subtest_skip_reason(int subtest); ++int test__pmu_events_subtest_get_nr(void); + int test__attr(struct test *test, int subtest); + int test__dso_data(struct test *test, int subtest); + int test__dso_data_cache(struct test *test, int subtest); +-- +2.27.0 + diff --git a/patches/0193-perf-test-Provide-a-subtest-callback-to-ask-for-the-.patch b/patches/0193-perf-test-Provide-a-subtest-callback-to-ask-for-the-.patch new file mode 100644 index 0000000..fb1f480 --- /dev/null +++ b/patches/0193-perf-test-Provide-a-subtest-callback-to-ask-for-the-.patch @@ -0,0 +1,80 @@ +From 2fcba35dbd7a5173a3e38190b5fb8e659d6ed091 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 13 May 2020 14:29:33 -0700 +Subject: [PATCH 076/201] perf test: Provide a subtest callback to ask for the + reason for skipping a subtest + +mainline inclusion +from mainline-v5.8-rc1 +commit 3b536651eeb7667808de7651f0858c932a3c4138 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3b536651eeb7667808de7651f0858c932a3c4138 + +---------------------------------------------------------------------- + +Now subtests can inform why a test was skipped. The upcoming patch +improvint PMU event metric testing will use it. + +Signed-off-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jin Yao +Cc: Jiri Olsa +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200513212933.41273-1-irogers@google.com +[ split from a larger patch ] +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/builtin-test.c | 11 +++++++++-- + tools/perf/tests/tests.h | 1 + + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c +index 1925f170478c..b4b1e34aaef4 100644 +--- a/tools/perf/tests/builtin-test.c ++++ b/tools/perf/tests/builtin-test.c +@@ -406,8 +406,15 @@ static int test_and_print(struct test *t, bool force_skip, int subtest) + case TEST_OK: + pr_info(" Ok\n"); + break; +- case TEST_SKIP: +- color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); ++ case TEST_SKIP: { ++ const char *skip_reason = NULL; ++ if (t->subtest.skip_reason) ++ skip_reason = t->subtest.skip_reason(subtest); ++ if (skip_reason) ++ color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", skip_reason); ++ else ++ color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); ++ } + break; + case TEST_FAIL: + default: +diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h +index 7d2997c9fca7..897ca3e7812c 100644 +--- a/tools/perf/tests/tests.h ++++ b/tools/perf/tests/tests.h +@@ -34,6 +34,7 @@ struct test { + bool skip_if_fail; + int (*get_nr)(void); + const char *(*get_desc)(int subtest); ++ const char *(*skip_reason)(int subtest); + } subtest; + bool (*is_supported)(void); + void *priv; +-- +2.27.0 + diff --git a/patches/0194-perf-expr-Migrate-expr-ids-table-to-a-hashmap.patch b/patches/0194-perf-expr-Migrate-expr-ids-table-to-a-hashmap.patch new file mode 100644 index 0000000..64644e3 --- /dev/null +++ b/patches/0194-perf-expr-Migrate-expr-ids-table-to-a-hashmap.patch @@ -0,0 +1,825 @@ +From 8282a38ff6fc730bed66c3ce0f5db1be05813f6d Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Fri, 15 May 2020 15:17:32 -0700 +Subject: [PATCH 077/201] perf expr: Migrate expr ids table to a hashmap + +mainline inclusion +from mainline-v5.8-rc1 +commit ded80bda8bc9bb65a344b79b36d5acf45a907b25 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ded80bda8bc9bb65a344b79b36d5acf45a907b25 + +---------------------------------------------------------------------- + +Use a hashmap between a char* string and a double* value. While bpf's +hashmap entries are size_t in size, we can't guarantee sizeof(size_t) >= +sizeof(double). Avoid a memory allocation when gathering ids by making +0.0 a special value encoded as NULL. + +Original map suggestion by Andi Kleen: + + https://lore.kernel.org/lkml/20200224210308.GQ160988@tassilo.jf.intel.com/ + +and seconded by Jiri Olsa: + + https://lore.kernel.org/lkml/20200423112915.GH1136647@krava/ + +Committer notes: + +There are fixes that need to land upstream before we can use libbpf's +headers, for now use our copy unconditionally, since the data structures +at this point are exactly the same, no problem. + +When the fixes for libbpf's hashmap land upstream, we can fix this up. + +Testing it: + +Building with LIBBPF=1, i.e. the default: + + $ perf -vv | grep -i bpf + bpf: [ on ] # HAVE_LIBBPF_SUPPORT + $ nm ~/bin/perf | grep -i libbpf_ | wc -l + 39 + $ nm ~/bin/perf | grep -i hashmap_ | wc -l + 17 + $ + +Explicitely building without LIBBPF: + + $ perf -vv | grep -i bpf + bpf: [ OFF ] # HAVE_LIBBPF_SUPPORT + $ + $ nm ~/bin/perf | grep -i libbpf_ | wc -l + 0 + $ nm ~/bin/perf | grep -i hashmap_ | wc -l + 9 + $ + +Signed-off-by: Ian Rogers +Tested-by: Arnaldo Carvalho de Melo +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Alexei Starovoitov +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Daniel Borkmann +Cc: Jin Yao +Cc: Jiri Olsa +Cc: John Fastabend +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Martin KaFai Lau +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Stephane Eranian +Cc: Yonghong Song +Cc: bpf@vger.kernel.org +Cc: kp singh +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200515221732.44078-8-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c + tools/perf/util/stat-shadow.c +--- + tools/perf/tests/expr.c | 44 ++++++------ + tools/perf/tests/pmu-events.c | 25 +++---- + tools/perf/util/expr.c | 129 +++++++++++++++++++--------------- + tools/perf/util/expr.h | 29 ++++---- + tools/perf/util/expr.y | 22 +----- + tools/perf/util/metricgroup.c | 92 +++++++++++------------- + tools/perf/util/stat-shadow.c | 49 ++++++++----- + 7 files changed, 200 insertions(+), 190 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index d7f74094f935..13c4243110d8 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -17,15 +17,13 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2) + int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + { + const char *p; +- const char **other; +- double val; +- int i, ret; ++ double val, *val_ptr; ++ int ret; + struct expr_parse_ctx ctx; +- int num_other; + + expr__ctx_init(&ctx); +- expr__add_id(&ctx, "FOO", 1); +- expr__add_id(&ctx, "BAR", 2); ++ expr__add_id(&ctx, strdup("FOO"), 1); ++ expr__add_id(&ctx, strdup("BAR"), 2); + + ret = test(&ctx, "1+1", 2); + ret |= test(&ctx, "FOO+BAR", 3); +@@ -49,25 +47,29 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + ret = expr__parse(&val, &ctx, p, 1); + TEST_ASSERT_VAL("missing operand", ret == -1); + ++ expr__ctx_clear(&ctx); + TEST_ASSERT_VAL("find other", +- expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other, 1) == 0); +- TEST_ASSERT_VAL("find other", num_other == 3); +- TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR")); +- TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); +- TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); +- TEST_ASSERT_VAL("find other", other[3] == NULL); ++ expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", ++ &ctx, 1) == 0); ++ TEST_ASSERT_VAL("find other", hashmap__size(&ctx.ids) == 3); ++ TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BAR", ++ (void **)&val_ptr)); ++ TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BAZ", ++ (void **)&val_ptr)); ++ TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BOZO", ++ (void **)&val_ptr)); + ++ expr__ctx_clear(&ctx); + TEST_ASSERT_VAL("find other", +- expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", NULL, +- &other, &num_other, 3) == 0); +- TEST_ASSERT_VAL("find other", num_other == 2); +- TEST_ASSERT_VAL("find other", !strcmp(other[0], "EVENT1,param=3/")); +- TEST_ASSERT_VAL("find other", !strcmp(other[1], "EVENT2,param=3/")); +- TEST_ASSERT_VAL("find other", other[2] == NULL); ++ expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", ++ NULL, &ctx, 3) == 0); ++ TEST_ASSERT_VAL("find other", hashmap__size(&ctx.ids) == 2); ++ TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "EVENT1,param=3/", ++ (void **)&val_ptr)); ++ TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "EVENT2,param=3/", ++ (void **)&val_ptr)); + +- for (i = 0; i < num_other; i++) +- free((void *)other[i]); +- free((void *)other); ++ expr__ctx_clear(&ctx); + + return 0; + } +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 233806382300..41dab7e36761 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -435,8 +435,6 @@ static int test_parsing(void) + struct pmu_events_map *map; + struct pmu_event *pe; + int i, j, k; +- const char **ids; +- int idnum; + int ret = 0; + struct expr_parse_ctx ctx; + double result; +@@ -448,29 +446,34 @@ static int test_parsing(void) + break; + j = 0; + for (;;) { ++ struct hashmap_entry *cur; ++ size_t bkt; ++ + pe = &map->table[j++]; + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; +- if (expr__find_other(pe->metric_expr, NULL, +- &ids, &idnum, 0) < 0) { ++ expr__ctx_init(&ctx); ++ if (expr__find_other(pe->metric_expr, NULL, &ctx, 0) ++ < 0) { + expr_failure("Parse other failed", map, pe); + ret++; + continue; + } +- expr__ctx_init(&ctx); + + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to + * make them unique. + */ +- for (k = 0; k < idnum; k++) +- expr__add_id(&ctx, ids[k], k + 1); ++ k = 1; ++ hashmap__for_each_entry((&ctx.ids), cur, bkt) ++ expr__add_id(&ctx, strdup(cur->key), k++); + +- for (k = 0; k < idnum; k++) { +- if (check_parse_id(ids[k], map == cpus_map, pe)) ++ hashmap__for_each_entry((&ctx.ids), cur, bkt) { ++ if (check_parse_id(cur->key, map == cpus_map, ++ pe)) + ret++; + } + +@@ -478,9 +481,7 @@ static int test_parsing(void) + expr_failure("Parse failed", map, pe); + ret++; + } +- for (k = 0; k < idnum; k++) +- zfree(&ids[k]); +- free(ids); ++ expr__ctx_clear(&ctx); + } + } + /* TODO: fail when not ok */ +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index aa631e37ad1e..8ab40b42d3e6 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -4,25 +4,76 @@ + #include "expr.h" + #include "expr-bison.h" + #include "expr-flex.h" ++#include + + #ifdef PARSER_DEBUG + extern int expr_debug; + #endif + ++static size_t key_hash(const void *key, void *ctx __maybe_unused) ++{ ++ const char *str = (const char *)key; ++ size_t hash = 0; ++ ++ while (*str != '\0') { ++ hash *= 31; ++ hash += *str; ++ str++; ++ } ++ return hash; ++} ++ ++static bool key_equal(const void *key1, const void *key2, ++ void *ctx __maybe_unused) ++{ ++ return !strcmp((const char *)key1, (const char *)key2); ++} ++ + /* Caller must make sure id is allocated */ +-void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) ++int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) + { +- int idx; ++ double *val_ptr = NULL, *old_val = NULL; ++ char *old_key = NULL; ++ int ret; ++ ++ if (val != 0.0) { ++ val_ptr = malloc(sizeof(double)); ++ if (!val_ptr) ++ return -ENOMEM; ++ *val_ptr = val; ++ } ++ ret = hashmap__set(&ctx->ids, name, val_ptr, ++ (const void **)&old_key, (void **)&old_val); ++ free(old_key); ++ free(old_val); ++ return ret; ++} ++ ++int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) ++{ ++ double *data; + +- assert(ctx->num_ids < MAX_PARSE_ID); +- idx = ctx->num_ids++; +- ctx->ids[idx].name = name; +- ctx->ids[idx].val = val; ++ if (!hashmap__find(&ctx->ids, id, (void **)&data)) ++ return -1; ++ *val_ptr = (data == NULL) ? 0.0 : *data; ++ return 0; + } + + void expr__ctx_init(struct expr_parse_ctx *ctx) + { +- ctx->num_ids = 0; ++ hashmap__init(&ctx->ids, key_hash, key_equal, NULL); ++} ++ ++void expr__ctx_clear(struct expr_parse_ctx *ctx) ++{ ++ struct hashmap_entry *cur; ++ size_t bkt; ++ ++ hashmap__for_each_entry((&ctx->ids), cur, bkt) { ++ free((char *)cur->key); ++ free(cur->value); ++ } ++ hashmap__clear(&ctx->ids); + } + + static int +@@ -55,61 +106,25 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + return ret; + } + +-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime) ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, ++ const char *expr, int runtime) + { + return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; + } + +-static bool +-already_seen(const char *val, const char *one, const char **other, +- int num_other) +-{ +- int i; +- +- if (one && !strcasecmp(one, val)) +- return true; +- for (i = 0; i < num_other; i++) +- if (!strcasecmp(other[i], val)) +- return true; +- return false; +-} +- +-int expr__find_other(const char *expr, const char *one, const char ***other, +- int *num_other, int runtime) ++int expr__find_other(const char *expr, const char *one, ++ struct expr_parse_ctx *ctx, int runtime) + { +- int err, i = 0, j = 0; +- struct expr_parse_ctx ctx; +- +- expr__ctx_init(&ctx); +- err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime); +- if (err) +- return -1; +- +- *other = malloc((ctx.num_ids + 1) * sizeof(char *)); +- if (!*other) +- return -ENOMEM; +- +- for (i = 0, j = 0; i < ctx.num_ids; i++) { +- const char *str = ctx.ids[i].name; +- +- if (already_seen(str, one, *other, j)) +- continue; +- +- str = strdup(str); +- if (!str) +- goto out; +- (*other)[j++] = str; +- } +- (*other)[j] = NULL; +- +-out: +- if (i != ctx.num_ids) { +- while (--j) +- free((char *) (*other)[i]); +- free(*other); +- err = -1; ++ double *old_val = NULL; ++ char *old_key = NULL; ++ int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); ++ ++ if (one) { ++ hashmap__delete(&ctx->ids, one, ++ (const void **)&old_key, (void **)&old_val); ++ free(old_key); ++ free(old_val); + } + +- *num_other = j; +- return err; ++ return ret; + } +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 40fc452b0f2b..8a2c1074f90f 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -2,17 +2,17 @@ + #ifndef PARSE_CTX_H + #define PARSE_CTX_H 1 + +-#define EXPR_MAX_OTHER 64 +-#define MAX_PARSE_ID EXPR_MAX_OTHER +- +-struct expr_parse_id { +- const char *name; +- double val; +-}; ++// There are fixes that need to land upstream before we can use libbpf's headers, ++// for now use our copy uncoditionally, since the data structures at this point ++// are exactly the same, no problem. ++//#ifdef HAVE_LIBBPF_SUPPORT ++//#include ++//#else ++#include "util/hashmap.h" ++//#endif + + struct expr_parse_ctx { +- int num_ids; +- struct expr_parse_id ids[MAX_PARSE_ID]; ++ struct hashmap ids; + }; + + struct expr_scanner_ctx { +@@ -21,9 +21,12 @@ struct expr_scanner_ctx { + }; + + void expr__ctx_init(struct expr_parse_ctx *ctx); +-void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); +-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime); +-int expr__find_other(const char *expr, const char *one, const char ***other, +- int *num_other, int runtime); ++void expr__ctx_clear(struct expr_parse_ctx *ctx); ++int expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); ++int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr); ++int expr__parse(double *final_val, struct expr_parse_ctx *ctx, ++ const char *expr, int runtime); ++int expr__find_other(const char *expr, const char *one, ++ struct expr_parse_ctx *ids, int runtime); + + #endif +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 74c9195860c5..924df4e1c477 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -46,19 +46,6 @@ static void expr_error(double *final_val __maybe_unused, + pr_debug("%s\n", s); + } + +-static int lookup_id(struct expr_parse_ctx *ctx, char *id, double *val) +-{ +- int i; +- +- for (i = 0; i < ctx->num_ids; i++) { +- if (!strcasecmp(ctx->ids[i].name, id)) { +- *val = ctx->ids[i].val; +- return 0; +- } +- } +- return -1; +-} +- + %} + %% + +@@ -72,12 +59,7 @@ all_other: all_other other + + other: ID + { +- if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) { +- pr_err("failed: way too many variables"); +- YYABORT; +- } +- +- ctx->ids[ctx->num_ids++].name = $1; ++ expr__add_id(ctx, $1, 0.0); + } + | + MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' +@@ -92,7 +74,7 @@ if_expr: + ; + + expr: NUMBER +- | ID { if (lookup_id(ctx, $1, &$$) < 0) { ++ | ID { if (expr__get_id(ctx, $1, &$$)) { + pr_debug("%s not found\n", $1); + free($1); + YYABORT; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index b4fe2e2f3ca4..bd1b54b30a87 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -91,8 +91,7 @@ static void metricgroup__rblist_init(struct rblist *metric_events) + + struct egroup { + struct list_head nd; +- int idnum; +- const char **ids; ++ struct expr_parse_ctx pctx; + const char *metric_name; + const char *metric_expr; + const char *metric_unit; +@@ -100,19 +99,21 @@ struct egroup { + }; + + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, +- const char **ids, +- int idnum, ++ struct expr_parse_ctx *pctx, + struct perf_evsel **metric_events, + bool *evlist_used) + { + struct perf_evsel *ev; +- int i = 0, j = 0; + bool leader_found; ++ const size_t idnum = hashmap__size(&pctx->ids); ++ size_t i = 0; ++ int j = 0; ++ double *val_ptr; + + evlist__for_each_entry (perf_evlist, ev) { + if (evlist_used[j++]) + continue; +- if (!strcmp(ev->name, ids[i])) { ++ if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) { + if (!metric_events[i]) + metric_events[i] = ev; + i++; +@@ -123,14 +124,6 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + i = 0; + memset(metric_events, 0, + sizeof(struct perf_evsel *) * idnum); +- +- if (!strcmp(ev->name, ids[i])) { +- if (!metric_events[i]) +- metric_events[i] = ev; +- i++; +- if (i == idnum) +- break; +- } + } + } + +@@ -181,20 +174,21 @@ static int metricgroup__setup_events(struct list_head *groups, + list_for_each_entry (eg, groups, nd) { + struct perf_evsel **metric_events; + +- metric_events = calloc(sizeof(void *), eg->idnum + 1); ++ metric_events = calloc(sizeof(void *), ++ hashmap__size(&eg->pctx.ids) + 1); + if (!metric_events) { + ret = -ENOMEM; + break; + } +- evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum, +- metric_events, evlist_used); ++ evsel = find_evsel_group(perf_evlist, &eg->pctx, metric_events, ++ evlist_used); + if (!evsel) { + pr_debug("Cannot resolve %s: %s\n", + eg->metric_name, eg->metric_expr); + free(metric_events); + continue; + } +- for (i = 0; i < eg->idnum; i++) ++ for (i = 0; metric_events[i]; i++) + metric_events[i]->collect_stat = true; + me = metricgroup__lookup(metric_events_list, evsel, true); + if (!me) { +@@ -425,20 +419,20 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + } + + static void metricgroup__add_metric_weak_group(struct strbuf *events, +- const char **ids, +- int idnum) ++ struct expr_parse_ctx *ctx) + { ++ struct hashmap_entry *cur; ++ size_t bkt, i = 0; + bool no_group = false; +- int i; + +- for (i = 0; i < idnum; i++) { +- pr_debug("found event %s\n", ids[i]); ++ hashmap__for_each_entry((&ctx->ids), cur, bkt) { ++ pr_debug("found event %s\n", (const char *)cur->key); + /* + * Duration time maps to a software event and can make + * groups not count. Always use it outside a + * group. + */ +- if (!strcmp(ids[i], "duration_time")) { ++ if (!strcmp(cur->key, "duration_time")) { + if (i > 0) + strbuf_addf(events, "}:W,"); + strbuf_addf(events, "duration_time"); +@@ -447,21 +441,22 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, + } + strbuf_addf(events, "%s%s", + i == 0 || no_group ? "{" : ",", +- ids[i]); ++ (const char *)cur->key); + no_group = false; ++ i++; + } + if (!no_group) + strbuf_addf(events, "}:W"); + } + + static void metricgroup__add_metric_non_group(struct strbuf *events, +- const char **ids, +- int idnum) ++ struct expr_parse_ctx *ctx) + { +- int i; ++ struct hashmap_entry *cur; ++ size_t bkt; + +- for (i = 0; i < idnum; i++) +- strbuf_addf(events, ",%s", ids[i]); ++ hashmap__for_each_entry((&ctx->ids), cur, bkt) ++ strbuf_addf(events, ",%s", (const char *)cur->key); + } + + static void metricgroup___watchdog_constraint_hint(const char *name, bool foot) +@@ -505,32 +500,32 @@ int __weak arch_get_runtimeparam(void) + static int __metricgroup__add_metric(struct strbuf *events, + struct list_head *group_list, struct pmu_event *pe, int runtime) + { +- +- const char **ids; +- int idnum; + struct egroup *eg; + +- if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum, runtime) < 0) +- return -EINVAL; +- +- if (events->len > 0) +- strbuf_addf(events, ","); +- +- if (metricgroup__has_constraint(pe)) +- metricgroup__add_metric_non_group(events, ids, idnum); +- else +- metricgroup__add_metric_weak_group(events, ids, idnum); +- + eg = malloc(sizeof(*eg)); + if (!eg) + return -ENOMEM; + +- eg->ids = ids; +- eg->idnum = idnum; ++ expr__ctx_init(&eg->pctx); + eg->metric_name = pe->metric_name; + eg->metric_expr = pe->metric_expr; + eg->metric_unit = pe->unit; + eg->runtime = runtime; ++ ++ if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { ++ expr__ctx_clear(&eg->pctx); ++ free(eg); ++ return -EINVAL; ++ } ++ ++ if (events->len > 0) ++ strbuf_addf(events, ","); ++ ++ if (metricgroup__has_constraint(pe)) ++ metricgroup__add_metric_non_group(events, &eg->pctx); ++ else ++ metricgroup__add_metric_weak_group(events, &eg->pctx); ++ + list_add_tail(&eg->nd, group_list); + + return 0; +@@ -613,12 +608,9 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events, + static void metricgroup__free_egroups(struct list_head *group_list) + { + struct egroup *eg, *egtmp; +- int i; + + list_for_each_entry_safe (eg, egtmp, group_list, nd) { +- for (i = 0; i < eg->idnum; i++) +- free((char *)eg->ids[i]); +- free(eg->ids); ++ expr__ctx_clear(&eg->pctx); + list_del_init(&eg->nd); + free(eg); + } +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index dfa33d1bce53..8c8e1f7ea2e2 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -323,35 +323,46 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) + { + struct perf_evsel *counter, *leader, **metric_events, *oc; + bool found; +- const char **metric_names; ++ struct expr_parse_ctx ctx; ++ struct hashmap_entry *cur; ++ size_t bkt; + int i; +- int num_metric_names; + ++ expr__ctx_init(&ctx); + evlist__for_each_entry(evsel_list, counter) { + bool invalid = false; + + leader = counter->leader; + if (!counter->metric_expr) + continue; ++ ++ expr__ctx_clear(&ctx); + metric_events = counter->metric_events; + if (!metric_events) { +- if (expr__find_other(counter->metric_expr, counter->name, +- &metric_names, &num_metric_names, 1) < 0) ++ if (expr__find_other(counter->metric_expr, ++ counter->name, ++ &ctx, 1) < 0) + continue; + + metric_events = calloc(sizeof(struct perf_evsel *), +- num_metric_names + 1); +- if (!metric_events) ++ hashmap__size(&ctx.ids) + 1); ++ if (!metric_events) { ++ expr__ctx_clear(&ctx); + return; ++ } + counter->metric_events = metric_events; + } + +- for (i = 0; i < num_metric_names; i++) { ++ i = 0; ++ hashmap__for_each_entry((&ctx.ids), cur, bkt) { ++ const char *metric_name = (const char *)cur->key; ++ + found = false; + if (leader) { + /* Search in group */ + for_each_group_member (oc, leader) { +- if (!strcasecmp(oc->name, metric_names[i]) && ++ if (!strcasecmp(oc->name, ++ metric_name) && + !oc->collect_stat) { + found = true; + break; +@@ -360,7 +371,8 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) + } + if (!found) { + /* Search ignoring groups */ +- oc = perf_stat__find_event(evsel_list, metric_names[i]); ++ oc = perf_stat__find_event(evsel_list, ++ metric_name); + } + if (!oc) { + /* Deduping one is good enough to handle duplicated PMUs. */ +@@ -373,27 +385,28 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) + * of events. So we ask the user instead to add the missing + * events. + */ +- if (!printed || strcasecmp(printed, metric_names[i])) { ++ if (!printed || ++ strcasecmp(printed, metric_name)) { + fprintf(stderr, + "Add %s event to groups to get metric expression for %s\n", +- metric_names[i], ++ metric_name, + counter->name); +- printed = strdup(metric_names[i]); ++ printed = strdup(metric_name); + } + invalid = true; + continue; + } +- metric_events[i] = oc; ++ metric_events[i++] = oc; + oc->collect_stat = true; + } + metric_events[i] = NULL; +- free(metric_names); + if (invalid) { + free(metric_events); + counter->metric_events = NULL; + counter->metric_expr = NULL; + } + } ++ expr__ctx_clear(&ctx); + } + + static double runtime_stat_avg(struct runtime_stat *st, +@@ -738,7 +751,10 @@ static void generic_metric(struct perf_stat_config *config, + + expr__ctx_init(&pctx); + /* Must be first id entry */ +- expr__add_id(&pctx, name, avg); ++ n = strdup(name); ++ if (!n) ++ return; ++ expr__add_id(&pctx, n, avg); + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; +@@ -811,8 +827,7 @@ static void generic_metric(struct perf_stat_config *config, + } else + print_metric(config, ctxp, NULL, NULL, "", 0); + +- for (i = 1; i < pctx.num_ids; i++) +- free((void *)pctx.ids[i].name); ++ expr__ctx_clear(&pctx); + } + + void perf_stat__print_shadow_stats(struct perf_stat_config *config, +-- +2.27.0 + diff --git a/patches/0195-perf-metricgroup-Make-evlist_used-variable-a-bitmap-.patch b/patches/0195-perf-metricgroup-Make-evlist_used-variable-a-bitmap-.patch new file mode 100644 index 0000000..7b579ab --- /dev/null +++ b/patches/0195-perf-metricgroup-Make-evlist_used-variable-a-bitmap-.patch @@ -0,0 +1,110 @@ +From bea495f5119ce30bcfa4725b87aa639e10b803ef Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 00:28:08 -0700 +Subject: [PATCH 078/201] perf metricgroup: Make 'evlist_used' variable a + bitmap instead of array of bools + +mainline inclusion +from mainline-v5.8-rc1 +commit 45db55f2ef5e98ef096096efad975dc684a9493f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=45db55f2ef5e98ef096096efad975dc684a9493f + +---------------------------------------------------------------------- + +Use a bitmap rather than an array of bools. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520072814.128267-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index bd1b54b30a87..4a5baf5719c4 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -101,7 +101,7 @@ struct egroup { + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + struct expr_parse_ctx *pctx, + struct perf_evsel **metric_events, +- bool *evlist_used) ++ unsigned long *evlist_used) + { + struct perf_evsel *ev; + bool leader_found; +@@ -111,7 +111,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + double *val_ptr; + + evlist__for_each_entry (perf_evlist, ev) { +- if (evlist_used[j++]) ++ if (test_bit(j++, evlist_used)) + continue; + if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) { + if (!metric_events[i]) +@@ -147,7 +147,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + j++; + } + ev = metric_events[i]; +- evlist_used[ev->idx] = true; ++ set_bit(ev->idx, evlist_used); + } + + return metric_events[0]; +@@ -163,13 +163,11 @@ static int metricgroup__setup_events(struct list_head *groups, + int ret = 0; + struct egroup *eg; + struct perf_evsel *evsel; +- bool *evlist_used; ++ unsigned long *evlist_used; + +- evlist_used = calloc(perf_evlist->nr_entries, sizeof(bool)); +- if (!evlist_used) { +- ret = -ENOMEM; +- return ret; +- } ++ evlist_used = bitmap_alloc(perf_evlist->nr_entries); ++ if (!evlist_used) ++ return -ENOMEM; + + list_for_each_entry (eg, groups, nd) { + struct perf_evsel **metric_events; +@@ -210,7 +208,7 @@ static int metricgroup__setup_events(struct list_head *groups, + list_add(&expr->nd, &me->head); + } + +- free(evlist_used); ++ bitmap_free(evlist_used); + + return ret; + } +-- +2.27.0 + diff --git a/patches/0196-perf-metricgroup-Always-place-duration_time-last.patch b/patches/0196-perf-metricgroup-Always-place-duration_time-last.patch new file mode 100644 index 0000000..3079e65 --- /dev/null +++ b/patches/0196-perf-metricgroup-Always-place-duration_time-last.patch @@ -0,0 +1,93 @@ +From 9600c58c83d3c192fb75d43cb4f52e5b2fc25f19 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:05 -0700 +Subject: [PATCH 079/201] perf metricgroup: Always place duration_time last + +mainline inclusion +from mainline-v5.8-rc1 +commit 4e21c13aca38b69c4470b68ef29d198802e7d74e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4e21c13aca38b69c4470b68ef29d198802e7d74e + +---------------------------------------------------------------------- + +If a metric contains the duration_time event then the event is placed +outside of the metric's group of events. Rather than split the group, +make it so the duration_time is immediately after the group. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 4a5baf5719c4..9f803fd81c8f 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -420,8 +420,8 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, + struct expr_parse_ctx *ctx) + { + struct hashmap_entry *cur; +- size_t bkt, i = 0; +- bool no_group = false; ++ size_t bkt; ++ bool no_group = true, has_duration = false; + + hashmap__for_each_entry((&ctx->ids), cur, bkt) { + pr_debug("found event %s\n", (const char *)cur->key); +@@ -431,20 +431,20 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, + * group. + */ + if (!strcmp(cur->key, "duration_time")) { +- if (i > 0) +- strbuf_addf(events, "}:W,"); +- strbuf_addf(events, "duration_time"); +- no_group = true; ++ has_duration = true; + continue; + } + strbuf_addf(events, "%s%s", +- i == 0 || no_group ? "{" : ",", ++ no_group ? "{" : ",", + (const char *)cur->key); + no_group = false; +- i++; + } +- if (!no_group) ++ if (!no_group) { + strbuf_addf(events, "}:W"); ++ if (has_duration) ++ strbuf_addf(events, ",duration_time"); ++ } else if (has_duration) ++ strbuf_addf(events, "duration_time"); + } + + static void metricgroup__add_metric_non_group(struct strbuf *events, +-- +2.27.0 + diff --git a/patches/0197-perf-metricgroup-Use-early-return-in-add_metric.patch b/patches/0197-perf-metricgroup-Use-early-return-in-add_metric.patch new file mode 100644 index 0000000..851263e --- /dev/null +++ b/patches/0197-perf-metricgroup-Use-early-return-in-add_metric.patch @@ -0,0 +1,110 @@ +From 41adaa29c3f367b5a536ccd0a6b0550b469a5618 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:06 -0700 +Subject: [PATCH 080/201] perf metricgroup: Use early return in add_metric + +mainline inclusion +from mainline-v5.8-rc1 +commit 908103991a9970a8e033e9f3aedd092a2c993f49 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=908103991a9970a8e033e9f3aedd092a2c993f49 + +---------------------------------------------------------------------- + +Use early return in metricgroup__add_metric and try to make the intent +of the returns more intention revealing. + +Suggested-by: Jiri Olsa +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-3-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 9f803fd81c8f..dafabead253b 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -534,7 +534,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); + struct pmu_event *pe; +- int i, ret = -EINVAL; ++ int i, ret; ++ bool has_match = false; + + if (!map) + return 0; +@@ -542,17 +543,23 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + for (i = 0; ; i++) { + pe = &map->table[i]; + +- if (!pe->name && !pe->metric_group && !pe->metric_name) ++ if (!pe->name && !pe->metric_group && !pe->metric_name) { ++ /* End of pmu events. */ ++ if (!has_match) ++ return -EINVAL; + break; ++ } + if (!pe->metric_expr) + continue; + if (match_metric(pe->metric_group, metric) || + match_metric(pe->metric_name, metric)) { +- ++ has_match = true; + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { + ret = __metricgroup__add_metric(events, group_list, pe, 1); ++ if (ret) ++ return ret; + } else { + int j, count; + +@@ -563,14 +570,15 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + * those events to group_list. + */ + +- for (j = 0; j < count; j++) ++ for (j = 0; j < count; j++) { + ret = __metricgroup__add_metric(events, group_list, pe, j); ++ if (ret) ++ return ret; ++ } + } +- if (ret == -ENOMEM) +- break; + } + } +- return ret; ++ return 0; + } + + static int metricgroup__add_metric_list(const char *list, struct strbuf *events, +-- +2.27.0 + diff --git a/patches/0198-perf-metricgroup-Delay-events-string-creation.patch b/patches/0198-perf-metricgroup-Delay-events-string-creation.patch new file mode 100644 index 0000000..fb62a5e --- /dev/null +++ b/patches/0198-perf-metricgroup-Delay-events-string-creation.patch @@ -0,0 +1,144 @@ +From fb520c75e6f1ad6fdd10ffe290bd3ba05748713d Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:07 -0700 +Subject: [PATCH 081/201] perf metricgroup: Delay events string creation + +mainline inclusion +from mainline-v5.8-rc1 +commit 7f9eca51c1e8e5acc4264f960c2cdec150f597f9 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7f9eca51c1e8e5acc4264f960c2cdec150f597f9 + +---------------------------------------------------------------------- + +Currently event groups are placed into groups_list at the same time as +the events string containing the events is built. Separate these two +operations and build the groups_list first, then the event string from +the groups_list. This adds an ability to reorder the groups_list that +will be used in a later patch. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-4-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 33 +++++++++++++++++++++------------ + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index dafabead253b..14b9e897cc74 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -96,6 +96,7 @@ struct egroup { + const char *metric_expr; + const char *metric_unit; + int runtime; ++ bool has_constraint; + }; + + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, +@@ -495,8 +496,8 @@ int __weak arch_get_runtimeparam(void) + return 1; + } + +-static int __metricgroup__add_metric(struct strbuf *events, +- struct list_head *group_list, struct pmu_event *pe, int runtime) ++static int __metricgroup__add_metric(struct list_head *group_list, ++ struct pmu_event *pe, int runtime) + { + struct egroup *eg; + +@@ -509,6 +510,7 @@ static int __metricgroup__add_metric(struct strbuf *events, + eg->metric_expr = pe->metric_expr; + eg->metric_unit = pe->unit; + eg->runtime = runtime; ++ eg->has_constraint = metricgroup__has_constraint(pe); + + if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { + expr__ctx_clear(&eg->pctx); +@@ -516,14 +518,6 @@ static int __metricgroup__add_metric(struct strbuf *events, + return -EINVAL; + } + +- if (events->len > 0) +- strbuf_addf(events, ","); +- +- if (metricgroup__has_constraint(pe)) +- metricgroup__add_metric_non_group(events, &eg->pctx); +- else +- metricgroup__add_metric_weak_group(events, &eg->pctx); +- + list_add_tail(&eg->nd, group_list); + + return 0; +@@ -534,6 +528,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); + struct pmu_event *pe; ++ struct egroup *eg; + int i, ret; + bool has_match = false; + +@@ -557,7 +552,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __metricgroup__add_metric(events, group_list, pe, 1); ++ ret = __metricgroup__add_metric(group_list, ++ pe, 1); + if (ret) + return ret; + } else { +@@ -571,13 +567,26 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + */ + + for (j = 0; j < count; j++) { +- ret = __metricgroup__add_metric(events, group_list, pe, j); ++ ret = __metricgroup__add_metric( ++ group_list, pe, j); + if (ret) + return ret; + } + } + } + } ++ list_for_each_entry(eg, group_list, nd) { ++ if (events->len > 0) ++ strbuf_addf(events, ","); ++ ++ if (eg->has_constraint) { ++ metricgroup__add_metric_non_group(events, ++ &eg->pctx); ++ } else { ++ metricgroup__add_metric_weak_group(events, ++ &eg->pctx); ++ } ++ } + return 0; + } + +-- +2.27.0 + diff --git a/patches/0199-perf-metricgroup-Order-event-groups-by-size.patch b/patches/0199-perf-metricgroup-Order-event-groups-by-size.patch new file mode 100644 index 0000000..ff995ff --- /dev/null +++ b/patches/0199-perf-metricgroup-Order-event-groups-by-size.patch @@ -0,0 +1,80 @@ +From 32ef39b64d9bef122fb265827f281911991c8412 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:08 -0700 +Subject: [PATCH 082/201] perf metricgroup: Order event groups by size + +mainline inclusion +from mainline-v5.8-rc1 +commit 6bf2102bec4e600e72f87569d2c8e01a3efb340e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6bf2102bec4e600e72f87569d2c8e01a3efb340e + +---------------------------------------------------------------------- + +When adding event groups to the group list, insert them in size order. +This performs an insertion sort on the group list. By placing the +largest groups at the front of the group list it is possible to see if a +larger group contains the same events as a later group. This can make +the later group redundant - it can reuse the events from the large +group. A later patch will add this sharing. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-5-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 14b9e897cc74..c9ff1be3a992 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -518,7 +518,21 @@ static int __metricgroup__add_metric(struct list_head *group_list, + return -EINVAL; + } + +- list_add_tail(&eg->nd, group_list); ++ if (list_empty(group_list)) ++ list_add(&eg->nd, group_list); ++ else { ++ struct list_head *pos; ++ ++ /* Place the largest groups at the front. */ ++ list_for_each_prev(pos, group_list) { ++ struct egroup *old = list_entry(pos, struct egroup, nd); ++ ++ if (hashmap__size(&eg->pctx.ids) <= ++ hashmap__size(&old->pctx.ids)) ++ break; ++ } ++ list_add(&eg->nd, pos); ++ } + + return 0; + } +-- +2.27.0 + diff --git a/patches/0200-perf-metricgroup-Remove-duped-metric-group-events.patch b/patches/0200-perf-metricgroup-Remove-duped-metric-group-events.patch new file mode 100644 index 0000000..05b2620 --- /dev/null +++ b/patches/0200-perf-metricgroup-Remove-duped-metric-group-events.patch @@ -0,0 +1,254 @@ +From 44f2d339d18d722e5afd9beccb4474fc0ed60412 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:09 -0700 +Subject: [PATCH 083/201] perf metricgroup: Remove duped metric group events + +mainline inclusion +from mainline-v5.8-rc1 +commit 2440689d62e93574ca71c87129f7d523ddff7679 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2440689d62e93574ca71c87129f7d523ddff7679 + +---------------------------------------------------------------------- + +A metric group contains multiple metrics. These metrics may use the same +events. If metrics use separate events then it leads to more +multiplexing and overall metric counts fail to sum to 100%. + +Modify how metrics are associated with events so that if the events in +an earlier group satisfy the current metric, the same events are used. +A record of used events is kept and at the end of processing unnecessary +events are eliminated. + +Before: + + $ perf stat -a -M TopDownL1 sleep 1 + + Performance counter stats for 'system wide': + + 920,211,343 uops_issued.any # 0.5 Backend_Bound (16.56%) + 1,977,733,128 idq_uops_not_delivered.core (16.56%) + 51,668,510 int_misc.recovery_cycles (16.56%) + 732,305,692 uops_retired.retire_slots (16.56%) + 1,497,621,849 cycles (16.56%) + 721,098,274 uops_issued.any # 0.1 Bad_Speculation (16.79%) + 1,332,681,791 cycles (16.79%) + 552,475,482 uops_retired.retire_slots (16.79%) + 47,708,340 int_misc.recovery_cycles (16.79%) + 1,383,713,292 cycles + # 0.4 Frontend_Bound (16.76%) + 2,013,757,701 idq_uops_not_delivered.core (16.76%) + 1,373,363,790 cycles + # 0.1 Retiring (33.54%) + 577,302,589 uops_retired.retire_slots (33.54%) + 392,766,987 inst_retired.any # 0.3 IPC (50.24%) + 1,351,873,350 cpu_clk_unhalted.thread (50.24%) + 1,332,510,318 cycles + # 5330041272.0 SLOTS (49.90%) + + 1.006336145 seconds time elapsed + +After: + + $ perf stat -a -M TopDownL1 sleep 1 + + Performance counter stats for 'system wide': + + 765,949,145 uops_issued.any # 0.1 Bad_Speculation + # 0.5 Backend_Bound (50.09%) + 1,883,830,591 idq_uops_not_delivered.core # 0.3 Frontend_Bound (50.09%) + 48,237,080 int_misc.recovery_cycles (50.09%) + 581,798,385 uops_retired.retire_slots # 0.1 Retiring (50.09%) + 1,361,628,527 cycles + # 5446514108.0 SLOTS (50.09%) + 391,415,714 inst_retired.any # 0.3 IPC (49.91%) + 1,336,486,781 cpu_clk_unhalted.thread (49.91%) + + 1.005469298 seconds time elapsed + +Note: Bad_Speculation + Backend_Bound + Frontend_Bound + Retiring = 100% +after, where as before it is 110%. After there are 2 groups, whereas +before there are 6. After the cycles event appears once, before it +appeared 5 times. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-6-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 91 ++++++++++++++++++++++++----------- + 1 file changed, 62 insertions(+), 29 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index c9ff1be3a992..65f96cfa4183 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -99,36 +99,72 @@ struct egroup { + bool has_constraint; + }; + ++/** ++ * Find a group of events in perf_evlist that correpond to those from a parsed ++ * metric expression. ++ * @perf_evlist: a list of events something like: {metric1 leader, metric1 ++ * sibling, metric1 sibling}:W,duration_time,{metric2 leader, metric2 sibling, ++ * metric2 sibling}:W,duration_time ++ * @pctx: the parse context for the metric expression. ++ * @has_constraint: is there a contraint on the group of events? In which case ++ * the events won't be grouped. ++ * @metric_events: out argument, null terminated array of evsel's associated ++ * with the metric. ++ * @evlist_used: in/out argument, bitmap tracking which evlist events are used. ++ * @return the first metric event or NULL on failure. ++ */ + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + struct expr_parse_ctx *pctx, ++ bool has_constraint, + struct perf_evsel **metric_events, + unsigned long *evlist_used) + { +- struct perf_evsel *ev; +- bool leader_found; +- const size_t idnum = hashmap__size(&pctx->ids); +- size_t i = 0; +- int j = 0; ++ struct perf_evsel *ev, *current_leader = NULL; + double *val_ptr; ++ int i = 0, matched_events = 0, events_to_match; ++ const int idnum = (int)hashmap__size(&pctx->ids); ++ ++ /* duration_time is grouped separately. */ ++ if (!has_constraint && ++ hashmap__find(&pctx->ids, "duration_time", (void **)&val_ptr)) ++ events_to_match = idnum - 1; ++ else ++ events_to_match = idnum; + + evlist__for_each_entry (perf_evlist, ev) { +- if (test_bit(j++, evlist_used)) ++ /* ++ * Events with a constraint aren't grouped and match the first ++ * events available. ++ */ ++ if (has_constraint && ev->weak_group) + continue; +- if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) { +- if (!metric_events[i]) +- metric_events[i] = ev; +- i++; +- if (i == idnum) +- break; +- } else { +- /* Discard the whole match and start again */ +- i = 0; ++ if (!has_constraint && ev->leader != current_leader) { ++ /* ++ * Start of a new group, discard the whole match and ++ * start again. ++ */ ++ matched_events = 0; + memset(metric_events, 0, + sizeof(struct perf_evsel *) * idnum); ++ current_leader = ev->leader; + } ++ if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) ++ metric_events[matched_events++] = ev; ++ if (matched_events == events_to_match) ++ break; + } + +- if (i != idnum) { ++ if (events_to_match != idnum) { ++ /* Add the first duration_time. */ ++ evlist__for_each_entry(perf_evlist, ev) { ++ if (!strcmp(ev->name, "duration_time")) { ++ metric_events[matched_events++] = ev; ++ break; ++ } ++ } ++ } ++ ++ if (matched_events != idnum) { + /* Not whole match */ + return NULL; + } +@@ -136,18 +172,8 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + metric_events[idnum] = NULL; + + for (i = 0; i < idnum; i++) { +- leader_found = false; +- evlist__for_each_entry(perf_evlist, ev) { +- if (!leader_found && (ev == metric_events[i])) +- leader_found = true; +- +- if (leader_found && +- !strcmp(ev->name, metric_events[i]->name)) { +- ev->metric_leader = metric_events[i]; +- } +- j++; +- } + ev = metric_events[i]; ++ ev->metric_leader = ev; + set_bit(ev->idx, evlist_used); + } + +@@ -163,7 +189,7 @@ static int metricgroup__setup_events(struct list_head *groups, + int i = 0; + int ret = 0; + struct egroup *eg; +- struct perf_evsel *evsel; ++ struct perf_evsel *evsel, *tmp; + unsigned long *evlist_used; + + evlist_used = bitmap_alloc(perf_evlist->nr_entries); +@@ -179,7 +205,8 @@ static int metricgroup__setup_events(struct list_head *groups, + ret = -ENOMEM; + break; + } +- evsel = find_evsel_group(perf_evlist, &eg->pctx, metric_events, ++ evsel = find_evsel_group(perf_evlist, &eg->pctx, ++ eg->has_constraint, metric_events, + evlist_used); + if (!evsel) { + pr_debug("Cannot resolve %s: %s\n", +@@ -209,6 +236,12 @@ static int metricgroup__setup_events(struct list_head *groups, + list_add(&expr->nd, &me->head); + } + ++ evlist__for_each_entry_safe(perf_evlist, tmp, evsel) { ++ if (!test_bit(evsel->idx, evlist_used)) { ++ perf_evlist__remove(perf_evlist, evsel); ++ perf_evsel__delete(evsel); ++ } ++ } + bitmap_free(evlist_used); + + return ret; +-- +2.27.0 + diff --git a/patches/0201-perf-metricgroup-Add-options-to-not-group-or-merge.patch b/patches/0201-perf-metricgroup-Add-options-to-not-group-or-merge.patch new file mode 100644 index 0000000..6d4cefb --- /dev/null +++ b/patches/0201-perf-metricgroup-Add-options-to-not-group-or-merge.patch @@ -0,0 +1,365 @@ +From af2d642045c3d5f3a7ab5a25c95b119f065cb94e Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:10 -0700 +Subject: [PATCH 084/201] perf metricgroup: Add options to not group or merge + +mainline inclusion +from mainline-v5.8-rc1 +commit 05530a7921c0f5149a01e34c4e031c5b18bdc1cc +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=05530a7921c0f5149a01e34c4e031c5b18bdc1cc + +---------------------------------------------------------------------- + +Add --metric-no-group that causes all events within metrics to not be +grouped. This can allow the event to get more time when multiplexed, but +may also lower accuracy. +Add --metric-no-merge option. By default events in different metrics may +be shared if the group of events for one metric is the same or larger +than that of the second. Sharing may increase or lower accuracy and so +is now configurable. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-7-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c + tools/perf/util/stat.h +--- + tools/perf/Documentation/perf-stat.txt | 19 +++++++ + tools/perf/builtin-stat.c | 11 ++++- + tools/perf/util/metricgroup.c | 68 ++++++++++++++++++++------ + tools/perf/util/metricgroup.h | 6 ++- + tools/perf/util/stat.h | 20 ++++---- + 5 files changed, 96 insertions(+), 28 deletions(-) + +diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt +index b10a90b6a718..a5c61d03db59 100644 +--- a/tools/perf/Documentation/perf-stat.txt ++++ b/tools/perf/Documentation/perf-stat.txt +@@ -217,6 +217,25 @@ filter out the startup phase of the program, which is often very different. + + Print statistics of transactional execution if supported. + ++--metric-no-group:: ++By default, events to compute a metric are placed in weak groups. The ++group tries to enforce scheduling all or none of the events. The ++--metric-no-group option places events outside of groups and may ++increase the chance of the event being scheduled - leading to more ++accuracy. However, as events may not be scheduled together accuracy ++for metrics like instructions per cycle can be lower - as both metrics ++may no longer be being measured at the same time. ++ ++--metric-no-merge:: ++By default metric events in different weak groups can be shared if one ++group contains all the events needed by another. In such cases one ++group will be eliminated reducing event multiplexing and making it so ++that certain groups of metrics sum to 100%. A downside to sharing a ++group is that the group may require multiplexing and so accuracy for a ++small group that need not have multiplexing is lowered. This option ++forbids the event merging logic from sharing events between groups and ++may be used to increase accuracy in this case. ++ + STAT RECORD + ----------- + Stores stat data into perf data file. +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 0d8943ead576..56f62a9d0f0d 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1981,7 +1981,10 @@ static int parse_metric_groups(const struct option *opt, + const char *str, + int unset __maybe_unused) + { +- return metricgroup__parse_groups(opt, str, &stat_config.metric_events); ++ return metricgroup__parse_groups(opt, str, ++ stat_config.metric_no_group, ++ stat_config.metric_no_merge, ++ &stat_config.metric_events); + } + + static struct option stat_options[] = { +@@ -2054,6 +2057,10 @@ static struct option stat_options[] = { + "ms to wait before starting measurement after program start"), + OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, + "Only print computed metrics. No raw values", enable_metric_only), ++ OPT_BOOLEAN(0, "metric-no-group", &stat_config.metric_no_group, ++ "don't group metric events, impacts multiplexing"), ++ OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge, ++ "don't try to share events between metrics in a group"), + OPT_BOOLEAN(0, "topdown", &topdown_run, + "measure topdown level 1 statistics"), + OPT_BOOLEAN(0, "smi-cost", &smi_cost, +@@ -2437,6 +2444,8 @@ static int add_default_attributes(void) + struct option opt = { .value = &evsel_list }; + + return metricgroup__parse_groups(&opt, "transaction", ++ stat_config.metric_no_group, ++ stat_config.metric_no_merge, + &stat_config.metric_events); + } + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 65f96cfa4183..249233acb715 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -101,11 +101,15 @@ struct egroup { + + /** + * Find a group of events in perf_evlist that correpond to those from a parsed +- * metric expression. ++ * metric expression. Note, as find_evsel_group is called in the same order as ++ * perf_evlist was constructed, metric_no_merge doesn't need to test for ++ * underfilling a group. + * @perf_evlist: a list of events something like: {metric1 leader, metric1 + * sibling, metric1 sibling}:W,duration_time,{metric2 leader, metric2 sibling, + * metric2 sibling}:W,duration_time + * @pctx: the parse context for the metric expression. ++ * @metric_no_merge: don't attempt to share events for the metric with other ++ * metrics. + * @has_constraint: is there a contraint on the group of events? In which case + * the events won't be grouped. + * @metric_events: out argument, null terminated array of evsel's associated +@@ -115,6 +119,7 @@ struct egroup { + */ + static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + struct expr_parse_ctx *pctx, ++ bool metric_no_merge, + bool has_constraint, + struct perf_evsel **metric_events, + unsigned long *evlist_used) +@@ -138,6 +143,9 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + */ + if (has_constraint && ev->weak_group) + continue; ++ /* Ignore event if already used and merging is disabled. */ ++ if (metric_no_merge && test_bit(ev->idx, evlist_used)) ++ continue; + if (!has_constraint && ev->leader != current_leader) { + /* + * Start of a new group, discard the whole match and +@@ -148,8 +156,23 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + sizeof(struct perf_evsel *) * idnum); + current_leader = ev->leader; + } +- if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) ++ if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) { ++ if (has_constraint) { ++ /* ++ * Events aren't grouped, ensure the same event ++ * isn't matched from two groups. ++ */ ++ for (i = 0; i < matched_events; i++) { ++ if (!strcmp(ev->name, ++ metric_events[i]->name)) { ++ break; ++ } ++ } ++ if (i != matched_events) ++ continue; ++ } + metric_events[matched_events++] = ev; ++ } + if (matched_events == events_to_match) + break; + } +@@ -181,6 +204,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + } + + static int metricgroup__setup_events(struct list_head *groups, ++ bool metric_no_merge, + struct perf_evlist *perf_evlist, + struct rblist *metric_events_list) + { +@@ -206,8 +230,9 @@ static int metricgroup__setup_events(struct list_head *groups, + break; + } + evsel = find_evsel_group(perf_evlist, &eg->pctx, +- eg->has_constraint, metric_events, +- evlist_used); ++ metric_no_merge, ++ eg->has_constraint, metric_events, ++ evlist_used); + if (!evsel) { + pr_debug("Cannot resolve %s: %s\n", + eg->metric_name, eg->metric_expr); +@@ -530,7 +555,9 @@ int __weak arch_get_runtimeparam(void) + } + + static int __metricgroup__add_metric(struct list_head *group_list, +- struct pmu_event *pe, int runtime) ++ struct pmu_event *pe, ++ bool metric_no_group, ++ int runtime) + { + struct egroup *eg; + +@@ -543,7 +570,7 @@ static int __metricgroup__add_metric(struct list_head *group_list, + eg->metric_expr = pe->metric_expr; + eg->metric_unit = pe->unit; + eg->runtime = runtime; +- eg->has_constraint = metricgroup__has_constraint(pe); ++ eg->has_constraint = metric_no_group || metricgroup__has_constraint(pe); + + if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { + expr__ctx_clear(&eg->pctx); +@@ -570,7 +597,8 @@ static int __metricgroup__add_metric(struct list_head *group_list, + return 0; + } + +-static int metricgroup__add_metric(const char *metric, struct strbuf *events, ++static int metricgroup__add_metric(const char *metric, bool metric_no_group, ++ struct strbuf *events, + struct list_head *group_list) + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); +@@ -600,7 +628,9 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + + if (!strstr(pe->metric_expr, "?")) { + ret = __metricgroup__add_metric(group_list, +- pe, 1); ++ pe, ++ metric_no_group, ++ 1); + if (ret) + return ret; + } else { +@@ -615,7 +645,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + + for (j = 0; j < count; j++) { + ret = __metricgroup__add_metric( +- group_list, pe, j); ++ group_list, pe, ++ metric_no_group, j); + if (ret) + return ret; + } +@@ -637,7 +668,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, + return 0; + } + +-static int metricgroup__add_metric_list(const char *list, struct strbuf *events, ++static int metricgroup__add_metric_list(const char *list, bool metric_no_group, ++ struct strbuf *events, + struct list_head *group_list) + { + char *llist, *nlist, *p; +@@ -652,7 +684,8 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events, + strbuf_addf(events, "%s", ""); + + while ((p = strsep(&llist, ",")) != NULL) { +- ret = metricgroup__add_metric(p, events, group_list); ++ ret = metricgroup__add_metric(p, metric_no_group, events, ++ group_list); + if (ret == -EINVAL) { + fprintf(stderr, "Cannot find metric or group `%s'\n", + p); +@@ -679,8 +712,10 @@ static void metricgroup__free_egroups(struct list_head *group_list) + } + + int metricgroup__parse_groups(const struct option *opt, +- const char *str, +- struct rblist *metric_events) ++ const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events) + { + struct parse_events_error parse_error; + struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; +@@ -690,7 +725,8 @@ int metricgroup__parse_groups(const struct option *opt, + + if (metric_events->nr_entries == 0) + metricgroup__rblist_init(metric_events); +- ret = metricgroup__add_metric_list(str, &extra_events, &group_list); ++ ret = metricgroup__add_metric_list(str, metric_no_group, ++ &extra_events, &group_list); + if (ret) + return ret; + pr_debug("adding %s\n", extra_events.buf); +@@ -701,8 +737,8 @@ int metricgroup__parse_groups(const struct option *opt, + goto out; + } + strbuf_release(&extra_events); +- ret = metricgroup__setup_events(&group_list, perf_evlist, +- metric_events); ++ ret = metricgroup__setup_events(&group_list, metric_no_merge, ++ perf_evlist, metric_events); + out: + metricgroup__free_egroups(&group_list); + return ret; +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index f2a17a05eb81..b6dfd7d09b9c 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -29,8 +29,10 @@ struct metric_event *metricgroup__lookup(struct rblist *metric_events, + struct perf_evsel *evsel, + bool create); + int metricgroup__parse_groups(const struct option *opt, +- const char *str, +- struct rblist *metric_events); ++ const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events); + + void metricgroup__print(bool metrics, bool groups, char *filter, + bool raw, bool details); +diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h +index 8a7d8425acf8..fbbc47ed5d3f 100644 +--- a/tools/perf/util/stat.h ++++ b/tools/perf/util/stat.h +@@ -85,15 +85,17 @@ struct runtime_stat { + }; + + struct perf_stat_config { +- enum aggr_mode aggr_mode; +- bool scale; +- FILE *output; +- unsigned int interval; +- unsigned int timeout; +- int times; +- struct runtime_stat *stats; +- int stats_num; +- struct rblist metric_events; ++ enum aggr_mode aggr_mode; ++ bool scale; ++ bool metric_no_group; ++ bool metric_no_merge; ++ FILE *output; ++ unsigned int interval; ++ unsigned int timeout; ++ int times; ++ struct runtime_stat *stats; ++ int stats_num; ++ struct rblist metric_events; + }; + + void update_stats(struct stats *stats, u64 val); +-- +2.27.0 + diff --git a/patches/0202-perf-metricgroup-Remove-unnecessary-from-events.patch b/patches/0202-perf-metricgroup-Remove-unnecessary-from-events.patch new file mode 100644 index 0000000..f2b4905 --- /dev/null +++ b/patches/0202-perf-metricgroup-Remove-unnecessary-from-events.patch @@ -0,0 +1,70 @@ +From 5c7b42272956bf76e7e0c7bbb0c8a752e246e9ee Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 20 May 2020 11:20:11 -0700 +Subject: [PATCH 085/201] perf metricgroup: Remove unnecessary ',' from events + +mainline inclusion +from mainline-v5.8-rc1 +commit e2ce1059b0b3d032aa07cc51c24d28ec498feb5f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e2ce1059b0b3d032aa07cc51c24d28ec498feb5f + +---------------------------------------------------------------------- + +Remove unnecessary commas from events before they are parsed. This +avoids ',' being echoed by parse-events.l. + +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Cong Wang +Cc: Jin Yao +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Kim Phillips +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Srikar Dronamraju +Cc: Stephane Eranian +Cc: Vince Weaver +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200520182011.32236-8-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 249233acb715..8fa4b98f6231 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -511,9 +511,14 @@ static void metricgroup__add_metric_non_group(struct strbuf *events, + { + struct hashmap_entry *cur; + size_t bkt; ++ bool first = true; + +- hashmap__for_each_entry((&ctx->ids), cur, bkt) +- strbuf_addf(events, ",%s", (const char *)cur->key); ++ hashmap__for_each_entry((&ctx->ids), cur, bkt) { ++ if (!first) ++ strbuf_addf(events, ","); ++ strbuf_addf(events, "%s", (const char *)cur->key); ++ first = false; ++ } + } + + static void metricgroup___watchdog_constraint_hint(const char *name, bool foot) +-- +2.27.0 + diff --git a/patches/0203-perf-parser-Add-support-to-specify-rXXX-event-with-p.patch b/patches/0203-perf-parser-Add-support-to-specify-rXXX-event-with-p.patch new file mode 100644 index 0000000..b9d8f45 --- /dev/null +++ b/patches/0203-perf-parser-Add-support-to-specify-rXXX-event-with-p.patch @@ -0,0 +1,190 @@ +From b77372524aa141ad73960c45cac590e344cda3d7 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Fri, 17 Apr 2020 00:14:05 +0200 +Subject: [PATCH 086/201] perf parser: Add support to specify rXXX event with + pmu + +mainline inclusion +from mainline-v5.8-rc1 +commit 3a6c51e4d66cf2fbc05583247b2d2f1179e8a74c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3a6c51e4d66cf2fbc05583247b2d2f1179e8a74c + +---------------------------------------------------------------------- + +The current rXXXX event specification creates event under PERF_TYPE_RAW +pmu type. This change allows to use rXXXX within pmu syntax, so it's +type is used via the following syntax: + + -e 'cpu/r3c/' + -e 'cpum_cf/r0/' + +The XXXX number goes directly to perf_event_attr::config the same way as +in '-e rXXXX' event. The perf_event_attr::type is filled with pmu type. + +Committer testing: + +So, lets see what goes in perf_event_attr::config for, say, the +'instructions' PERF_TYPE_HARDWARE (0) event, first we should look at how +to encode this event as a PERF_TYPE_RAW event for this specific CPU, an +AMD Ryzen 5: + + # cat /sys/devices/cpu/events/instructions + event=0xc0 + # + +Then try with it _and_ the instruction, just to see that they are close +enough: + + # perf stat -e rc0,instructions sleep 1 + + Performance counter stats for 'sleep 1': + + 919,794 rc0 + 919,898 instructions + + 1.000754579 seconds time elapsed + + 0.000715000 seconds user + 0.000000000 seconds sys + # + +Now we should try, before this patch, the PMU event encoding: + + # perf stat -e cpu/rc0/ sleep 1 + event syntax error: 'cpu/rc0/' + \___ unknown term + + valid terms: event,edge,inv,umask,cmask,config,config1,config2,name,period,percore + # + +Now with this patch, the three ways of specifying the 'instructions' CPU +counter are accepted: + + # perf stat -e cpu/rc0/,rc0,instructions sleep 1 + + Performance counter stats for 'sleep 1': + + 892,948 cpu/rc0/ + 893,052 rc0 + 893,156 instructions + + 1.000931819 seconds time elapsed + + 0.000916000 seconds user + 0.000000000 seconds sys + + # + +Requested-by: Thomas Richter +Signed-off-by: Jiri Olsa +Tested-by: Arnaldo Carvalho de Melo +Tested-by: Thomas Richter +Cc: Alexander Shishkin +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Sumanth Korikkar +Cc: Vasily Gorbik +Link: http://lore.kernel.org/lkml/20200416221405.437788-1-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/parse-events.c + tools/perf/util/parse-events.l +--- + tools/perf/Documentation/perf-list.txt | 5 +++++ + tools/perf/tests/parse-events.c | 17 ++++++++++++++++- + tools/perf/util/parse-events.l | 1 + + tools/perf/util/parse-events.y | 9 +++++++++ + 4 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt +index 54d16b4d1ede..b040247d4cb8 100644 +--- a/tools/perf/Documentation/perf-list.txt ++++ b/tools/perf/Documentation/perf-list.txt +@@ -116,6 +116,11 @@ raw encoding of 0x1A8 can be used: + perf stat -e r1a8 -a sleep 1 + perf record -e r1a8 ... + ++It's also possible to use pmu syntax: ++ ++ perf record -e r1a8 -a sleep 1 ++ perf record -e cpu/r1a8/ ... ++ + You should refer to the processor specific documentation for getting these + details. Some of them are referenced in the SEE ALSO section below. + +diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c +index 8f3c80e13584..b379368b6d62 100644 +--- a/tools/perf/tests/parse-events.c ++++ b/tools/perf/tests/parse-events.c +@@ -1356,6 +1356,16 @@ static int test__checkevent_complex_name(struct perf_evlist *evlist) + return 0; + } + ++static int test__checkevent_raw_pmu(struct perf_evlist *evlist) ++{ ++ struct perf_evsel *evsel = perf_evlist__first(evlist); ++ ++ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); ++ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); ++ TEST_ASSERT_VAL("wrong config", 0x1a == evsel->attr.config); ++ return 0; ++} ++ + static int test__sym_event_slash(struct perf_evlist *evlist) + { + struct perf_evsel *evsel = perf_evlist__first(evlist); +@@ -1750,7 +1760,12 @@ static struct evlist_test test__events_pmu[] = { + .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", + .check = test__checkevent_complex_name, + .id = 3, +- } ++ }, ++ { ++ .name = "software/r1a/", ++ .check = test__checkevent_raw_pmu, ++ .id = 4, ++ }, + }; + + struct terms_test { +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index d8c82cd8d610..3719ab1fefb9 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -282,6 +282,7 @@ inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } + no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } + overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } + no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } ++r{num_raw_hex} { return raw(yyscanner); } + , { return ','; } + "/" { BEGIN(INITIAL); return '/'; } + {name_minus} { return str(yyscanner, PE_NAME); } +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index b940b621b14e..ff913778a7d4 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -575,6 +575,15 @@ event_term + } + + event_term: ++PE_RAW ++{ ++ struct parse_events_term *term; ++ ++ ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG, ++ NULL, $1, false, &@1, NULL)); ++ $$ = term; ++} ++| + PE_NAME '=' PE_NAME + { + struct parse_events_term *term; +-- +2.27.0 + diff --git a/patches/0204-perf-tools-Allow-r0x-HEX-event-syntax.patch b/patches/0204-perf-tools-Allow-r0x-HEX-event-syntax.patch new file mode 100644 index 0000000..a601072 --- /dev/null +++ b/patches/0204-perf-tools-Allow-r0x-HEX-event-syntax.patch @@ -0,0 +1,86 @@ +From 5a898b8919815faf58618a42a600d117e631bc83 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sat, 25 Jul 2020 14:19:58 +0200 +Subject: [PATCH 087/201] perf tools: Allow r0x event syntax + +mainline inclusion +from mainline-v5.9-rc1 +commit c33cdf541181fae3dbcfbd79e40b11b0efe8c3d8 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c33cdf541181fae3dbcfbd79e40b11b0efe8c3d8 + +---------------------------------------------------------------------- + +Add support to specify raw event with 'r0' syntax within pmu term +syntax like: + + -e cpu/r0xdead/ + +It will be used to specify raw events in cases where they conflict with +real pmu terms, like 'read', which is valid raw event syntax, but also a +possible pmu term name as reported by Jin Yao. + +Reported-by: Jin Yao +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Richter +Link: http://lore.kernel.org/lkml/20200725121959.1181869-1-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/Documentation/perf-list.txt | 1 + + tools/perf/tests/parse-events.c | 5 +++++ + tools/perf/util/parse-events.l | 1 + + 3 files changed, 7 insertions(+) + +diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt +index b040247d4cb8..d8671953e992 100644 +--- a/tools/perf/Documentation/perf-list.txt ++++ b/tools/perf/Documentation/perf-list.txt +@@ -120,6 +120,7 @@ It's also possible to use pmu syntax: + + perf record -e r1a8 -a sleep 1 + perf record -e cpu/r1a8/ ... ++ perf record -e cpu/r0x1a8/ ... + + You should refer to the processor specific documentation for getting these + details. Some of them are referenced in the SEE ALSO section below. +diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c +index b379368b6d62..95cdc0d01a19 100644 +--- a/tools/perf/tests/parse-events.c ++++ b/tools/perf/tests/parse-events.c +@@ -1766,6 +1766,11 @@ static struct evlist_test test__events_pmu[] = { + .check = test__checkevent_raw_pmu, + .id = 4, + }, ++ { ++ .name = "software/r0x1a/", ++ .check = test__checkevent_raw_pmu, ++ .id = 4, ++ }, + }; + + struct terms_test { +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index 3719ab1fefb9..e7f00b5c123d 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -283,6 +283,7 @@ no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } + overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } + no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } + r{num_raw_hex} { return raw(yyscanner); } ++r0x{num_raw_hex} { return raw(yyscanner); } + , { return ','; } + "/" { BEGIN(INITIAL); return '/'; } + {name_minus} { return str(yyscanner, PE_NAME); } +-- +2.27.0 + diff --git a/patches/0205-perf-stat-Do-not-pass-avg-to-generic_metric.patch b/patches/0205-perf-stat-Do-not-pass-avg-to-generic_metric.patch new file mode 100644 index 0000000..e9fc075 --- /dev/null +++ b/patches/0205-perf-stat-Do-not-pass-avg-to-generic_metric.patch @@ -0,0 +1,78 @@ +From bf4aa0d85a33f2d2714946ac8d8da7e8a45ed488 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Mon, 25 May 2020 00:42:07 +0200 +Subject: [PATCH 088/201] perf stat: Do not pass avg to generic_metric + +mainline inclusion +from mainline-v5.8-rc1 +commit 5f09ca5a1484632d1d3dc533d626d12c4370dbbc +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5f09ca5a1484632d1d3dc533d626d12c4370dbbc + +---------------------------------------------------------------------- + +There's no need to pass the given evsel's count to metric data, because +it will be pushed again within the following metric_events loop. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200524224219.234847-3-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/stat-shadow.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 8c8e1f7ea2e2..40af5b4feb00 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -737,7 +737,6 @@ static void generic_metric(struct perf_stat_config *config, + const char *metric_name, + const char *metric_unit, + int runtime, +- double avg, + int cpu, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +@@ -750,11 +749,6 @@ static void generic_metric(struct perf_stat_config *config, + char *n, *pn; + + expr__ctx_init(&pctx); +- /* Must be first id entry */ +- n = strdup(name); +- if (!n) +- return; +- expr__add_id(&pctx, n, avg); + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; +@@ -1042,7 +1036,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + print_metric(config, ctxp, NULL, NULL, name, 0); + } else if (evsel->metric_expr) { + generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, +- evsel->metric_name, NULL, 1, avg, cpu, out, st); ++ evsel->metric_name, NULL, 1, cpu, out, st); + } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { + char unit = 'M'; + char unit_buf[10]; +@@ -1071,7 +1065,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + out->new_line(config, ctxp); + generic_metric(config, mexp->metric_expr, mexp->metric_events, + evsel->name, mexp->metric_name, +- mexp->metric_unit, mexp->runtime, avg, cpu, out, st); ++ mexp->metric_unit, mexp->runtime, cpu, out, st); + } + } + if (num == 0) +-- +2.27.0 + diff --git a/patches/0206-perf-parse-Add-struct-parse_events_state-pointer-to-.patch b/patches/0206-perf-parse-Add-struct-parse_events_state-pointer-to-.patch new file mode 100644 index 0000000..4466e51 --- /dev/null +++ b/patches/0206-perf-parse-Add-struct-parse_events_state-pointer-to-.patch @@ -0,0 +1,136 @@ +From d9408ff297274978db3e6905ef70a3d25fa4029a Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Mon, 25 May 2020 00:42:08 +0200 +Subject: [PATCH 089/201] perf parse: Add 'struct parse_events_state' pointer + to scanner + +mainline inclusion +from mainline-v5.8-rc1 +commit 1244a32736f8f6a12e0959aa897813744122d690 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1244a32736f8f6a12e0959aa897813744122d690 + +---------------------------------------------------------------------- + +We need to pass more data to the scanner so let's start with having it +to take pointer to 'struct parse_events_state' object instead of just +start token. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200524224219.234847-4-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +--- + tools/perf/util/parse-events.c | 15 +++++++++------ + tools/perf/util/parse-events.h | 1 + + tools/perf/util/parse-events.l | 8 ++++---- + 3 files changed, 14 insertions(+), 10 deletions(-) + +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 8b9b13b6e901..67ae5069737b 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -24,7 +24,7 @@ + #include "debug.h" + #include + #include "parse-events-bison.h" +-#define YY_EXTRA_TYPE int ++#define YY_EXTRA_TYPE void* + #include "parse-events-flex.h" + #include "pmu.h" + #include "thread_map.h" +@@ -1820,13 +1820,14 @@ perf_pmu__parse_check(const char *name) + return r ? r->type : PMU_EVENT_SYMBOL_ERR; + } + +-static int parse_events__scanner(const char *str, void *parse_state, int start_token) ++static int parse_events__scanner(const char *str, ++ struct parse_events_state *parse_state) + { + YY_BUFFER_STATE buffer; + void *scanner; + int ret; + +- ret = parse_events_lex_init_extra(start_token, &scanner); ++ ret = parse_events_lex_init_extra(parse_state, &scanner); + if (ret) + return ret; + +@@ -1849,11 +1850,12 @@ static int parse_events__scanner(const char *str, void *parse_state, int start_t + int parse_events_terms(struct list_head *terms, const char *str) + { + struct parse_events_state parse_state = { +- .terms = NULL, ++ .terms = NULL, ++ .stoken = PE_START_TERMS, + }; + int ret; + +- ret = parse_events__scanner(str, &parse_state, PE_START_TERMS); ++ ret = parse_events__scanner(str, &parse_state); + if (!ret) { + list_splice(parse_state.terms, terms); + zfree(&parse_state.terms); +@@ -1872,10 +1874,11 @@ int parse_events(struct perf_evlist *evlist, const char *str, + .idx = evlist->nr_entries, + .error = err, + .evlist = evlist, ++ .stoken = PE_START_EVENTS, + }; + int ret; + +- ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS); ++ ret = parse_events__scanner(str, &parse_state); + perf_pmu__parse_cleanup(); + + if (!ret && list_empty(&parse_state.list)) { +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 52be0b3b26f7..306f636aad96 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -119,6 +119,7 @@ struct parse_events_state { + struct parse_events_error *error; + struct perf_evlist *evlist; + struct list_head *terms; ++ int stoken; + }; + + void parse_events__shrink_config_terms(void); +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index e7f00b5c123d..15ac319d94fa 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -209,10 +209,10 @@ modifier_bp [rwx]{1,3} + %% + + %{ +- { +- int start_token; ++ struct parse_events_state *_parse_state = parse_events_get_extra(yyscanner); + +- start_token = parse_events_get_extra(yyscanner); ++ { ++ int start_token = _parse_state->stoken; + + if (start_token == PE_START_TERMS) + BEGIN(config); +@@ -220,7 +220,7 @@ modifier_bp [rwx]{1,3} + BEGIN(event); + + if (start_token) { +- parse_events_set_extra(NULL, yyscanner); ++ _parse_state->stoken = 0; + /* + * The flex parser does not init locations variable + * via the scan_string interface, so we need do the +-- +2.27.0 + diff --git a/patches/0207-perf-tools-Fix-term-parsing-for-raw-syntax.patch b/patches/0207-perf-tools-Fix-term-parsing-for-raw-syntax.patch new file mode 100644 index 0000000..4bb0be5 --- /dev/null +++ b/patches/0207-perf-tools-Fix-term-parsing-for-raw-syntax.patch @@ -0,0 +1,217 @@ +From dd55ddc72730188206769fd3a43738f50919109f Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 26 Jul 2020 09:52:44 +0200 +Subject: [PATCH 090/201] perf tools: Fix term parsing for raw syntax + +mainline inclusion +from mainline-v5.9-rc1 +commit 4929e95a1400e45b4b5a87fd3ce10273444187d4 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4929e95a1400e45b4b5a87fd3ce10273444187d4 + +---------------------------------------------------------------------- + +Jin Yao reported issue with possible conflict between raw events and +term values in pmu event syntax. + +Currently following syntax is resolved as raw event with 0xead value: + + uncore_imc_free_running/read/ + +instead of using 'read' term from uncore_imc_free_running pmu, because +'read' is correct raw event syntax with 0xead value. + +To solve this issue we do following: + + - check existing terms during rXXXX syntax processing + and make them priority in case of conflict + + - allow pmu/r0x1234/ syntax to be able to specify conflicting + raw event (implemented in previous patch) + +Also add automated tests for this and perf_pmu__parse_cleanup call to +parse_events_terms, so the test gets properly cleaned up. + +Fixes: 3a6c51e4d66c ("perf parser: Add support to specify rXXX event with pmu") +Reported-by: Jin Yao +Signed-off-by: Jiri Olsa +Tested-by: Jin Yao +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Richter +Link: http://lore.kernel.org/lkml/20200726075244.1191481-2-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-events.c | 37 ++++++++++++++++++++++++++++++++- + tools/perf/util/parse-events.c | 28 +++++++++++++++++++++++++ + tools/perf/util/parse-events.h | 2 ++ + tools/perf/util/parse-events.l | 19 ++++++++++------- + 4 files changed, 77 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c +index 95cdc0d01a19..4ca5e569a05f 100644 +--- a/tools/perf/tests/parse-events.c ++++ b/tools/perf/tests/parse-events.c +@@ -631,6 +631,34 @@ static int test__checkterms_simple(struct list_head *terms) + TEST_ASSERT_VAL("wrong val", term->val.num == 1); + TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask")); + ++ /* ++ * read ++ * ++ * The perf_pmu__test_parse_init injects 'read' term into ++ * perf_pmu_events_list, so 'read' is evaluated as read term ++ * and not as raw event with 'ead' hex value. ++ */ ++ term = list_entry(term->list.next, struct parse_events_term, list); ++ TEST_ASSERT_VAL("wrong type term", ++ term->type_term == PARSE_EVENTS__TERM_TYPE_USER); ++ TEST_ASSERT_VAL("wrong type val", ++ term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); ++ TEST_ASSERT_VAL("wrong val", term->val.num == 1); ++ TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "read")); ++ ++ /* ++ * r0xead ++ * ++ * To be still able to pass 'ead' value with 'r' syntax, ++ * we added support to parse 'r0xHEX' event. ++ */ ++ term = list_entry(term->list.next, struct parse_events_term, list); ++ TEST_ASSERT_VAL("wrong type term", ++ term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG); ++ TEST_ASSERT_VAL("wrong type val", ++ term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); ++ TEST_ASSERT_VAL("wrong val", term->val.num == 0xead); ++ TEST_ASSERT_VAL("wrong config", !term->config); + return 0; + } + +@@ -1781,7 +1809,7 @@ struct terms_test { + + static struct terms_test test__terms[] = { + [0] = { +- .str = "config=10,config1,config2=3,umask=1", ++ .str = "config=10,config1,config2=3,umask=1,read,r0xead", + .check = test__checkterms_simple, + }, + }; +@@ -1840,6 +1868,13 @@ static int test_term(struct terms_test *t) + + INIT_LIST_HEAD(&terms); + ++ /* ++ * The perf_pmu__test_parse_init prepares perf_pmu_events_list ++ * which gets freed in parse_events_terms. ++ */ ++ if (perf_pmu__test_parse_init()) ++ return -1; ++ + ret = parse_events_terms(&terms, t->str); + if (ret) { + pr_debug("failed to parse terms '%s', err %d\n", +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 67ae5069737b..328d133933bf 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -1796,6 +1796,32 @@ static void perf_pmu__parse_init(void) + perf_pmu__parse_cleanup(); + } + ++/* ++ * This function injects special term in ++ * perf_pmu_events_list so the test code ++ * can check on this functionality. ++ */ ++int perf_pmu__test_parse_init(void) ++{ ++ struct perf_pmu_event_symbol *list; ++ ++ list = malloc(sizeof(*list) * 1); ++ if (!list) ++ return -ENOMEM; ++ ++ list->type = PMU_EVENT_SYMBOL; ++ list->symbol = strdup("read"); ++ ++ if (!list->symbol) { ++ free(list); ++ return -ENOMEM; ++ } ++ ++ perf_pmu_events_list = list; ++ perf_pmu_events_list_num = 1; ++ return 0; ++} ++ + enum perf_pmu_event_symbol_type + perf_pmu__parse_check(const char *name) + { +@@ -1856,6 +1882,8 @@ int parse_events_terms(struct list_head *terms, const char *str) + int ret; + + ret = parse_events__scanner(str, &parse_state); ++ perf_pmu__parse_cleanup(); ++ + if (!ret) { + list_splice(parse_state.terms, terms); + zfree(&parse_state.terms); +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 306f636aad96..28af56c9939f 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -237,4 +237,6 @@ static inline bool is_sdt_event(char *str __maybe_unused) + } + #endif /* HAVE_LIBELF_SUPPORT */ + ++int perf_pmu__test_parse_init(void); ++ + #endif /* __PERF_PARSE_EVENTS_H */ +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index 15ac319d94fa..1ff9f8805410 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -41,14 +41,6 @@ static int value(yyscan_t scanner, int base) + return __value(yylval, text, base, PE_VALUE); + } + +-static int raw(yyscan_t scanner) +-{ +- YYSTYPE *yylval = parse_events_get_lval(scanner); +- char *text = parse_events_get_text(scanner); +- +- return __value(yylval, text + 1, 16, PE_RAW); +-} +- + static int str(yyscan_t scanner, int token) + { + YYSTYPE *yylval = parse_events_get_lval(scanner); +@@ -72,6 +64,17 @@ static int str(yyscan_t scanner, int token) + return token; + } + ++static int raw(yyscan_t scanner) ++{ ++ YYSTYPE *yylval = parse_events_get_lval(scanner); ++ char *text = parse_events_get_text(scanner); ++ ++ if (perf_pmu__parse_check(text) == PMU_EVENT_SYMBOL) ++ return str(scanner, PE_NAME); ++ ++ return __value(yylval, text + 1, 16, PE_RAW); ++} ++ + static bool isbpf_suffix(char *text) + { + int len = strlen(text); +-- +2.27.0 + diff --git a/patches/0208-perf-tools-Add-fake-pmu-support.patch b/patches/0208-perf-tools-Add-fake-pmu-support.patch new file mode 100644 index 0000000..3b180ca --- /dev/null +++ b/patches/0208-perf-tools-Add-fake-pmu-support.patch @@ -0,0 +1,188 @@ +From cfab54eab73c970afecf43fe5e2126e20caaf27a Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:29 +0200 +Subject: [PATCH 091/201] perf tools: Add fake pmu support + +mainline inclusion +from mainline-v5.9-rc1 +commit 387ad33fe710758a8e1b860819a7452bceb4329a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=387ad33fe710758a8e1b860819a7452bceb4329a + +---------------------------------------------------------------------- + +Add a way to create a pmu event without the actual PMU being in place. + +This way we can test metrics defined for any processor. + +The interface is to define fake_pmu in struct parse_events_state data. +It will be used only in tests via special interface function added in +following changes. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/parse-events.c + tools/perf/util/parse-events.h +--- + tools/perf/util/parse-events.c | 6 ++--- + tools/perf/util/parse-events.h | 1 + + tools/perf/util/parse-events.l | 8 +++++-- + tools/perf/util/parse-events.y | 41 ++++++++++++++++++++++++++++++++-- + 4 files changed, 49 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 328d133933bf..f3fe4ed4a9ea 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -1266,7 +1266,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, + bool use_uncore_alias; + LIST_HEAD(config_terms); + +- pmu = perf_pmu__find(name); ++ pmu = parse_state->fake_pmu ?: perf_pmu__find(name); + if (!pmu) { + if (asprintf(&err->str, + "Cannot find PMU `%s'. Missing kernel support?", +@@ -1297,7 +1297,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, + } + } + +- if (perf_pmu__check_alias(pmu, head_config, &info)) ++ if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) + return -EINVAL; + + /* +@@ -1310,7 +1310,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, + if (get_config_terms(head_config, &config_terms)) + return -ENOMEM; + +- if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { ++ if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + struct perf_evsel_config_term *pos, *tmp; + + list_for_each_entry_safe(pos, tmp, &config_terms, list) { +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index 28af56c9939f..c78809837f29 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -120,6 +120,7 @@ struct parse_events_state { + struct perf_evlist *evlist; + struct list_head *terms; + int stoken; ++ struct perf_pmu *fake_pmu; + }; + + void parse_events__shrink_config_terms(void); +diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l +index 1ff9f8805410..83ccfea42e9b 100644 +--- a/tools/perf/util/parse-events.l ++++ b/tools/perf/util/parse-events.l +@@ -132,12 +132,16 @@ do { \ + yyless(0); \ + } while (0) + +-static int pmu_str_check(yyscan_t scanner) ++static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state) + { + YYSTYPE *yylval = parse_events_get_lval(scanner); + char *text = parse_events_get_text(scanner); + + yylval->str = strdup(text); ++ ++ if (parse_state->fake_pmu) ++ return PE_PMU_EVENT_FAKE; ++ + switch (perf_pmu__parse_check(text)) { + case PMU_EVENT_SYMBOL_PREFIX: + return PE_PMU_EVENT_PRE; +@@ -372,7 +376,7 @@ r{num_raw_hex} { return raw(yyscanner); } + {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } + {bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } + {bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } +-{name} { return pmu_str_check(yyscanner); } ++{name} { return pmu_str_check(yyscanner, _parse_state); } + {name_tag} { return str(yyscanner, PE_NAME); } + "/" { BEGIN(config); return '/'; } + - { return '-'; } +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index ff913778a7d4..f03da974770c 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -59,7 +59,7 @@ static void inc_group_count(struct list_head *list, + %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT + %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP + %token PE_ERROR +-%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT ++%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE + %token PE_ARRAY_ALL PE_ARRAY_RANGE + %token PE_DRV_CFG_TERM + %type PE_VALUE +@@ -76,7 +76,7 @@ static void inc_group_count(struct list_head *list, + %type PE_MODIFIER_EVENT + %type PE_MODIFIER_BP + %type PE_EVENT_NAME +-%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT ++%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE + %type PE_DRV_CFG_TERM + %type value_sym + %type event_config +@@ -301,6 +301,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc + YYABORT; + $$ = list; + } ++| ++PE_PMU_EVENT_FAKE sep_dc ++{ ++ struct list_head *list; ++ int err; ++ ++ list = alloc_list(); ++ if (!list) ++ YYABORT; ++ ++ err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); ++ free($1); ++ if (err < 0) { ++ free(list); ++ YYABORT; ++ } ++ $$ = list; ++} ++| ++PE_PMU_EVENT_FAKE opt_pmu_config ++{ ++ struct list_head *list; ++ int err; ++ ++ list = alloc_list(); ++ if (!list) ++ YYABORT; ++ ++ err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); ++ free($1); ++ parse_events_terms__delete($2); ++ if (err < 0) { ++ free(list); ++ YYABORT; ++ } ++ $$ = list; ++} + + value_sym: + PE_VALUE_SYM_HW +-- +2.27.0 + diff --git a/patches/0209-perf-tests-Factor-check_parse_id-function.patch b/patches/0209-perf-tests-Factor-check_parse_id-function.patch new file mode 100644 index 0000000..72b4459 --- /dev/null +++ b/patches/0209-perf-tests-Factor-check_parse_id-function.patch @@ -0,0 +1,99 @@ +From e55faa87583d6afabe8506954c5f0ace70c5051a Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:31 +0200 +Subject: [PATCH 092/201] perf tests: Factor check_parse_id function + +mainline inclusion +from mainline-v5.9-rc1 +commit 34bacc9578de2893ab6301cea89ea001d8e4cf5b +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34bacc9578de2893ab6301cea89ea001d8e4cf5b + +---------------------------------------------------------------------- + +Separating the generic part of check_parse_id function, +so it can be used in following changes for the new test. + +Committer notes: + +Fix this error: + + tests/pmu-events.c:413:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] + struct parse_events_error error = { 0 }; + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-4-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/pmu-events.c +--- + tools/perf/tests/pmu-events.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 41dab7e36761..7269bdeeda2c 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -390,9 +390,8 @@ static bool is_number(const char *str) + return errno == 0 && end_ptr != str; + } + +-static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) ++static int check_parse_id(const char *id, struct parse_events_error *error) + { +- struct parse_events_error error; + struct perf_evlist *evlist; + int ret; + +@@ -401,8 +400,18 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) + return 0; + + evlist = perf_evlist__new(); +- memset(&error, 0, sizeof(error)); +- ret = parse_events(evlist, id, &error); ++ if (!evlist) ++ return -ENOMEM; ++ ret = parse_events(evlist, id, error); ++ perf_evlist__delete(evlist); ++ return ret; ++} ++ ++static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) ++{ ++ struct parse_events_error error = { .idx = 0, }; ++ ++ int ret = check_parse_id(id, &error); + if (ret && same_cpu) { + pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", + pe->metric_name, id, pe->metric_expr); +@@ -413,7 +422,6 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) + id, pe->metric_name, pe->metric_expr); + ret = 0; + } +- perf_evlist__delete(evlist); + free(error.str); + free(error.help); + return ret; +@@ -472,7 +480,7 @@ static int test_parsing(void) + expr__add_id(&ctx, strdup(cur->key), k++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { +- if (check_parse_id(cur->key, map == cpus_map, ++ if (check_parse_cpu(cur->key, map == cpus_map, + pe)) + ret++; + } +-- +2.27.0 + diff --git a/patches/0210-perf-parse-Provide-a-way-to-pass-a-fake_pmu-to-parse.patch b/patches/0210-perf-parse-Provide-a-way-to-pass-a-fake_pmu-to-parse.patch new file mode 100644 index 0000000..3831a8f --- /dev/null +++ b/patches/0210-perf-parse-Provide-a-way-to-pass-a-fake_pmu-to-parse.patch @@ -0,0 +1,110 @@ +From 42dc1676164d4ab890ebe2cf704136e49429ad00 Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Wed, 3 Jun 2020 12:32:55 -0300 +Subject: [PATCH 093/201] perf parse: Provide a way to pass a fake_pmu to + parse_events() + +mainline inclusion +from mainline-v5.9-rc1 +commit 3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f + +---------------------------------------------------------------------- + +This is an alternative patch to what Jiri sent that instead of changing +all callers to parse_events() for allowing to pass a fake_pmu, provide +another function specifically for that. + +From Jiri's patch: + +This way it's possible to parse events from PMUs which are not present +in the system. It's available only for testing purposes coming in +following changes, so all the current users set fake_pmu argument as +false. + +Based-on-a-patch-by: Jiri Olsa +Link: http://lore.kernel.org/lkml/20200602214741.1218986-3-jolsa@kernel.org +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/parse-events.c + tools/perf/util/parse-events.h +--- + tools/perf/util/parse-events.c | 15 ++++++++------- + tools/perf/util/parse-events.h | 12 ++++++++++-- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index f3fe4ed4a9ea..b96fe0525b1b 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -1894,15 +1894,16 @@ int parse_events_terms(struct list_head *terms, const char *str) + return ret; + } + +-int parse_events(struct perf_evlist *evlist, const char *str, +- struct parse_events_error *err) ++int __parse_events(struct perf_evlist *evlist, const char *str, ++ struct parse_events_error *err, struct perf_pmu *fake_pmu) + { + struct parse_events_state parse_state = { +- .list = LIST_HEAD_INIT(parse_state.list), +- .idx = evlist->nr_entries, +- .error = err, +- .evlist = evlist, +- .stoken = PE_START_EVENTS, ++ .list = LIST_HEAD_INIT(parse_state.list), ++ .idx = evlist->nr_entries, ++ .error = err, ++ .evlist = evlist, ++ .stoken = PE_START_EVENTS, ++ .fake_pmu = fake_pmu, + }; + int ret; + +diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h +index c78809837f29..ffe0c04c6cdb 100644 +--- a/tools/perf/util/parse-events.h ++++ b/tools/perf/util/parse-events.h +@@ -17,6 +17,7 @@ struct perf_evlist; + struct parse_events_error; + + struct option; ++struct perf_pmu; + + struct tracepoint_path { + char *system; +@@ -31,8 +32,15 @@ bool have_tracepoints(struct list_head *evlist); + const char *event_type(int type); + + int parse_events_option(const struct option *opt, const char *str, int unset); +-int parse_events(struct perf_evlist *evlist, const char *str, +- struct parse_events_error *error); ++int __parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *error, ++ struct perf_pmu *fake_pmu); ++ ++static inline int parse_events(struct perf_evlist *evlist, const char *str, ++ struct parse_events_error *err) ++{ ++ return __parse_events(evlist, str, err, NULL); ++} ++ + int parse_events_terms(struct list_head *terms, const char *str); + int parse_filter(const struct option *opt, const char *str, int unset); + int exclude_perf(const struct option *opt, const char *arg, int unset); +-- +2.27.0 + diff --git a/patches/0211-perf-pmu-Add-a-perf_pmu__fake-object-to-use-with-__p.patch b/patches/0211-perf-pmu-Add-a-perf_pmu__fake-object-to-use-with-__p.patch new file mode 100644 index 0000000..d7d9744 --- /dev/null +++ b/patches/0211-perf-pmu-Add-a-perf_pmu__fake-object-to-use-with-__p.patch @@ -0,0 +1,63 @@ +From 5f51ac014c4ff646e1347b1e3dd7a8ee1419c23a Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Tue, 9 Jun 2020 13:23:24 -0300 +Subject: [PATCH 094/201] perf pmu: Add a perf_pmu__fake object to use with + __parse_events() + +mainline inclusion +from mainline-v5.9-rc1 +commit e46fc8d9dd352c88fec49b140008958d2dc1efe1 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e46fc8d9dd352c88fec49b140008958d2dc1efe1 + +---------------------------------------------------------------------- + +When wanting to use the support in __parse_events() for fake pmus, just +pass it. + +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 2 ++ + tools/perf/util/pmu.h | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 7eefbebbf990..7217b8fac00d 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -21,6 +21,8 @@ + #include "cache.h" + #include "string2.h" + ++struct perf_pmu perf_pmu__fake; ++ + struct perf_pmu_format { + char *name; + int value; +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 79f167db4a33..c44c4a701bf4 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -33,6 +33,8 @@ struct perf_pmu { + int (*set_drv_config) (struct perf_evsel_config_term *term); + }; + ++extern struct perf_pmu perf_pmu__fake; ++ + struct perf_pmu_info { + const char *unit; + const char *metric_expr; +-- +2.27.0 + diff --git a/patches/0212-perf-tests-Add-another-metric-parsing-test.patch b/patches/0212-perf-tests-Add-another-metric-parsing-test.patch new file mode 100644 index 0000000..86387a1 --- /dev/null +++ b/patches/0212-perf-tests-Add-another-metric-parsing-test.patch @@ -0,0 +1,252 @@ +From a19b089ceb882c3e227f45080a2047c2b1744acd Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Wed, 3 Jun 2020 12:51:15 -0300 +Subject: [PATCH 095/201] perf tests: Add another metric parsing test + +mainline inclusion +from mainline-v5.9-rc1 +commit e1c92a7fbbc5668510736624df3028accd6af0ea +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e1c92a7fbbc5668510736624df3028accd6af0ea + +---------------------------------------------------------------------- + +The test goes through all metrics compiled for arch within pmu events +and try to parse them. + +This test is different from 'test_parsing' in that we go through all the +events in the current arch, not just one defined for current CPU model. +Using 'fake_pmu' to parse events which do not have PMUs defined in the +system. + +Say there's bad change in ivybridge metrics file, like: + + - a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + + b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + @@ -8,7 +8,7 @@ + - "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * (( + + "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 * + +the test fails with (on my kabylake laptop): + + $ perf test 'Parsing of PMU event table metrics with fake PMUs' -v + parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh... + syntax error, line 1 + expr__parse failed + test child finished with -1 + ... + +The test also defines its own list of metrics and tries to parse them. +It's handy for developing. + +Committer notes: + +Testing it: + + $ perf test fake + 10: PMU events : + 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! + $ perf test -v fake |& tail + parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.' + parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.' + parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.' + parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.' + parsing 'idq_uops_not_delivered.core / * (4 * cycles)' + syntax error + expr__parse failed + test child finished with -1 + ---- end ---- + PMU events subtest 4: FAILED! + $ + +And fix this error: + + tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] + struct parse_events_error error = { 0 }; + +Signed-off-by: Jiri Olsa +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/pmu-events.c +--- + tools/perf/tests/pmu-events.c | 115 +++++++++++++++++++++++++++++++++- + 1 file changed, 112 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 7269bdeeda2c..0a6611d8ec32 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -390,7 +390,8 @@ static bool is_number(const char *str) + return errno == 0 && end_ptr != str; + } + +-static int check_parse_id(const char *id, struct parse_events_error *error) ++static int check_parse_id(const char *id, struct parse_events_error *error, ++ struct perf_pmu *fake_pmu) + { + struct perf_evlist *evlist; + int ret; +@@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error) + evlist = perf_evlist__new(); + if (!evlist) + return -ENOMEM; +- ret = parse_events(evlist, id, error); ++ ret = __parse_events(evlist, id, error, fake_pmu); + perf_evlist__delete(evlist); + return ret; + } +@@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) + { + struct parse_events_error error = { .idx = 0, }; + +- int ret = check_parse_id(id, &error); ++ int ret = check_parse_id(id, &error, NULL); + if (ret && same_cpu) { + pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", + pe->metric_name, id, pe->metric_expr); +@@ -427,6 +428,16 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) + return ret; + } + ++static int check_parse_fake(const char *id) ++{ ++ struct parse_events_error error = { .idx = 0, }; ++ int ret = check_parse_id(id, &error, &perf_pmu__fake); ++ ++ free(error.str); ++ free(error.help); ++ return ret; ++} ++ + static void expr_failure(const char *msg, + const struct pmu_events_map *map, + const struct pmu_event *pe) +@@ -496,6 +507,100 @@ static int test_parsing(void) + return ret == 0 ? TEST_OK : TEST_SKIP; + } + ++struct test_metric { ++ const char *str; ++}; ++ ++static struct test_metric metrics[] = { ++ { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, ++ { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, ++ { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, ++ { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, ++ { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, ++}; ++ ++static int metric_parse_fake(const char *str) ++{ ++ struct expr_parse_ctx ctx; ++ struct hashmap_entry *cur; ++ double result; ++ int ret = -1; ++ size_t bkt; ++ int i; ++ ++ pr_debug("parsing '%s'\n", str); ++ ++ expr__ctx_init(&ctx); ++ if (expr__find_other(str, NULL, &ctx, 0) < 0) { ++ pr_err("expr__find_other failed\n"); ++ return -1; ++ } ++ ++ /* ++ * Add all ids with a made up value. The value may ++ * trigger divide by zero when subtracted and so try to ++ * make them unique. ++ */ ++ i = 1; ++ hashmap__for_each_entry((&ctx.ids), cur, bkt) ++ expr__add_id(&ctx, strdup(cur->key), i++); ++ ++ hashmap__for_each_entry((&ctx.ids), cur, bkt) { ++ if (check_parse_fake(cur->key)) { ++ pr_err("check_parse_fake failed\n"); ++ goto out; ++ } ++ } ++ ++ if (expr__parse(&result, &ctx, str, 1)) ++ pr_err("expr__parse failed\n"); ++ else ++ ret = 0; ++ ++out: ++ expr__ctx_clear(&ctx); ++ return ret; ++} ++ ++/* ++ * Parse all the metrics for current architecture, ++ * or all defined cpus via the 'fake_pmu' ++ * in parse_events. ++ */ ++static int test_parsing_fake(void) ++{ ++ struct pmu_events_map *map; ++ struct pmu_event *pe; ++ unsigned int i, j; ++ int err = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(metrics); i++) { ++ err = metric_parse_fake(metrics[i].str); ++ if (err) ++ return err; ++ } ++ ++ i = 0; ++ for (;;) { ++ map = &pmu_events_map[i++]; ++ if (!map->table) ++ break; ++ j = 0; ++ for (;;) { ++ pe = &map->table[j++]; ++ if (!pe->name && !pe->metric_group && !pe->metric_name) ++ break; ++ if (!pe->metric_expr) ++ continue; ++ err = metric_parse_fake(pe->metric_expr); ++ if (err) ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ + static const struct { + int (*func)(void); + const char *desc; +@@ -512,6 +617,10 @@ static const struct { + .func = test_parsing, + .desc = "Parsing of PMU event table metrics", + }, ++ { ++ .func = test_parsing_fake, ++ .desc = "Parsing of PMU event table metrics with fake PMUs", ++ }, + }; + + const char *test__pmu_events_subtest_get_desc(int subtest) +-- +2.27.0 + diff --git a/patches/0213-perf-parse-Factor-out-parse_groups-function.patch b/patches/0213-perf-parse-Factor-out-parse_groups-function.patch new file mode 100644 index 0000000..8d71972 --- /dev/null +++ b/patches/0213-perf-parse-Factor-out-parse_groups-function.patch @@ -0,0 +1,78 @@ +From f86993e23c3bc1178c82ef5e361484dfc30456ff Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:33 +0200 +Subject: [PATCH 096/201] perf parse: Factor out parse_groups() function + +mainline inclusion +from mainline-v5.9-rc1 +commit 8b4468a2107af32b796fa818e5fb76481c39ee5a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8b4468a2107af32b796fa818e5fb76481c39ee5a + +---------------------------------------------------------------------- + +Factor out the parse_groups function, it will be used for new test +interface coming in following changes. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 8fa4b98f6231..d2f54aa12b33 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -716,14 +716,12 @@ static void metricgroup__free_egroups(struct list_head *group_list) + } + } + +-int metricgroup__parse_groups(const struct option *opt, +- const char *str, +- bool metric_no_group, +- bool metric_no_merge, +- struct rblist *metric_events) ++static int parse_groups(struct perf_evlist *perf_evlist, const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events) + { + struct parse_events_error parse_error; +- struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; + struct strbuf extra_events; + LIST_HEAD(group_list); + int ret; +@@ -749,6 +747,18 @@ int metricgroup__parse_groups(const struct option *opt, + return ret; + } + ++int metricgroup__parse_groups(const struct option *opt, ++ const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events) ++{ ++ struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; ++ ++ return parse_groups(perf_evlist, str, metric_no_group, ++ metric_no_merge, metric_events); ++} ++ + bool metricgroup__has_metric(const char *metric) + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); +-- +2.27.0 + diff --git a/patches/0214-perf-tools-Add-fake_pmu-to-parse_group-function.patch b/patches/0214-perf-tools-Add-fake_pmu-to-parse_group-function.patch new file mode 100644 index 0000000..5895fdd --- /dev/null +++ b/patches/0214-perf-tools-Add-fake_pmu-to-parse_group-function.patch @@ -0,0 +1,74 @@ +From 28ba4a7842588c0d3daf91b8e910d04f72f20c26 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 9 Jun 2020 12:50:42 -0300 +Subject: [PATCH 097/201] perf tools: Add fake_pmu to parse_group() function + +mainline inclusion +from mainline-v5.9-rc1 +commit 68173bda6ac9d498e450276323f1c10a1d0307ad +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=68173bda6ac9d498e450276323f1c10a1d0307ad + +---------------------------------------------------------------------- + +Allow to pass fake_pmu in parse_groups function so it can be used in +parse_events call. + +It's will be passed by the upcoming metricgroup__parse_groups_test +function. + +Committer notes: + +Made it a 'struct perf_pmu' pointer, in line with the changes at the +start of this patchkit to avoid statics deep down in library code. + +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ingo Molnar +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index d2f54aa12b33..9fa47eb1b968 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -719,6 +719,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) + static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, ++ struct perf_pmu *fake_pmu, + struct rblist *metric_events) + { + struct parse_events_error parse_error; +@@ -734,7 +735,7 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + return ret; + pr_debug("adding %s\n", extra_events.buf); + memset(&parse_error, 0, sizeof(struct parse_events_error)); +- ret = parse_events(perf_evlist, extra_events.buf, &parse_error); ++ ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); + if (ret) { + parse_events_print_error(&parse_error, extra_events.buf); + goto out; +@@ -756,7 +757,7 @@ int metricgroup__parse_groups(const struct option *opt, + struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; + + return parse_groups(perf_evlist, str, metric_no_group, +- metric_no_merge, metric_events); ++ metric_no_merge, NULL, metric_events); + } + + bool metricgroup__has_metric(const char *metric) +-- +2.27.0 + diff --git a/patches/0215-perf-tools-Add-map-to-parse_groups-function.patch b/patches/0215-perf-tools-Add-map-to-parse_groups-function.patch new file mode 100644 index 0000000..712993d --- /dev/null +++ b/patches/0215-perf-tools-Add-map-to-parse_groups-function.patch @@ -0,0 +1,116 @@ +From 7d56affe37448a05c6dc70ea14dd25980bf90a97 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 9 Jun 2020 12:57:47 -0300 +Subject: [PATCH 098/201] perf tools: Add map to parse_groups() function + +mainline inclusion +from mainline-v5.9-rc1 +commit 1381396b0b778c918bf191b1960f92fbd563476d +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1381396b0b778c918bf191b1960f92fbd563476d + +---------------------------------------------------------------------- + +For testing purposes we need to pass our own map of events from +parse_groups() through metricgroup__add_metric. + +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ingo Molnar +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-8-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 9fa47eb1b968..b3feb3b5cd99 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -604,17 +604,14 @@ static int __metricgroup__add_metric(struct list_head *group_list, + + static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct strbuf *events, +- struct list_head *group_list) ++ struct list_head *group_list, ++ struct pmu_events_map *map) + { +- struct pmu_events_map *map = perf_pmu__find_map(NULL); + struct pmu_event *pe; + struct egroup *eg; + int i, ret; + bool has_match = false; + +- if (!map) +- return 0; +- + for (i = 0; ; i++) { + pe = &map->table[i]; + +@@ -675,7 +672,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + + static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + struct strbuf *events, +- struct list_head *group_list) ++ struct list_head *group_list, ++ struct pmu_events_map *map) + { + char *llist, *nlist, *p; + int ret = -EINVAL; +@@ -690,7 +688,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + + while ((p = strsep(&llist, ",")) != NULL) { + ret = metricgroup__add_metric(p, metric_no_group, events, +- group_list); ++ group_list, map); + if (ret == -EINVAL) { + fprintf(stderr, "Cannot find metric or group `%s'\n", + p); +@@ -720,7 +718,8 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, + struct perf_pmu *fake_pmu, +- struct rblist *metric_events) ++ struct rblist *metric_events, ++ struct pmu_events_map *map) + { + struct parse_events_error parse_error; + struct strbuf extra_events; +@@ -730,7 +729,7 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + if (metric_events->nr_entries == 0) + metricgroup__rblist_init(metric_events); + ret = metricgroup__add_metric_list(str, metric_no_group, +- &extra_events, &group_list); ++ &extra_events, &group_list, map); + if (ret) + return ret; + pr_debug("adding %s\n", extra_events.buf); +@@ -755,9 +754,13 @@ int metricgroup__parse_groups(const struct option *opt, + struct rblist *metric_events) + { + struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; ++ struct pmu_events_map *map = perf_pmu__find_map(NULL); ++ ++ if (!map) ++ return 0; + + return parse_groups(perf_evlist, str, metric_no_group, +- metric_no_merge, NULL, metric_events); ++ metric_no_merge, NULL, metric_events, map); + } + + bool metricgroup__has_metric(const char *metric) +-- +2.27.0 + diff --git a/patches/0216-perf-tools-Add-metricgroup__parse_groups_test-functi.patch b/patches/0216-perf-tools-Add-metricgroup__parse_groups_test-functi.patch new file mode 100644 index 0000000..e28cc27 --- /dev/null +++ b/patches/0216-perf-tools-Add-metricgroup__parse_groups_test-functi.patch @@ -0,0 +1,89 @@ +From dcedd111e3843d6b47fb723282481c8cf1cce769 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:36 +0200 +Subject: [PATCH 099/201] perf tools: Add metricgroup__parse_groups_test + function + +mainline inclusion +from mainline-v5.9-rc1 +commit f78ac00a8c999f4418e69e606485784fc5ff1d09 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f78ac00a8c999f4418e69e606485784fc5ff1d09 + +---------------------------------------------------------------------- + +Add the metricgroup__parse_groups_test function. It will be used as +test's interface to metric parsing in following changes. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-9-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 11 +++++++++++ + tools/perf/util/metricgroup.h | 9 +++++++++ + 2 files changed, 20 insertions(+) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index b3feb3b5cd99..5058db5810aa 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -763,6 +763,17 @@ int metricgroup__parse_groups(const struct option *opt, + metric_no_merge, NULL, metric_events, map); + } + ++int metricgroup__parse_groups_test(struct perf_evlist *evlist, ++ struct pmu_events_map *map, ++ const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events) ++{ ++ return parse_groups(evlist, str, metric_no_group, ++ metric_no_merge, &perf_pmu__fake, metric_events, map); ++} ++ + bool metricgroup__has_metric(const char *metric) + { + struct pmu_events_map *map = perf_pmu__find_map(NULL); +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index b6dfd7d09b9c..11811764edde 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -7,8 +7,10 @@ + #include + + struct perf_evsel; ++struct perf_evlist; + struct option; + struct rblist; ++struct pmu_events_map; + + struct metric_event { + struct rb_node nd; +@@ -34,6 +36,13 @@ int metricgroup__parse_groups(const struct option *opt, + bool metric_no_merge, + struct rblist *metric_events); + ++int metricgroup__parse_groups_test(struct perf_evlist *evlist, ++ struct pmu_events_map *map, ++ const char *str, ++ bool metric_no_group, ++ bool metric_no_merge, ++ struct rblist *metric_events); ++ + void metricgroup__print(bool metrics, bool groups, char *filter, + bool raw, bool details); + bool metricgroup__has_metric(const char *metric); +-- +2.27.0 + diff --git a/patches/0217-perf-tools-Factor-out-prepare_metric-function.patch b/patches/0217-perf-tools-Factor-out-prepare_metric-function.patch new file mode 100644 index 0000000..a1de9c8 --- /dev/null +++ b/patches/0217-perf-tools-Factor-out-prepare_metric-function.patch @@ -0,0 +1,123 @@ +From d7551f1a5c8ab7e70a096147d7c7000e921fad06 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:37 +0200 +Subject: [PATCH 100/201] perf tools: Factor out prepare_metric function + +mainline inclusion +from mainline-v5.9-rc1 +commit 2cfaa853d8ead2fe4cd82986163b5cea21e300bd +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2cfaa853d8ead2fe4cd82986163b5cea21e300bd + +---------------------------------------------------------------------- + +Factoring out prepare_metric function so it can be used in test +interface coming in following changes. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-10-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/stat-shadow.c +--- + tools/perf/util/stat-shadow.c | 53 ++++++++++++++++++++++------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 40af5b4feb00..c686b8dc3cd7 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -730,25 +730,16 @@ static void print_smi_cost(struct perf_stat_config *config, + out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); + } + +-static void generic_metric(struct perf_stat_config *config, +- const char *metric_expr, +- struct perf_evsel **metric_events, +- char *name, +- const char *metric_name, +- const char *metric_unit, +- int runtime, +- int cpu, +- struct perf_stat_output_ctx *out, +- struct runtime_stat *st) ++static int prepare_metric(struct perf_evsel **metric_events, ++ struct expr_parse_ctx *pctx, ++ int cpu, ++ struct runtime_stat *st) + { +- print_metric_t print_metric = out->print_metric; +- struct expr_parse_ctx pctx; +- double ratio, scale; +- int i; +- void *ctxp = out->ctx; ++ double scale; + char *n, *pn; ++ int i; + +- expr__ctx_init(&pctx); ++ expr__ctx_init(pctx); + for (i = 0; metric_events[i]; i++) { + struct saved_value *v; + struct stats *stats; +@@ -771,7 +762,7 @@ static void generic_metric(struct perf_stat_config *config, + + n = strdup(metric_events[i]->name); + if (!n) +- return; ++ return -ENOMEM; + /* + * This display code with --no-merge adds [cpu] postfixes. + * These are not supported by the parser. Remove everything +@@ -782,11 +773,35 @@ static void generic_metric(struct perf_stat_config *config, + *pn = 0; + + if (metric_total) +- expr__add_id(&pctx, n, metric_total); ++ expr__add_id(pctx, n, metric_total); + else +- expr__add_id(&pctx, n, avg_stats(stats)*scale); ++ expr__add_id(pctx, n, avg_stats(stats)*scale); + } + ++ return i; ++} ++ ++static void generic_metric(struct perf_stat_config *config, ++ const char *metric_expr, ++ struct perf_evsel **metric_events, ++ char *name, ++ const char *metric_name, ++ const char *metric_unit, ++ int runtime, ++ int cpu, ++ struct perf_stat_output_ctx *out, ++ struct runtime_stat *st) ++{ ++ print_metric_t print_metric = out->print_metric; ++ struct expr_parse_ctx pctx; ++ double ratio, scale; ++ int i; ++ void *ctxp = out->ctx; ++ ++ i = prepare_metric(metric_events, &pctx, cpu, st); ++ if (i < 0) ++ return; ++ + if (!metric_events[i]) { + if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { + char *unit; +-- +2.27.0 + diff --git a/patches/0218-perf-tools-Release-metric_events-rblist.patch b/patches/0218-perf-tools-Release-metric_events-rblist.patch new file mode 100644 index 0000000..9c9d190 --- /dev/null +++ b/patches/0218-perf-tools-Release-metric_events-rblist.patch @@ -0,0 +1,95 @@ +From d148b6f6302f62d71dff7c93a00cb09c4181c88b Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:38 +0200 +Subject: [PATCH 101/201] perf tools: Release metric_events rblist + +mainline inclusion +from mainline-v5.9-rc1 +commit 9afe5658a6fa89f59f01d2857d78203cc8665f1c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9afe5658a6fa89f59f01d2857d78203cc8665f1c + +---------------------------------------------------------------------- + +We don't release metric_events rblist, add the missing delete hook and +call the release before leaving cmd_stat. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-11-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/builtin-stat.c | 1 + + tools/perf/util/metricgroup.c | 19 +++++++++++++++++++ + tools/perf/util/metricgroup.h | 1 + + 3 files changed, 21 insertions(+) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 56f62a9d0f0d..ad81defc42db 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -3180,6 +3180,7 @@ int cmd_stat(int argc, const char **argv) + + perf_evlist__delete(evsel_list); + ++ metricgroup__rblist_exit(&stat_config.metric_events); + runtime_stat_delete(&stat_config); + + return status; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 5058db5810aa..230c6d092ca2 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -82,11 +82,30 @@ static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused, + return &me->nd; + } + ++static void metric_event_delete(struct rblist *rblist __maybe_unused, ++ struct rb_node *rb_node) ++{ ++ struct metric_event *me = container_of(rb_node, struct metric_event, nd); ++ struct metric_expr *expr, *tmp; ++ ++ list_for_each_entry_safe(expr, tmp, &me->head, nd) { ++ free(expr); ++ } ++ ++ free(me); ++} ++ + static void metricgroup__rblist_init(struct rblist *metric_events) + { + rblist__init(metric_events); + metric_events->node_cmp = metric_event_cmp; + metric_events->node_new = metric_event_new; ++ metric_events->node_delete = metric_event_delete; ++} ++ ++void metricgroup__rblist_exit(struct rblist *metric_events) ++{ ++ rblist__exit(metric_events); + } + + struct egroup { +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 11811764edde..c198e2c4a294 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -47,4 +47,5 @@ void metricgroup__print(bool metrics, bool groups, char *filter, + bool raw, bool details); + bool metricgroup__has_metric(const char *metric); + int arch_get_runtimeparam(void); ++void metricgroup__rblist_exit(struct rblist *metric_events); + #endif +-- +2.27.0 + diff --git a/patches/0219-perf-tools-Add-test_generic_metric-function.patch b/patches/0219-perf-tools-Add-test_generic_metric-function.patch new file mode 100644 index 0000000..55d33d5 --- /dev/null +++ b/patches/0219-perf-tools-Add-test_generic_metric-function.patch @@ -0,0 +1,76 @@ +From a1323bf2f13800aab0a3391d792e9ad4ba7bb9f8 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:39 +0200 +Subject: [PATCH 102/201] perf tools: Add test_generic_metric function + +mainline inclusion +from mainline-v5.9-rc1 +commit 6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 + +---------------------------------------------------------------------- + +Adding test_generic_metric that prepares and runs given metric over the +data from struct runtime_stat object. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-12-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/stat.h +--- + tools/perf/util/stat-shadow.c | 14 ++++++++++++++ + tools/perf/util/stat.h | 2 ++ + 2 files changed, 16 insertions(+) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index c686b8dc3cd7..6b259855d5e0 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -839,6 +839,20 @@ static void generic_metric(struct perf_stat_config *config, + expr__ctx_clear(&pctx); + } + ++double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) ++{ ++ struct expr_parse_ctx pctx; ++ double ratio; ++ ++ if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) ++ return 0.; ++ ++ if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) ++ return 0.; ++ ++ return ratio; ++} ++ + void perf_stat__print_shadow_stats(struct perf_stat_config *config, + struct perf_evsel *evsel, + double avg, int cpu, +diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h +index fbbc47ed5d3f..4bb32cf357c6 100644 +--- a/tools/perf/util/stat.h ++++ b/tools/perf/util/stat.h +@@ -177,4 +177,6 @@ int perf_event__process_stat_event(struct perf_tool *tool, + size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); + size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); + size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); ++struct metric_expr; ++double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st); + #endif +-- +2.27.0 + diff --git a/patches/0220-perf-pmu-List-kernel-supplied-event-aliases-for-arm6.patch b/patches/0220-perf-pmu-List-kernel-supplied-event-aliases-for-arm6.patch new file mode 100644 index 0000000..c87e99e --- /dev/null +++ b/patches/0220-perf-pmu-List-kernel-supplied-event-aliases-for-arm6.patch @@ -0,0 +1,66 @@ +From 2ac7b40783b55cb6bef9489062d1812abf1b85da Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 17 Jun 2020 17:01:53 +0800 +Subject: [PATCH 103/201] perf pmu: List kernel supplied event aliases for + arm64 + +mainline inclusion +from mainline-v5.9-rc1 +commit 0a507af9c681ac2adedc5fe1b2d534e27be85446 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0a507af9c681ac2adedc5fe1b2d534e27be85446 + +---------------------------------------------------------------------- + +In commit dc098b35b56f ("perf list: List kernel supplied event aliases"), +the aliases for events are supplied in addition to CPU event in perf list. + +This relies on the name of the core PMU being "cpu", which is not the case +for arm64, so arm64 has always missed this. Use generic is_pmu_core() +helper which takes account of arm64 to make this feature work for arm64 +(and possibly other archs). + +Sample, before: + + armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] + +after: + + br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Acked-by: Namhyung Kim +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1592384514-119954-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 7217b8fac00d..cf1b43bddc85 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -1454,7 +1454,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, + list_for_each_entry(alias, &pmu->aliases, list) { + char *name = alias->desc ? alias->name : + format_alias(buf, sizeof(buf), pmu, alias); +- bool is_cpu = !strcmp(pmu->name, "cpu"); ++ bool is_cpu = is_pmu_core(pmu->name); + + if (alias->deprecated && !deprecated) + continue; +-- +2.27.0 + diff --git a/patches/0221-perf-pmu-Improve-CPU-core-PMU-HW-event-list-ordering.patch b/patches/0221-perf-pmu-Improve-CPU-core-PMU-HW-event-list-ordering.patch new file mode 100644 index 0000000..4600685 --- /dev/null +++ b/patches/0221-perf-pmu-Improve-CPU-core-PMU-HW-event-list-ordering.patch @@ -0,0 +1,194 @@ +From 00c006130c6786f2d48fb38eed1a4297e9d73944 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 17 Jun 2020 17:01:54 +0800 +Subject: [PATCH 104/201] perf pmu: Improve CPU core PMU HW event list ordering + +mainline inclusion +from mainline-v5.9-rc1 +commit 218ca91df47712a7b2b5a554e39c4a2c819a9e86 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=218ca91df47712a7b2b5a554e39c4a2c819a9e86 + +---------------------------------------------------------------------- + +For perf list, the CPU core PMU HW event ordering is such that not all +events may will be listed adjacent - consider this example: + + $ tools/perf/perf list + + List of pre-defined events (to be used in -e): + + duration_time [Tool event] + + branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] + branch-misses OR cpu/branch-misses/ [Kernel PMU event] + bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] + cache-misses OR cpu/cache-misses/ [Kernel PMU event] + cache-references OR cpu/cache-references/ [Kernel PMU event] + cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] + cstate_core/c3-residency/ [Kernel PMU event] + cstate_core/c6-residency/ [Kernel PMU event] + cstate_core/c7-residency/ [Kernel PMU event] + cstate_pkg/c2-residency/ [Kernel PMU event] + cstate_pkg/c3-residency/ [Kernel PMU event] + cstate_pkg/c6-residency/ [Kernel PMU event] + cstate_pkg/c7-residency/ [Kernel PMU event] + cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] + cycles-t OR cpu/cycles-t/ [Kernel PMU event] + el-abort OR cpu/el-abort/ [Kernel PMU event] + el-capacity OR cpu/el-capacity/ [Kernel PMU event] + +Notice in the above example how the cstate_core PMU events are mixed in +the middle of the CPU core events. + +For my arm64 platform, all the uncore events get mixed in, making the list +very disorganised: + + page-faults OR faults [Software event] + task-clock [Software event] + duration_time [Tool event] + L1-dcache-load-misses [Hardware cache event] + L1-dcache-loads [Hardware cache event] + L1-icache-load-misses [Hardware cache event] + L1-icache-loads [Hardware cache event] + branch-load-misses [Hardware cache event] + branch-loads [Hardware cache event] + dTLB-load-misses [Hardware cache event] + dTLB-loads [Hardware cache event] + iTLB-load-misses [Hardware cache event] + iTLB-loads [Hardware cache event] + br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] + br_mis_pred_retired OR armv8_pmuv3_0/br_mis_pred_retired/ [Kernel PMU event] + br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event] + br_retired OR armv8_pmuv3_0/br_retired/ [Kernel PMU event] + br_return_retired OR armv8_pmuv3_0/br_return_retired/ [Kernel PMU event] + bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event] + bus_cycles OR armv8_pmuv3_0/bus_cycles/ [Kernel PMU event] + cid_write_retired OR armv8_pmuv3_0/cid_write_retired/ [Kernel PMU event] + cpu_cycles OR armv8_pmuv3_0/cpu_cycles/ [Kernel PMU event] + dtlb_walk OR armv8_pmuv3_0/dtlb_walk/ [Kernel PMU event] + exc_return OR armv8_pmuv3_0/exc_return/ [Kernel PMU event] + exc_taken OR armv8_pmuv3_0/exc_taken/ [Kernel PMU event] + hisi_sccl1_ddrc0/act_cmd/ [Kernel PMU event] + hisi_sccl1_ddrc0/flux_rcmd/ [Kernel PMU event] + hisi_sccl1_ddrc0/flux_rd/ [Kernel PMU event] + hisi_sccl1_ddrc0/flux_wcmd/ [Kernel PMU event] + hisi_sccl1_ddrc0/flux_wr/ [Kernel PMU event] + hisi_sccl1_ddrc0/pre_cmd/ [Kernel PMU event] + hisi_sccl1_ddrc0/rnk_chg/ [Kernel PMU event] + +... + + hisi_sccl7_l3c21/wr_hit_cpipe/ [Kernel PMU event] + hisi_sccl7_l3c21/wr_hit_spipe/ [Kernel PMU event] + hisi_sccl7_l3c21/wr_spipe/ [Kernel PMU event] + inst_retired OR armv8_pmuv3_0/inst_retired/ [Kernel PMU event] + inst_spec OR armv8_pmuv3_0/inst_spec/ [Kernel PMU event] + itlb_walk OR armv8_pmuv3_0/itlb_walk/ [Kernel PMU event] + l1d_cache OR armv8_pmuv3_0/l1d_cache/ [Kernel PMU event] + l1d_cache_refill OR armv8_pmuv3_0/l1d_cache_refill/ [Kernel PMU event] + l1d_cache_wb OR armv8_pmuv3_0/l1d_cache_wb/ [Kernel PMU event] + l1d_tlb OR armv8_pmuv3_0/l1d_tlb/ [Kernel PMU event] + l1d_tlb_refill OR armv8_pmuv3_0/l1d_tlb_refill/ [Kernel PMU event] + +So the events are list alphabetically. However, CPU core event listing is +special from commit dc098b35b56f ("perf list: List kernel supplied event +aliases"), in that the alias and full event is shown (in that order). +As such, the core events may become sparse. + +Improve this by grouping the CPU core events and ensure that they are +listed first for kernel PMU events. For the first example, above, this +now looks like: + + duration_time [Tool event] + branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] + branch-misses OR cpu/branch-misses/ [Kernel PMU event] + bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] + cache-misses OR cpu/cache-misses/ [Kernel PMU event] + cache-references OR cpu/cache-references/ [Kernel PMU event] + cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] + cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] + cycles-t OR cpu/cycles-t/ [Kernel PMU event] + el-abort OR cpu/el-abort/ [Kernel PMU event] + el-capacity OR cpu/el-capacity/ [Kernel PMU event] + el-commit OR cpu/el-commit/ [Kernel PMU event] + el-conflict OR cpu/el-conflict/ [Kernel PMU event] + el-start OR cpu/el-start/ [Kernel PMU event] + instructions OR cpu/instructions/ [Kernel PMU event] + mem-loads OR cpu/mem-loads/ [Kernel PMU event] + mem-stores OR cpu/mem-stores/ [Kernel PMU event] + ref-cycles OR cpu/ref-cycles/ [Kernel PMU event] + topdown-fetch-bubbles OR cpu/topdown-fetch-bubbles/ [Kernel PMU event] + topdown-recovery-bubbles OR cpu/topdown-recovery-bubbles/ [Kernel PMU event] + topdown-slots-issued OR cpu/topdown-slots-issued/ [Kernel PMU event] + topdown-slots-retired OR cpu/topdown-slots-retired/ [Kernel PMU event] + topdown-total-slots OR cpu/topdown-total-slots/ [Kernel PMU event] + tx-abort OR cpu/tx-abort/ [Kernel PMU event] + tx-capacity OR cpu/tx-capacity/ [Kernel PMU event] + tx-commit OR cpu/tx-commit/ [Kernel PMU event] + tx-conflict OR cpu/tx-conflict/ [Kernel PMU event] + tx-start OR cpu/tx-start/ [Kernel PMU event] + cstate_core/c3-residency/ [Kernel PMU event] + cstate_core/c6-residency/ [Kernel PMU event] + cstate_core/c7-residency/ [Kernel PMU event] + cstate_pkg/c2-residency/ [Kernel PMU event] + cstate_pkg/c3-residency/ [Kernel PMU event] + cstate_pkg/c6-residency/ [Kernel PMU event] + cstate_pkg/c7-residency/ [Kernel PMU event] + +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Acked-by: Namhyung Kim +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1592384514-119954-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index cf1b43bddc85..713d1c6204a2 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -1379,6 +1379,7 @@ struct sevent { + char *pmu; + char *metric_expr; + char *metric_name; ++ int is_cpu; + }; + + static int cmp_sevent(const void *a, const void *b) +@@ -1395,6 +1396,11 @@ static int cmp_sevent(const void *a, const void *b) + if (n) + return n; + } ++ ++ /* Order CPU core events to be first */ ++ if (as->is_cpu != bs->is_cpu) ++ return bs->is_cpu - as->is_cpu; ++ + return strcmp(as->name, bs->name); + } + +@@ -1486,6 +1492,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, + aliases[j].pmu = pmu->name; + aliases[j].metric_expr = alias->metric_expr; + aliases[j].metric_name = alias->metric_name; ++ aliases[j].is_cpu = is_cpu; + j++; + } + if (pmu->selectable && +-- +2.27.0 + diff --git a/patches/0222-perf-metric-Rename-expr__add_id-to-expr__add_val.patch b/patches/0222-perf-metric-Rename-expr__add_id-to-expr__add_val.patch new file mode 100644 index 0000000..bd7a8c0 --- /dev/null +++ b/patches/0222-perf-metric-Rename-expr__add_id-to-expr__add_val.patch @@ -0,0 +1,138 @@ +From 76d2a94b32ebce193fcc707f2dcbe5011474f6b1 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 12 Jul 2020 15:26:17 +0200 +Subject: [PATCH 105/201] perf metric: Rename expr__add_id() to expr__add_val() + +mainline inclusion +from mainline-v5.9-rc1 +commit c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 + +---------------------------------------------------------------------- + +Rename expr__add_id() to expr__add_val() so we can use expr__add_id() to +actually add just the id without any value in following changes. + +There's no functional change. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200712132634.138901-2-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 4 ++-- + tools/perf/tests/pmu-events.c | 4 ++-- + tools/perf/util/expr.c | 2 +- + tools/perf/util/expr.h | 2 +- + tools/perf/util/expr.y | 2 +- + tools/perf/util/stat-shadow.c | 4 ++-- + 6 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 13c4243110d8..d1a5a6f25c50 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -22,8 +22,8 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + struct expr_parse_ctx ctx; + + expr__ctx_init(&ctx); +- expr__add_id(&ctx, strdup("FOO"), 1); +- expr__add_id(&ctx, strdup("BAR"), 2); ++ expr__add_id_val(&ctx, strdup("FOO"), 1); ++ expr__add_id_val(&ctx, strdup("BAR"), 2); + + ret = test(&ctx, "1+1", 2); + ret |= test(&ctx, "FOO+BAR", 3); +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 0a6611d8ec32..7a3cad2ac94e 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -488,7 +488,7 @@ static int test_parsing(void) + */ + k = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) +- expr__add_id(&ctx, strdup(cur->key), k++); ++ expr__add_id_val(&ctx, strdup(cur->key), k++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_cpu(cur->key, map == cpus_map, +@@ -543,7 +543,7 @@ static int metric_parse_fake(const char *str) + */ + i = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) +- expr__add_id(&ctx, strdup(cur->key), i++); ++ expr__add_id_val(&ctx, strdup(cur->key), i++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_fake(cur->key)) { +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 8ab40b42d3e6..e7b929a6d7a8 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -30,7 +30,7 @@ static bool key_equal(const void *key1, const void *key2, + } + + /* Caller must make sure id is allocated */ +-int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) ++int expr__add_id_val(struct expr_parse_ctx *ctx, const char *name, double val) + { + double *val_ptr = NULL, *old_val = NULL; + char *old_key = NULL; +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 8a2c1074f90f..bb6bac836b48 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -22,7 +22,7 @@ struct expr_scanner_ctx { + + void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__ctx_clear(struct expr_parse_ctx *ctx); +-int expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); ++int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr, int runtime); +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 924df4e1c477..e43f4ad1a7d3 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -59,7 +59,7 @@ all_other: all_other other + + other: ID + { +- expr__add_id(ctx, $1, 0.0); ++ expr__add_id_val(ctx, $1, 0.0); + } + | + MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 6b259855d5e0..403f20c67c28 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -773,9 +773,9 @@ static int prepare_metric(struct perf_evsel **metric_events, + *pn = 0; + + if (metric_total) +- expr__add_id(pctx, n, metric_total); ++ expr__add_id_val(pctx, n, metric_total); + else +- expr__add_id(pctx, n, avg_stats(stats)*scale); ++ expr__add_id_val(pctx, n, avg_stats(stats)*scale); + } + + return i; +-- +2.27.0 + diff --git a/patches/0223-perf-metric-Add-struct-expr_id_data-to-keep-expr-val.patch b/patches/0223-perf-metric-Add-struct-expr_id_data-to-keep-expr-val.patch new file mode 100644 index 0000000..875c9a4 --- /dev/null +++ b/patches/0223-perf-metric-Add-struct-expr_id_data-to-keep-expr-val.patch @@ -0,0 +1,146 @@ +From 19986eb8a8bd660c1026bb21913160989536e51f Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 12 Jul 2020 15:26:18 +0200 +Subject: [PATCH 106/201] perf metric: Add 'struct expr_id_data' to keep expr + value + +mainline inclusion +from mainline-v5.9-rc1 +commit ce0dc7d22271fa7eac3875fc9b57772742b8245e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ce0dc7d22271fa7eac3875fc9b57772742b8245e + +---------------------------------------------------------------------- + +Add 'struct expr_id_data' to keep an expr value instead of just a simple +double pointer, so we can store more data for ID in the following +changes. + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200712132634.138901-3-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/tests/expr.c | 3 ++- + tools/perf/util/expr.c | 22 +++++++++++----------- + tools/perf/util/expr.h | 4 ++++ + tools/perf/util/metricgroup.c | 2 +- + 4 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index d1a5a6f25c50..992b7546b9da 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -16,8 +16,9 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2) + + int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + { ++ struct expr_id_data *val_ptr; + const char *p; +- double val, *val_ptr; ++ double val; + int ret; + struct expr_parse_ctx ctx; + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index e7b929a6d7a8..e328931dcfe1 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -30,32 +30,32 @@ static bool key_equal(const void *key1, const void *key2, + } + + /* Caller must make sure id is allocated */ +-int expr__add_id_val(struct expr_parse_ctx *ctx, const char *name, double val) ++int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + { +- double *val_ptr = NULL, *old_val = NULL; ++ struct expr_id_data *data_ptr = NULL, *old_data = NULL; + char *old_key = NULL; + int ret; + + if (val != 0.0) { +- val_ptr = malloc(sizeof(double)); +- if (!val_ptr) ++ data_ptr = malloc(sizeof(*data_ptr)); ++ if (!data_ptr) + return -ENOMEM; +- *val_ptr = val; ++ data_ptr->val = val; + } +- ret = hashmap__set(&ctx->ids, name, val_ptr, +- (const void **)&old_key, (void **)&old_val); ++ ret = hashmap__set(&ctx->ids, id, data_ptr, ++ (const void **)&old_key, (void **)&old_data); + free(old_key); +- free(old_val); ++ free(old_data); + return ret; + } + + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) + { +- double *data; ++ struct expr_id_data *data; + + if (!hashmap__find(&ctx->ids, id, (void **)&data)) + return -1; +- *val_ptr = (data == NULL) ? 0.0 : *data; ++ *val_ptr = (data == NULL) ? 0.0 : data->val; + return 0; + } + +@@ -115,7 +115,7 @@ int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + int expr__find_other(const char *expr, const char *one, + struct expr_parse_ctx *ctx, int runtime) + { +- double *old_val = NULL; ++ struct expr_id_data *old_val = NULL; + char *old_key = NULL; + int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); + +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index bb6bac836b48..21fe5bd85718 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -15,6 +15,10 @@ struct expr_parse_ctx { + struct hashmap ids; + }; + ++struct expr_id_data { ++ double val; ++}; ++ + struct expr_scanner_ctx { + int start_token; + int runtime; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 230c6d092ca2..43f08a1e51ae 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -144,7 +144,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + unsigned long *evlist_used) + { + struct perf_evsel *ev, *current_leader = NULL; +- double *val_ptr; ++ struct expr_id_data *val_ptr; + int i = 0, matched_events = 0, events_to_match; + const int idnum = (int)hashmap__size(&pctx->ids); + +-- +2.27.0 + diff --git a/patches/0224-perf-metric-Fix-memory-leak-in-expr__add_id-function.patch b/patches/0224-perf-metric-Fix-memory-leak-in-expr__add_id-function.patch new file mode 100644 index 0000000..c341a8e --- /dev/null +++ b/patches/0224-perf-metric-Fix-memory-leak-in-expr__add_id-function.patch @@ -0,0 +1,53 @@ +From f27677eedf71764e9b1d204bf419b2ed538269b0 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:02 +0200 +Subject: [PATCH 107/201] perf metric: Fix memory leak in expr__add_id function + +mainline inclusion +from mainline-v5.9-rc1 +commit 2c46f54249c6e86d8d81b5ea2452319f197caf17 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2c46f54249c6e86d8d81b5ea2452319f197caf17 + +---------------------------------------------------------------------- + +Arnaldo found that we don't release value data in case the hashmap__set +fails. Releasing it in case of an error. + +Reported-by: Arnaldo Carvalho de Melo +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-2-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index e328931dcfe1..4dec1add3a13 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -44,6 +44,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + } + ret = hashmap__set(&ctx->ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); ++ if (ret) ++ free(data_ptr); + free(old_key); + free(old_data); + return ret; +-- +2.27.0 + diff --git a/patches/0225-perf-metric-Add-expr__add_id-function.patch b/patches/0225-perf-metric-Add-expr__add_id-function.patch new file mode 100644 index 0000000..af5605a --- /dev/null +++ b/patches/0225-perf-metric-Add-expr__add_id-function.patch @@ -0,0 +1,115 @@ +From eec278ff30e74f887718f6e7b25a6f55f6e1a93e Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:03 +0200 +Subject: [PATCH 108/201] perf metric: Add expr__add_id function + +mainline inclusion +from mainline-v5.9-rc1 +commit 070b3b5ad7bd077e673cad2c591a2ecf49c0b58a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=070b3b5ad7bd077e673cad2c591a2ecf49c0b58a + +---------------------------------------------------------------------- + +Add the expr__add_id() function to data for ID with zero value, which is +used when scanning the expression for IDs. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-3-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 31 +++++++++++++++++++++++++------ + tools/perf/util/expr.h | 1 + + tools/perf/util/expr.y | 2 +- + 3 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 4dec1add3a13..719313de63eb 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -29,6 +29,26 @@ static bool key_equal(const void *key1, const void *key2, + return !strcmp((const char *)key1, (const char *)key2); + } + ++/* Caller must make sure id is allocated */ ++int expr__add_id(struct expr_parse_ctx *ctx, const char *id) ++{ ++ struct expr_id_data *data_ptr = NULL, *old_data = NULL; ++ char *old_key = NULL; ++ int ret; ++ ++ data_ptr = malloc(sizeof(*data_ptr)); ++ if (!data_ptr) ++ return -ENOMEM; ++ ++ ret = hashmap__set(&ctx->ids, id, data_ptr, ++ (const void **)&old_key, (void **)&old_data); ++ if (ret) ++ free(data_ptr); ++ free(old_key); ++ free(old_data); ++ return ret; ++} ++ + /* Caller must make sure id is allocated */ + int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + { +@@ -36,12 +56,11 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + char *old_key = NULL; + int ret; + +- if (val != 0.0) { +- data_ptr = malloc(sizeof(*data_ptr)); +- if (!data_ptr) +- return -ENOMEM; +- data_ptr->val = val; +- } ++ data_ptr = malloc(sizeof(*data_ptr)); ++ if (!data_ptr) ++ return -ENOMEM; ++ data_ptr->val = val; ++ + ret = hashmap__set(&ctx->ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); + if (ret) +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 21fe5bd85718..ac32cda42006 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -26,6 +26,7 @@ struct expr_scanner_ctx { + + void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__ctx_clear(struct expr_parse_ctx *ctx); ++int expr__add_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index e43f4ad1a7d3..a04c969fb5ee 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -59,7 +59,7 @@ all_other: all_other other + + other: ID + { +- expr__add_id_val(ctx, $1, 0.0); ++ expr__add_id(ctx, $1); + } + | + MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' +-- +2.27.0 + diff --git a/patches/0226-perf-metric-Change-expr__get_id-to-return-struct-exp.patch b/patches/0226-perf-metric-Change-expr__get_id-to-return-struct-exp.patch new file mode 100644 index 0000000..754eec1 --- /dev/null +++ b/patches/0226-perf-metric-Change-expr__get_id-to-return-struct-exp.patch @@ -0,0 +1,105 @@ +From bd847b9c735158b626574b0610075af98774fd96 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:04 +0200 +Subject: [PATCH 109/201] perf metric: Change expr__get_id to return struct + expr_id_data + +mainline inclusion +from mainline-v5.9-rc1 +commit 60e10c0037d0159f886c8592b761ee31ab3b7e21 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=60e10c0037d0159f886c8592b761ee31ab3b7e21 + +---------------------------------------------------------------------- + +Changing expr__get_id to use and return struct expr_id_data +pointer as value for the ID. This way we can access data other +than value for given ID in following changes. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-4-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 10 +++------- + tools/perf/util/expr.h | 3 ++- + tools/perf/util/expr.y | 14 +++++++++----- + 3 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 719313de63eb..db2036cc41bf 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -70,14 +70,10 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + return ret; + } + +-int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) ++int expr__get_id(struct expr_parse_ctx *ctx, const char *id, ++ struct expr_id_data **data) + { +- struct expr_id_data *data; +- +- if (!hashmap__find(&ctx->ids, id, (void **)&data)) +- return -1; +- *val_ptr = (data == NULL) ? 0.0 : data->val; +- return 0; ++ return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1; + } + + void expr__ctx_init(struct expr_parse_ctx *ctx) +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index ac32cda42006..f38292fdab19 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -28,7 +28,8 @@ void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__ctx_clear(struct expr_parse_ctx *ctx); + int expr__add_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); +-int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr); ++int expr__get_id(struct expr_parse_ctx *ctx, const char *id, ++ struct expr_id_data **data); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr, int runtime); + int expr__find_other(const char *expr, const char *one, +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index a04c969fb5ee..207dd371fed2 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -74,12 +74,16 @@ if_expr: + ; + + expr: NUMBER +- | ID { if (expr__get_id(ctx, $1, &$$)) { +- pr_debug("%s not found\n", $1); ++ | ID { ++ struct expr_id_data *data; ++ ++ if (expr__get_id(ctx, $1, &data) || !data) { ++ pr_debug("%s not found\n", $1); ++ free($1); ++ YYABORT; ++ } ++ $$ = data->val; + free($1); +- YYABORT; +- } +- free($1); + } + | expr '|' expr { $$ = (long)$1 | (long)$3; } + | expr '&' expr { $$ = (long)$1 & (long)$3; } +-- +2.27.0 + diff --git a/patches/0227-perf-metric-Add-expr__del_id-function.patch b/patches/0227-perf-metric-Add-expr__del_id-function.patch new file mode 100644 index 0000000..49b3e99 --- /dev/null +++ b/patches/0227-perf-metric-Add-expr__del_id-function.patch @@ -0,0 +1,93 @@ +From 130b083fbf5b21bd12a82db4b38b32b5fe7ba0dc Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:05 +0200 +Subject: [PATCH 110/201] perf metric: Add expr__del_id function + +mainline inclusion +from mainline-v5.9-rc1 +commit 332603c2aa1a3be92720343269e670f8118a8831 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=332603c2aa1a3be92720343269e670f8118a8831 + +---------------------------------------------------------------------- + +Adding expr__del_id function to remove ID from hashmap. It will save us +few lines in following changes. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-5-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 21 +++++++++++++-------- + tools/perf/util/expr.h | 1 + + 2 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index db2036cc41bf..5f7e606a2a95 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -76,6 +76,17 @@ int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1; + } + ++void expr__del_id(struct expr_parse_ctx *ctx, const char *id) ++{ ++ struct expr_id_data *old_val = NULL; ++ char *old_key = NULL; ++ ++ hashmap__delete(&ctx->ids, id, ++ (const void **)&old_key, (void **)&old_val); ++ free(old_key); ++ free(old_val); ++} ++ + void expr__ctx_init(struct expr_parse_ctx *ctx) + { + hashmap__init(&ctx->ids, key_hash, key_equal, NULL); +@@ -132,16 +143,10 @@ int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + int expr__find_other(const char *expr, const char *one, + struct expr_parse_ctx *ctx, int runtime) + { +- struct expr_id_data *old_val = NULL; +- char *old_key = NULL; + int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); + +- if (one) { +- hashmap__delete(&ctx->ids, one, +- (const void **)&old_key, (void **)&old_val); +- free(old_key); +- free(old_val); +- } ++ if (one) ++ expr__del_id(ctx, one); + + return ret; + } +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index f38292fdab19..2462abd0ac65 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -26,6 +26,7 @@ struct expr_scanner_ctx { + + void expr__ctx_init(struct expr_parse_ctx *ctx); + void expr__ctx_clear(struct expr_parse_ctx *ctx); ++void expr__del_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, +-- +2.27.0 + diff --git a/patches/0228-perf-metric-Add-macros-for-iterating-map-events.patch b/patches/0228-perf-metric-Add-macros-for-iterating-map-events.patch new file mode 100644 index 0000000..d54f4f8 --- /dev/null +++ b/patches/0228-perf-metric-Add-macros-for-iterating-map-events.patch @@ -0,0 +1,148 @@ +From d70bea294fb0ca6361e9dd4b661e837c13257e63 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:06 +0200 +Subject: [PATCH 111/201] perf metric: Add macros for iterating map events + +mainline inclusion +from mainline-v5.9-rc1 +commit 5c5f5e835f7e40e74f4a8370abb32647b11c3366 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5c5f5e835f7e40e74f4a8370abb32647b11c3366 + +---------------------------------------------------------------------- + +Adding following macros to iterate events and metric: + + map_for_each_event(__pe, __idx, __map) + - iterates over all pmu_events_map events + + map_for_each_metric(__pe, __idx, __map, __metric) + - iterates over all metrics that match __metric argument + +and use it in metricgroup__add_metric function. Macros will be be used +from other places in following changes. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-6-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 77 ++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 37 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 43f08a1e51ae..f6e725c6062c 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -621,6 +621,17 @@ static int __metricgroup__add_metric(struct list_head *group_list, + return 0; + } + ++#define map_for_each_event(__pe, __idx, __map) \ ++ for (__idx = 0, __pe = &__map->table[__idx]; \ ++ __pe->name || __pe->metric_group || __pe->metric_name; \ ++ __pe = &__map->table[++__idx]) ++ ++#define map_for_each_metric(__pe, __idx, __map, __metric) \ ++ map_for_each_event(__pe, __idx, __map) \ ++ if (__pe->metric_expr && \ ++ (match_metric(__pe->metric_group, __metric) || \ ++ match_metric(__pe->metric_name, __metric))) ++ + static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct strbuf *events, + struct list_head *group_list, +@@ -631,49 +642,41 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + int i, ret; + bool has_match = false; + +- for (i = 0; ; i++) { +- pe = &map->table[i]; +- +- if (!pe->name && !pe->metric_group && !pe->metric_name) { +- /* End of pmu events. */ +- if (!has_match) +- return -EINVAL; +- break; +- } +- if (!pe->metric_expr) +- continue; +- if (match_metric(pe->metric_group, metric) || +- match_metric(pe->metric_name, metric)) { +- has_match = true; +- pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); +- +- if (!strstr(pe->metric_expr, "?")) { +- ret = __metricgroup__add_metric(group_list, +- pe, +- metric_no_group, +- 1); +- if (ret) +- return ret; +- } else { +- int j, count; ++ map_for_each_metric(pe, i, map, metric) { ++ pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); ++ has_match = true; ++ ++ if (!strstr(pe->metric_expr, "?")) { ++ ret = __metricgroup__add_metric(group_list, ++ pe, ++ metric_no_group, ++ 1); ++ if (ret) ++ return ret; ++ } else { ++ int j, count; + +- count = arch_get_runtimeparam(); ++ count = arch_get_runtimeparam(); + +- /* This loop is added to create multiple +- * events depend on count value and add +- * those events to group_list. +- */ ++ /* This loop is added to create multiple ++ * events depend on count value and add ++ * those events to group_list. ++ */ + +- for (j = 0; j < count; j++) { +- ret = __metricgroup__add_metric( +- group_list, pe, +- metric_no_group, j); +- if (ret) +- return ret; +- } ++ for (j = 0; j < count; j++) { ++ ret = __metricgroup__add_metric( ++ group_list, pe, ++ metric_no_group, j); ++ if (ret) ++ return ret; + } + } + } ++ ++ /* End of pmu events. */ ++ if (!has_match) ++ return -EINVAL; ++ + list_for_each_entry(eg, group_list, nd) { + if (events->len > 0) + strbuf_addf(events, ","); +-- +2.27.0 + diff --git a/patches/0229-perf-metric-Add-add_metric-function.patch b/patches/0229-perf-metric-Add-add_metric-function.patch new file mode 100644 index 0000000..c1f80df --- /dev/null +++ b/patches/0229-perf-metric-Add-add_metric-function.patch @@ -0,0 +1,121 @@ +From f82681d8b89d41453021a9e14d918a4b87076bb6 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:07 +0200 +Subject: [PATCH 112/201] perf metric: Add add_metric function + +mainline inclusion +from mainline-v5.9-rc1 +commit 3fd29fa6c1644026ec7adbe017cacdf03724e6bc +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3fd29fa6c1644026ec7adbe017cacdf03724e6bc + +---------------------------------------------------------------------- + +Decouple metric adding logging into add_metric function, +so it can be used from other places in following changes. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-7-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 62 ++++++++++++++++++++--------------- + 1 file changed, 36 insertions(+), 26 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index f6e725c6062c..ecc1f2db1a75 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -632,6 +632,39 @@ static int __metricgroup__add_metric(struct list_head *group_list, + (match_metric(__pe->metric_group, __metric) || \ + match_metric(__pe->metric_name, __metric))) + ++static int add_metric(struct list_head *group_list, ++ struct pmu_event *pe, ++ bool metric_no_group) ++{ ++ int ret = 0; ++ ++ pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); ++ ++ if (!strstr(pe->metric_expr, "?")) { ++ ret = __metricgroup__add_metric(group_list, ++ pe, ++ metric_no_group, ++ 1); ++ } else { ++ int j, count; ++ ++ count = arch_get_runtimeparam(); ++ ++ /* This loop is added to create multiple ++ * events depend on count value and add ++ * those events to group_list. ++ */ ++ ++ for (j = 0; j < count && !ret; j++) { ++ ret = __metricgroup__add_metric( ++ group_list, pe, ++ metric_no_group, j); ++ } ++ } ++ ++ return ret; ++} ++ + static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct strbuf *events, + struct list_head *group_list, +@@ -643,34 +676,11 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + bool has_match = false; + + map_for_each_metric(pe, i, map, metric) { +- pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + has_match = true; + +- if (!strstr(pe->metric_expr, "?")) { +- ret = __metricgroup__add_metric(group_list, +- pe, +- metric_no_group, +- 1); +- if (ret) +- return ret; +- } else { +- int j, count; +- +- count = arch_get_runtimeparam(); +- +- /* This loop is added to create multiple +- * events depend on count value and add +- * those events to group_list. +- */ +- +- for (j = 0; j < count; j++) { +- ret = __metricgroup__add_metric( +- group_list, pe, +- metric_no_group, j); +- if (ret) +- return ret; +- } +- } ++ ret = add_metric(group_list, pe, metric_no_group); ++ if (ret) ++ return ret; + } + + /* End of pmu events. */ +-- +2.27.0 + diff --git a/patches/0230-perf-metric-Rename-__metricgroup__add_metric-to-__ad.patch b/patches/0230-perf-metric-Rename-__metricgroup__add_metric-to-__ad.patch new file mode 100644 index 0000000..60fc3be --- /dev/null +++ b/patches/0230-perf-metric-Rename-__metricgroup__add_metric-to-__ad.patch @@ -0,0 +1,82 @@ +From 7a32d75cd3c403586270e9a5750cc5813b341a79 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:08 +0200 +Subject: [PATCH 113/201] perf metric: Rename __metricgroup__add_metric to + __add_metric + +mainline inclusion +from mainline-v5.9-rc1 +commit ce39194034008e6736646efb52230627972f1049 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ce39194034008e6736646efb52230627972f1049 + +---------------------------------------------------------------------- + +Renaming __metricgroup__add_metric to __add_metric to fit in the current +function names. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-8-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index ecc1f2db1a75..4081999a05af 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -578,10 +578,10 @@ int __weak arch_get_runtimeparam(void) + return 1; + } + +-static int __metricgroup__add_metric(struct list_head *group_list, +- struct pmu_event *pe, +- bool metric_no_group, +- int runtime) ++static int __add_metric(struct list_head *group_list, ++ struct pmu_event *pe, ++ bool metric_no_group, ++ int runtime) + { + struct egroup *eg; + +@@ -641,10 +641,7 @@ static int add_metric(struct list_head *group_list, + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __metricgroup__add_metric(group_list, +- pe, +- metric_no_group, +- 1); ++ ret = __add_metric(group_list, pe, metric_no_group, 1); + } else { + int j, count; + +@@ -656,9 +653,7 @@ static int add_metric(struct list_head *group_list, + */ + + for (j = 0; j < count && !ret; j++) { +- ret = __metricgroup__add_metric( +- group_list, pe, +- metric_no_group, j); ++ ret = __add_metric(group_list, pe, metric_no_group, j); + } + } + +-- +2.27.0 + diff --git a/patches/0231-perf-metric-Collect-referenced-metrics-in-struct-met.patch b/patches/0231-perf-metric-Collect-referenced-metrics-in-struct-met.patch new file mode 100644 index 0000000..04d05a7 --- /dev/null +++ b/patches/0231-perf-metric-Collect-referenced-metrics-in-struct-met.patch @@ -0,0 +1,309 @@ +From 2b09c4be3626223ad986b311085f7c5d8a26d975 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:09 +0200 +Subject: [PATCH 114/201] perf metric: Collect referenced metrics in struct + metric_ref_node + +mainline inclusion +from mainline-v5.9-rc1 +commit a29c164aa3163f8ffbc36db3e57296eff95a8087 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a29c164aa3163f8ffbc36db3e57296eff95a8087 + +---------------------------------------------------------------------- + +Collecting referenced metrics in struct metric_ref_node object, +so we can process them later on. + +The change will parse nested metric names out of expression and +'resolve' them. + +All referenced metrics are dissolved into one context, meaning all +nested metrics events and added to the parent context. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-9-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 188 +++++++++++++++++++++++++++++++--- + 1 file changed, 172 insertions(+), 16 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 4081999a05af..9bb402fc03ab 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -108,12 +108,25 @@ void metricgroup__rblist_exit(struct rblist *metric_events) + rblist__exit(metric_events); + } + ++/* ++ * A node in the list of referenced metrics. metric_expr ++ * is held as a convenience to avoid a search through the ++ * metric list. ++ */ ++struct metric_ref_node { ++ const char *metric_name; ++ const char *metric_expr; ++ struct list_head list; ++}; ++ + struct egroup { + struct list_head nd; + struct expr_parse_ctx pctx; + const char *metric_name; + const char *metric_expr; + const char *metric_unit; ++ struct list_head metric_refs; ++ int metric_refs_cnt; + int runtime; + bool has_constraint; + }; +@@ -581,27 +594,72 @@ int __weak arch_get_runtimeparam(void) + static int __add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, +- int runtime) ++ int runtime, ++ struct egroup **egp) + { ++ struct metric_ref_node *ref; + struct egroup *eg; + +- eg = malloc(sizeof(*eg)); +- if (!eg) +- return -ENOMEM; ++ if (*egp == NULL) { ++ /* ++ * We got in here for the parent group, ++ * allocate it and put it on the list. ++ */ ++ eg = malloc(sizeof(*eg)); ++ if (!eg) ++ return -ENOMEM; ++ ++ expr__ctx_init(&eg->pctx); ++ eg->metric_name = pe->metric_name; ++ eg->metric_expr = pe->metric_expr; ++ eg->metric_unit = pe->unit; ++ eg->runtime = runtime; ++ eg->has_constraint = metric_no_group || metricgroup__has_constraint(pe); ++ INIT_LIST_HEAD(&eg->metric_refs); ++ eg->metric_refs_cnt = 0; ++ *egp = eg; ++ } else { ++ /* ++ * We got here for the referenced metric, via the ++ * recursive metricgroup__add_metric call, add ++ * it to the parent group. ++ */ ++ eg = *egp; ++ ++ ref = malloc(sizeof(*ref)); ++ if (!ref) ++ return -ENOMEM; + +- expr__ctx_init(&eg->pctx); +- eg->metric_name = pe->metric_name; +- eg->metric_expr = pe->metric_expr; +- eg->metric_unit = pe->unit; +- eg->runtime = runtime; +- eg->has_constraint = metric_no_group || metricgroup__has_constraint(pe); ++ /* ++ * Intentionally passing just const char pointers, ++ * from 'pe' object, so they never go away. We don't ++ * need to change them, so there's no need to create ++ * our own copy. ++ */ ++ ref->metric_name = pe->metric_name; ++ ref->metric_expr = pe->metric_expr; ++ ++ list_add(&ref->list, &eg->metric_refs); ++ eg->metric_refs_cnt++; ++ } + ++ /* ++ * For both the parent and referenced metrics, we parse ++ * all the metric's IDs and add it to the parent context. ++ */ + if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { + expr__ctx_clear(&eg->pctx); + free(eg); + return -EINVAL; + } + ++ /* ++ * We add new group only in the 'parent' call, ++ * so bail out for referenced metric case. ++ */ ++ if (eg->metric_refs_cnt) ++ return 0; ++ + if (list_empty(group_list)) + list_add(&eg->nd, group_list); + else { +@@ -632,16 +690,94 @@ static int __add_metric(struct list_head *group_list, + (match_metric(__pe->metric_group, __metric) || \ + match_metric(__pe->metric_name, __metric))) + ++static struct pmu_event *find_metric(const char *metric, struct pmu_events_map *map) ++{ ++ struct pmu_event *pe; ++ int i; ++ ++ map_for_each_event(pe, i, map) { ++ if (match_metric(pe->metric_name, metric)) ++ return pe; ++ } ++ ++ return NULL; ++} ++ + static int add_metric(struct list_head *group_list, + struct pmu_event *pe, +- bool metric_no_group) ++ bool metric_no_group, ++ struct egroup **egp); ++ ++static int __resolve_metric(struct egroup *eg, ++ bool metric_no_group, ++ struct list_head *group_list, ++ struct pmu_events_map *map) + { ++ struct hashmap_entry *cur; ++ size_t bkt; ++ bool all; ++ int ret; ++ ++ /* ++ * Iterate all the parsed IDs and if there's metric, ++ * add it to the context. ++ */ ++ do { ++ all = true; ++ hashmap__for_each_entry((&eg->pctx.ids), cur, bkt) { ++ struct pmu_event *pe; ++ ++ pe = find_metric(cur->key, map); ++ if (!pe) ++ continue; ++ ++ all = false; ++ /* The metric key itself needs to go out.. */ ++ expr__del_id(&eg->pctx, cur->key); ++ ++ /* ... and it gets resolved to the parent context. */ ++ ret = add_metric(group_list, pe, metric_no_group, &eg); ++ if (ret) ++ return ret; ++ ++ /* ++ * We added new metric to hashmap, so we need ++ * to break the iteration and start over. ++ */ ++ break; ++ } ++ } while (!all); ++ ++ return 0; ++} ++ ++static int resolve_metric(bool metric_no_group, ++ struct list_head *metric_list, ++ struct pmu_events_map *map) ++{ ++ struct egroup *eg; ++ int err; ++ ++ list_for_each_entry(eg, metric_list, nd) { ++ err = __resolve_metric(eg, metric_no_group, metric_list, map); ++ if (err) ++ return err; ++ } ++ return 0; ++} ++ ++static int add_metric(struct list_head *group_list, ++ struct pmu_event *pe, ++ bool metric_no_group, ++ struct egroup **egp) ++{ ++ struct egroup *orig = *egp; + int ret = 0; + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __add_metric(group_list, pe, metric_no_group, 1); ++ ret = __add_metric(group_list, pe, metric_no_group, 1, egp); + } else { + int j, count; + +@@ -652,9 +788,8 @@ static int add_metric(struct list_head *group_list, + * those events to group_list. + */ + +- for (j = 0; j < count && !ret; j++) { +- ret = __add_metric(group_list, pe, metric_no_group, j); +- } ++ for (j = 0; j < count && !ret; j++, *egp = orig) ++ ret = __add_metric(group_list, pe, metric_no_group, j, egp); + } + + return ret; +@@ -672,8 +807,18 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + + map_for_each_metric(pe, i, map, metric) { + has_match = true; ++ eg = NULL; ++ ++ ret = add_metric(group_list, pe, metric_no_group, &eg); ++ if (ret) ++ return ret; + +- ret = add_metric(group_list, pe, metric_no_group); ++ /* ++ * Process any possible referenced metrics ++ * included in the expression. ++ */ ++ ret = resolve_metric(metric_no_group, ++ group_list, map); + if (ret) + return ret; + } +@@ -730,11 +875,22 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + return ret; + } + ++static void egroup__free_refs(struct egroup *egroup) ++{ ++ struct metric_ref_node *ref, *tmp; ++ ++ list_for_each_entry_safe(ref, tmp, &egroup->metric_refs, list) { ++ list_del(&ref->list); ++ free(ref); ++ } ++} ++ + static void metricgroup__free_egroups(struct list_head *group_list) + { + struct egroup *eg, *egtmp; + + list_for_each_entry_safe (eg, egtmp, group_list, nd) { ++ egroup__free_refs(eg); + expr__ctx_clear(&eg->pctx); + list_del_init(&eg->nd); + free(eg); +-- +2.27.0 + diff --git a/patches/0232-perf-metric-Collect-referenced-metrics-in-struct-met.patch b/patches/0232-perf-metric-Collect-referenced-metrics-in-struct-met.patch new file mode 100644 index 0000000..9db7d2b --- /dev/null +++ b/patches/0232-perf-metric-Collect-referenced-metrics-in-struct-met.patch @@ -0,0 +1,128 @@ +From dfcb16856514453111e1b59da3d6cefa5000f18f Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:10 +0200 +Subject: [PATCH 115/201] perf metric: Collect referenced metrics in struct + metric_expr + +mainline inclusion +from mainline-v5.9-rc1 +commit e7e1badd80282ff7ee07a5176f0620f57c798934 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e7e1badd80282ff7ee07a5176f0620f57c798934 + +---------------------------------------------------------------------- + +Add referenced metrics into struct metric_expr object, so they are +accessible when computing the metric. + +Storing just name and expression itself, so the metric can be resolved +and computed. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-10-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c + tools/perf/util/metricgroup.h +--- + tools/perf/util/metricgroup.c | 32 ++++++++++++++++++++++++++++++++ + tools/perf/util/metricgroup.h | 6 ++++++ + 2 files changed, 38 insertions(+) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 9bb402fc03ab..ef3f1d41f7db 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -89,6 +89,7 @@ static void metric_event_delete(struct rblist *rblist __maybe_unused, + struct metric_expr *expr, *tmp; + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { ++ free(expr->metric_refs); + free(expr); + } + +@@ -254,6 +255,7 @@ static int metricgroup__setup_events(struct list_head *groups, + + list_for_each_entry (eg, groups, nd) { + struct perf_evsel **metric_events; ++ struct metric_ref *metric_refs = NULL; + + metric_events = calloc(sizeof(void *), + hashmap__size(&eg->pctx.ids) + 1); +@@ -285,6 +287,36 @@ static int metricgroup__setup_events(struct list_head *groups, + free(metric_events); + break; + } ++ ++ /* ++ * Collect and store collected nested expressions ++ * for metric processing. ++ */ ++ if (eg->metric_refs_cnt) { ++ struct metric_ref_node *ref; ++ ++ metric_refs = zalloc(sizeof(struct metric_ref) * (eg->metric_refs_cnt + 1)); ++ if (!metric_refs) { ++ ret = -ENOMEM; ++ free(metric_events); ++ break; ++ } ++ ++ i = 0; ++ list_for_each_entry(ref, &eg->metric_refs, list) { ++ /* ++ * Intentionally passing just const char pointers, ++ * originally from 'struct pmu_event' object. ++ * We don't need to change them, so there's no ++ * need to create our own copy. ++ */ ++ metric_refs[i].metric_name = ref->metric_name; ++ metric_refs[i].metric_expr = ref->metric_expr; ++ i++; ++ } ++ }; ++ ++ expr->metric_refs = metric_refs; + expr->metric_expr = eg->metric_expr; + expr->metric_name = eg->metric_name; + expr->metric_unit = eg->metric_unit; +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index c198e2c4a294..23b4f44b3f39 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -18,12 +18,18 @@ struct metric_event { + struct list_head head; /* list of metric_expr */ + }; + ++struct metric_ref { ++ const char *metric_name; ++ const char *metric_expr; ++}; ++ + struct metric_expr { + struct list_head nd; + const char *metric_expr; + const char *metric_name; + const char *metric_unit; + struct perf_evsel **metric_events; ++ struct metric_ref *metric_refs; + int runtime; + }; + +-- +2.27.0 + diff --git a/patches/0233-perf-metric-Add-referenced-metrics-to-hash-data.patch b/patches/0233-perf-metric-Add-referenced-metrics-to-hash-data.patch new file mode 100644 index 0000000..1cea8eb --- /dev/null +++ b/patches/0233-perf-metric-Add-referenced-metrics-to-hash-data.patch @@ -0,0 +1,245 @@ +From fa1f49e0b6617cf5aced9fc888b8182498aba72e Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:11 +0200 +Subject: [PATCH 116/201] perf metric: Add referenced metrics to hash data + +mainline inclusion +from mainline-v5.9-rc1 +commit 83de0b7d535deeffcbea2f1c3defce912e0206a7 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=83de0b7d535deeffcbea2f1c3defce912e0206a7 + +---------------------------------------------------------------------- + +Adding referenced metrics to the parsing context so they can be resolved +during the metric processing. + +Adding expr__add_ref function to store referenced metrics into parse +context. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-11-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/expr.c + tools/perf/util/stat-shadow.c +--- + tools/perf/util/expr.c | 54 +++++++++++++++++++++++++++++++++++ + tools/perf/util/expr.h | 13 ++++++++- + tools/perf/util/stat-shadow.c | 20 +++++++++---- + 3 files changed, 80 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index 5f7e606a2a95..b5d0542792a0 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -1,10 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 + #include + #include ++#include "metricgroup.h" ++#include "debug.h" + #include "expr.h" + #include "expr-bison.h" + #include "expr-flex.h" + #include ++#include "util.h" ++#include + + #ifdef PARSER_DEBUG + extern int expr_debug; +@@ -60,6 +64,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + if (!data_ptr) + return -ENOMEM; + data_ptr->val = val; ++ data_ptr->is_ref = false; + + ret = hashmap__set(&ctx->ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); +@@ -70,6 +75,55 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) + return ret; + } + ++int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) ++{ ++ struct expr_id_data *data_ptr = NULL, *old_data = NULL; ++ char *old_key = NULL; ++ char *name, *p; ++ int ret; ++ ++ data_ptr = zalloc(sizeof(*data_ptr)); ++ if (!data_ptr) ++ return -ENOMEM; ++ ++ name = strdup(ref->metric_name); ++ if (!name) { ++ free(data_ptr); ++ return -ENOMEM; ++ } ++ ++ /* ++ * The jevents tool converts all metric expressions ++ * to lowercase, including metric references, hence ++ * we need to add lowercase name for metric, so it's ++ * properly found. ++ */ ++ for (p = name; *p; p++) ++ *p = tolower(*p); ++ ++ /* ++ * Intentionally passing just const char pointers, ++ * originally from 'struct pmu_event' object. ++ * We don't need to change them, so there's no ++ * need to create our own copy. ++ */ ++ data_ptr->ref.metric_name = ref->metric_name; ++ data_ptr->ref.metric_expr = ref->metric_expr; ++ data_ptr->is_ref = true; ++ ++ ret = hashmap__set(&ctx->ids, name, data_ptr, ++ (const void **)&old_key, (void **)&old_data); ++ if (ret) ++ free(data_ptr); ++ ++ pr_debug2("adding ref metric %s: %s\n", ++ ref->metric_name, ref->metric_expr); ++ ++ free(old_key); ++ free(old_data); ++ return ret; ++} ++ + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **data) + { +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 2462abd0ac65..81d04ff7f857 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -11,12 +11,22 @@ + #include "util/hashmap.h" + //#endif + ++struct metric_ref; ++ + struct expr_parse_ctx { + struct hashmap ids; + }; + + struct expr_id_data { +- double val; ++ union { ++ double val; ++ struct { ++ const char *metric_name; ++ const char *metric_expr; ++ } ref; ++ }; ++ ++ bool is_ref; + }; + + struct expr_scanner_ctx { +@@ -29,6 +39,7 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx); + void expr__del_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id(struct expr_parse_ctx *ctx, const char *id); + int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); ++int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **data); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 403f20c67c28..48a2a58e282f 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -731,13 +731,14 @@ static void print_smi_cost(struct perf_stat_config *config, + } + + static int prepare_metric(struct perf_evsel **metric_events, ++ struct metric_ref *metric_refs, + struct expr_parse_ctx *pctx, + int cpu, + struct runtime_stat *st) + { + double scale; + char *n, *pn; +- int i; ++ int i, j, ret; + + expr__ctx_init(pctx); + for (i = 0; metric_events[i]; i++) { +@@ -778,12 +779,19 @@ static int prepare_metric(struct perf_evsel **metric_events, + expr__add_id_val(pctx, n, avg_stats(stats)*scale); + } + ++ for (j = 0; metric_refs && metric_refs[j].metric_name; j++) { ++ ret = expr__add_ref(pctx, &metric_refs[j]); ++ if (ret) ++ return ret; ++ } ++ + return i; + } + + static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, + struct perf_evsel **metric_events, ++ struct metric_ref *metric_refs, + char *name, + const char *metric_name, + const char *metric_unit, +@@ -798,7 +806,7 @@ static void generic_metric(struct perf_stat_config *config, + int i; + void *ctxp = out->ctx; + +- i = prepare_metric(metric_events, &pctx, cpu, st); ++ i = prepare_metric(metric_events, metric_refs, &pctx, cpu, st); + if (i < 0) + return; + +@@ -844,7 +852,7 @@ double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_sta + struct expr_parse_ctx pctx; + double ratio; + +- if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) ++ if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0) + return 0.; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) +@@ -1064,8 +1072,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + else + print_metric(config, ctxp, NULL, NULL, name, 0); + } else if (evsel->metric_expr) { +- generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, +- evsel->metric_name, NULL, 1, cpu, out, st); ++ generic_metric(config, evsel->metric_expr, evsel->metric_events, NULL, ++ evsel->name, evsel->metric_name, NULL, 1, cpu, out, st); + } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { + char unit = 'M'; + char unit_buf[10]; +@@ -1093,7 +1101,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, + if (num++ > 0) + out->new_line(config, ctxp); + generic_metric(config, mexp->metric_expr, mexp->metric_events, +- evsel->name, mexp->metric_name, ++ mexp->metric_refs, evsel->name, mexp->metric_name, + mexp->metric_unit, mexp->runtime, cpu, out, st); + } + } +-- +2.27.0 + diff --git a/patches/0234-perf-metric-Compute-referenced-metrics.patch b/patches/0234-perf-metric-Compute-referenced-metrics.patch new file mode 100644 index 0000000..036b02a --- /dev/null +++ b/patches/0234-perf-metric-Compute-referenced-metrics.patch @@ -0,0 +1,140 @@ +From 7a617e7a27cc595f8eb1063b50210bbc70073a1b Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:12 +0200 +Subject: [PATCH 117/201] perf metric: Compute referenced metrics + +mainline inclusion +from mainline-v5.9-rc1 +commit 4ea2896715e6743ea79426106f3d078d78a80f9f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4ea2896715e6743ea79426106f3d078d78a80f9f + +---------------------------------------------------------------------- + +Adding computation (expr__parse call) of referenced metric at +the point when it needs to be resolved during the parent metric +computation. + +Once the inner metric is computed, the result is stored and +used if there's another usage of that metric. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-12-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/expr.c | 31 +++++++++++++++++++++++++++++++ + tools/perf/util/expr.h | 3 +++ + tools/perf/util/expr.y | 4 ++-- + 3 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index b5d0542792a0..c03ed6d9b0ac 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -109,6 +109,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) + */ + data_ptr->ref.metric_name = ref->metric_name; + data_ptr->ref.metric_expr = ref->metric_expr; ++ data_ptr->ref.counted = false; + data_ptr->is_ref = true; + + ret = hashmap__set(&ctx->ids, name, data_ptr, +@@ -130,6 +131,34 @@ int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1; + } + ++int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, ++ struct expr_id_data **datap) ++{ ++ struct expr_id_data *data; ++ ++ if (expr__get_id(ctx, id, datap) || !*datap) { ++ pr_debug("%s not found\n", id); ++ return -1; ++ } ++ ++ data = *datap; ++ ++ pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", ++ data->is_ref, data->ref.counted, data->val, id); ++ ++ if (data->is_ref && !data->ref.counted) { ++ data->ref.counted = true; ++ pr_debug("processing metric: %s ENTRY\n", id); ++ if (expr__parse(&data->val, ctx, data->ref.metric_expr, 1)) { ++ pr_debug("%s failed to count\n", id); ++ return -1; ++ } ++ pr_debug("processing metric: %s EXIT: %f\n", id, data->val); ++ } ++ ++ return 0; ++} ++ + void expr__del_id(struct expr_parse_ctx *ctx, const char *id) + { + struct expr_id_data *old_val = NULL; +@@ -170,6 +199,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, + void *scanner; + int ret; + ++ pr_debug2("parsing metric: %s\n", expr); ++ + ret = expr_lex_init_extra(&scanner_ctx, &scanner); + if (ret) + return ret; +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 81d04ff7f857..9ed208d93418 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -23,6 +23,7 @@ struct expr_id_data { + struct { + const char *metric_name; + const char *metric_expr; ++ bool counted; + } ref; + }; + +@@ -42,6 +43,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); + int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); + int expr__get_id(struct expr_parse_ctx *ctx, const char *id, + struct expr_id_data **data); ++int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, ++ struct expr_id_data **datap); + int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr, int runtime); + int expr__find_other(const char *expr, const char *one, +diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y +index 207dd371fed2..02703a874893 100644 +--- a/tools/perf/util/expr.y ++++ b/tools/perf/util/expr.y +@@ -77,11 +77,11 @@ expr: NUMBER + | ID { + struct expr_id_data *data; + +- if (expr__get_id(ctx, $1, &data) || !data) { +- pr_debug("%s not found\n", $1); ++ if (expr__resolve_id(ctx, $1, &data)) { + free($1); + YYABORT; + } ++ + $$ = data->val; + free($1); + } +-- +2.27.0 + diff --git a/patches/0235-perf-metric-Add-events-for-the-current-list.patch b/patches/0235-perf-metric-Add-events-for-the-current-list.patch new file mode 100644 index 0000000..fb5b29c --- /dev/null +++ b/patches/0235-perf-metric-Add-events-for-the-current-list.patch @@ -0,0 +1,87 @@ +From c2605dd49acf110bcb59df2ad07b1353cbf8dd6c Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:13 +0200 +Subject: [PATCH 118/201] perf metric: Add events for the current list + +mainline inclusion +from mainline-v5.9-rc1 +commit fc393839c11bbe2c7f1a44ab34e5f2a219d8366e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fc393839c11bbe2c7f1a44ab34e5f2a219d8366e + +---------------------------------------------------------------------- + +There's no need to iterate the whole list of groups, when adding new +events. The currently created groups are the ones we want to add. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-13-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index ef3f1d41f7db..4a3a24fab67e 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -834,6 +834,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + { + struct pmu_event *pe; + struct egroup *eg; ++ LIST_HEAD(list); + int i, ret; + bool has_match = false; + +@@ -841,7 +842,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + has_match = true; + eg = NULL; + +- ret = add_metric(group_list, pe, metric_no_group, &eg); ++ ret = add_metric(&list, pe, metric_no_group, &eg); + if (ret) + return ret; + +@@ -850,7 +851,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + * included in the expression. + */ + ret = resolve_metric(metric_no_group, +- group_list, map); ++ &list, map); + if (ret) + return ret; + } +@@ -859,7 +860,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + if (!has_match) + return -EINVAL; + +- list_for_each_entry(eg, group_list, nd) { ++ list_for_each_entry(eg, &list, nd) { + if (events->len > 0) + strbuf_addf(events, ","); + +@@ -871,6 +872,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + &eg->pctx); + } + } ++ ++ list_splice(&list, group_list); + return 0; + } + +-- +2.27.0 + diff --git a/patches/0236-perf-tests-Add-parse-metric-test-for-ipc-metric.patch b/patches/0236-perf-tests-Add-parse-metric-test-for-ipc-metric.patch new file mode 100644 index 0000000..8e7df39 --- /dev/null +++ b/patches/0236-perf-tests-Add-parse-metric-test-for-ipc-metric.patch @@ -0,0 +1,255 @@ +From 83d5f9550b4823ef28e1fef8d122a641a1607534 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:40 +0200 +Subject: [PATCH 119/201] perf tests: Add parse metric test for ipc metric + +mainline inclusion +from mainline-v5.9-rc1 +commit acf71b05d1a19726594a8436ba9d8af871941e6c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acf71b05d1a19726594a8436ba9d8af871941e6c + +---------------------------------------------------------------------- + +Adding new test that process metrics code and checks the expected +results. Starting with easy ipc metric. + +Committer testing: + + # perf test "Parse and process metrics" + 67: Parse and process metrics : Ok + # + # perf test -v "Parse and process metrics" + 67: Parse and process metrics : + --- start --- + test child forked, pid 103402 + metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC + found event inst_retired.any + found event cpu_clk_unhalted.thread + adding {inst_retired.any,cpu_clk_unhalted.thread}:W + test child finished with 0 + ---- end ---- + Parse and process metrics: Ok + # + +Had to fix it to initialize that 'struct value' array sentinel with a +named initializer to fix the build with some versions of clang: + + tests/parse-metric.c:135:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-13-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/Build | 1 + + tools/perf/tests/builtin-test.c | 4 + + tools/perf/tests/parse-metric.c | 145 ++++++++++++++++++++++++++++++++ + tools/perf/tests/tests.h | 1 + + 4 files changed, 151 insertions(+) + create mode 100644 tools/perf/tests/parse-metric.c + +diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build +index d28758661fb7..da2249118b6f 100644 +--- a/tools/perf/tests/Build ++++ b/tools/perf/tests/Build +@@ -51,6 +51,7 @@ perf-y += clang.o + perf-y += unit_number__scnprintf.o + perf-y += mem2node.o + perf-y += demangle-java-test.o ++perf-y += parse-metric.o + + $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build + $(call rule_mkdir) +diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c +index b4b1e34aaef4..ef1cbbba848f 100644 +--- a/tools/perf/tests/builtin-test.c ++++ b/tools/perf/tests/builtin-test.c +@@ -294,6 +294,10 @@ static struct test generic_tests[] = { + .desc = "Demangle Java", + .func = test__demangle_java, + }, ++ { ++ .desc = "Parse and process metrics", ++ .func = test__parse_metric, ++ }, + { + .func = NULL, + }, +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +new file mode 100644 +index 000000000000..77a2199c2a85 +--- /dev/null ++++ b/tools/perf/tests/parse-metric.c +@@ -0,0 +1,145 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++#include "cpumap.h" ++#include "evlist.h" ++#include "metricgroup.h" ++#include "tests.h" ++#include "pmu-events/pmu-events.h" ++#include "evlist.h" ++#include "rblist.h" ++#include "debug.h" ++#include "expr.h" ++#include "stat.h" ++ ++static struct pmu_event pme_test[] = { ++{ ++ .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", ++ .metric_name = "IPC", ++}, ++}; ++ ++static struct pmu_events_map map = { ++ .cpuid = "test", ++ .version = "1", ++ .type = "core", ++ .table = pme_test, ++}; ++ ++struct value { ++ const char *event; ++ u64 val; ++}; ++ ++static u64 find_value(const char *name, struct value *values) ++{ ++ struct value *v = values; ++ ++ while (v->event) { ++ if (!strcmp(name, v->event)) ++ return v->val; ++ v++; ++ }; ++ return 0; ++} ++ ++static void load_runtime_stat(struct runtime_stat *st, struct perf_evlist *evlist, ++ struct value *vals) ++{ ++ struct perf_evsel *evsel; ++ u64 count; ++ ++ evlist__for_each_entry(evlist, evsel) { ++ count = find_value(evsel->name, vals); ++ perf_stat__update_shadow_stats(evsel, count, 0, st); ++ } ++} ++ ++static double compute_single(struct rblist *metric_events, struct perf_evlist *evlist, ++ struct runtime_stat *st) ++{ ++ struct perf_evsel *evsel = perf_evlist__first(evlist); ++ struct metric_event *me; ++ ++ me = metricgroup__lookup(metric_events, evsel, false); ++ if (me != NULL) { ++ struct metric_expr *mexp; ++ ++ mexp = list_first_entry(&me->head, struct metric_expr, nd); ++ return test_generic_metric(mexp, 0, st); ++ } ++ return 0.; ++} ++ ++static int compute_metric(const char *name, struct value *vals, double *ratio) ++{ ++ struct rblist metric_events = { ++ .nr_entries = 0, ++ }; ++ struct cpu_map *cpus; ++ struct runtime_stat st; ++ struct perf_evlist *evlist; ++ int err; ++ ++ /* ++ * We need to prepare evlist for stat mode running on CPU 0 ++ * because that's where all the stats are going to be created. ++ */ ++ evlist = perf_evlist__new(); ++ if (!evlist) ++ return -ENOMEM; ++ ++ cpus = cpu_map__new("0"); ++ if (!cpus) ++ return -ENOMEM; ++ ++ perf_evlist__set_maps(evlist, cpus, NULL); ++ ++ /* Parse the metric into metric_events list. */ ++ err = metricgroup__parse_groups_test(evlist, &map, name, ++ false, false, ++ &metric_events); ++ ++ TEST_ASSERT_VAL("failed to parse metric", err == 0); ++ ++ if (perf_evlist__alloc_stats(evlist, false)) ++ return -1; ++ ++ /* Load the runtime stats with given numbers for events. */ ++ runtime_stat__init(&st); ++ load_runtime_stat(&st, evlist, vals); ++ ++ /* And execute the metric */ ++ *ratio = compute_single(&metric_events, evlist, &st); ++ ++ /* ... clenup. */ ++ metricgroup__rblist_exit(&metric_events); ++ runtime_stat__exit(&st); ++ perf_evlist__free_stats(evlist); ++ cpu_map__put(cpus); ++ perf_evlist__delete(evlist); ++ return 0; ++} ++ ++static int test_ipc(void) ++{ ++ double ratio; ++ struct value vals[] = { ++ { .event = "inst_retired.any", .val = 300 }, ++ { .event = "cpu_clk_unhalted.thread", .val = 200 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to compute metric", ++ compute_metric("IPC", vals, &ratio) == 0); ++ ++ TEST_ASSERT_VAL("IPC failed, wrong ratio", ++ ratio == 1.5); ++ return 0; ++} ++ ++int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) ++{ ++ TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); ++ return 0; ++} +diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h +index 897ca3e7812c..506e9aa59bae 100644 +--- a/tools/perf/tests/tests.h ++++ b/tools/perf/tests/tests.h +@@ -110,6 +110,7 @@ int test__clang_subtest_get_nr(void); + int test__unit_number__scnprint(struct test *test, int subtest); + int test__mem2node(struct test *t, int subtest); + int test__demangle_java(struct test *test, int subtest); ++int test__parse_metric(struct test *test, int subtest); + + bool test__bp_signal_is_supported(void); + +-- +2.27.0 + diff --git a/patches/0237-perf-tests-Add-parse-metric-test-for-frontend-metric.patch b/patches/0237-perf-tests-Add-parse-metric-test-for-frontend-metric.patch new file mode 100644 index 0000000..f2e5f08 --- /dev/null +++ b/patches/0237-perf-tests-Add-parse-metric-test-for-frontend-metric.patch @@ -0,0 +1,112 @@ +From 363546e8528e51f0fc5040c0ace71277bcc02a9c Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Tue, 2 Jun 2020 23:47:41 +0200 +Subject: [PATCH 120/201] perf tests: Add parse metric test for frontend metric + +mainline inclusion +from mainline-v5.9-rc1 +commit 98461d9dc115a2ef555ad114866e8acdc6377aaa +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=98461d9dc115a2ef555ad114866e8acdc6377aaa + +---------------------------------------------------------------------- + +Adding new metric test for frontend metric. It's stolen from x86 pmu +events. + +Committer testing: + + # perf test "Parse and process metrics" + 67: Parse and process metrics : Ok + # perf test -v "Parse and process metrics" + # + 67: Parse and process metrics : + --- start --- + test child forked, pid 104881 + metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC + found event inst_retired.any + found event cpu_clk_unhalted.thread + adding {inst_retired.any,cpu_clk_unhalted.thread}:W + metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT + found event cpu_clk_unhalted.one_thread_active + found event cpu_clk_unhalted.ref_xclk + found event idq_uops_not_delivered.core + found event cpu_clk_unhalted.thread + adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W + test child finished with 0 + ---- end ---- + Parse and process metrics: Ok + # + +Had to fix it to initialize that 'struct value' array sentinel with a +named initializer to fix the build with some versions of clang: + + tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + +Signed-off-by: Jiri Olsa +Acked-by: Ian Rogers +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-metric.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 77a2199c2a85..79145cfc4b00 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -17,6 +17,11 @@ static struct pmu_event pme_test[] = { + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", + }, ++{ ++ .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " ++ "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", ++ .metric_name = "Frontend_Bound_SMT", ++}, + }; + + static struct pmu_events_map map = { +@@ -138,8 +143,28 @@ static int test_ipc(void) + return 0; + } + ++static int test_frontend(void) ++{ ++ double ratio; ++ struct value vals[] = { ++ { .event = "idq_uops_not_delivered.core", .val = 300 }, ++ { .event = "cpu_clk_unhalted.thread", .val = 200 }, ++ { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 }, ++ { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to compute metric", ++ compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0); ++ ++ TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio", ++ ratio == 0.45); ++ return 0; ++} ++ + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) + { + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); ++ TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); + return 0; + } +-- +2.27.0 + diff --git a/patches/0238-perf-metric-Add-cache_miss_cycles-to-metric-parse-te.patch b/patches/0238-perf-metric-Add-cache_miss_cycles-to-metric-parse-te.patch new file mode 100644 index 0000000..67ba08f --- /dev/null +++ b/patches/0238-perf-metric-Add-cache_miss_cycles-to-metric-parse-te.patch @@ -0,0 +1,99 @@ +From f44426297c25f55c7f153f1fc6acb2285263d62a Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:14 +0200 +Subject: [PATCH 121/201] perf metric: Add cache_miss_cycles to metric parse + test + +mainline inclusion +from mainline-v5.9-rc1 +commit 55f30d68397df7d67367a0643d9dea7cbbcda061 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55f30d68397df7d67367a0643d9dea7cbbcda061 + +---------------------------------------------------------------------- + +Adding test that compute metric with other metrics in it. + cache_miss_cycles = metric:dcache_miss_cpi + metric:icache_miss_cycles + +Committer notes: + +Fixed up initializer to cope with: + + tests/parse-metric.c:242:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-14-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-metric.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 79145cfc4b00..09170f0d1107 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -22,6 +22,18 @@ static struct pmu_event pme_test[] = { + "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", + .metric_name = "Frontend_Bound_SMT", + }, ++{ ++ .metric_expr = "l1d\\-loads\\-misses / inst_retired.any", ++ .metric_name = "dcache_miss_cpi", ++}, ++{ ++ .metric_expr = "l1i\\-loads\\-misses / inst_retired.any", ++ .metric_name = "icache_miss_cycles", ++}, ++{ ++ .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)", ++ .metric_name = "cache_miss_cycles", ++}, + }; + + static struct pmu_events_map map = { +@@ -162,9 +174,28 @@ static int test_frontend(void) + return 0; + } + ++static int test_cache_miss_cycles(void) ++{ ++ double ratio; ++ struct value vals[] = { ++ { .event = "l1d-loads-misses", .val = 300 }, ++ { .event = "l1i-loads-misses", .val = 200 }, ++ { .event = "inst_retired.any", .val = 400 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to compute metric", ++ compute_metric("cache_miss_cycles", vals, &ratio) == 0); ++ ++ TEST_ASSERT_VAL("cache_miss_cycles failed, wrong ratio", ++ ratio == 1.25); ++ return 0; ++} ++ + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) + { + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); ++ TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); + return 0; + } +-- +2.27.0 + diff --git a/patches/0239-perf-metric-Add-DCache_L2-to-metric-parse-test.patch b/patches/0239-perf-metric-Add-DCache_L2-to-metric-parse-test.patch new file mode 100644 index 0000000..65bd30f --- /dev/null +++ b/patches/0239-perf-metric-Add-DCache_L2-to-metric-parse-test.patch @@ -0,0 +1,139 @@ +From fe1c9c5f4018c7d629164e2d3932a88e1d5d0f51 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:15 +0200 +Subject: [PATCH 122/201] perf metric: Add DCache_L2 to metric parse test + +mainline inclusion +from mainline-v5.9-rc1 +commit 5a606f3b9c85ea024a8071765a523c85df93c454 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5a606f3b9c85ea024a8071765a523c85df93c454 + +---------------------------------------------------------------------- + +Adding test that compute DCache_L2 metrics with other related metrics in it. + +Committer notes: + +Fixed up this: + + tests/parse-metric.c:285:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + ^ + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-15-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-metric.c | 71 +++++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 09170f0d1107..2df9ecae4179 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -34,6 +34,27 @@ static struct pmu_event pme_test[] = { + .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)", + .metric_name = "cache_miss_cycles", + }, ++{ ++ .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit", ++ .metric_name = "DCache_L2_All_Hits", ++}, ++{ ++ .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + " ++ "l2_rqsts.pf_miss + l2_rqsts.rfo_miss", ++ .metric_name = "DCache_L2_All_Miss", ++}, ++{ ++ .metric_expr = "dcache_l2_all_hits + dcache_l2_all_miss", ++ .metric_name = "DCache_L2_All", ++}, ++{ ++ .metric_expr = "d_ratio(dcache_l2_all_hits, dcache_l2_all)", ++ .metric_name = "DCache_L2_Hits", ++}, ++{ ++ .metric_expr = "d_ratio(dcache_l2_all_miss, dcache_l2_all)", ++ .metric_name = "DCache_L2_Misses", ++}, + }; + + static struct pmu_events_map map = { +@@ -192,10 +213,60 @@ static int test_cache_miss_cycles(void) + return 0; + } + ++ ++/* ++ * DCache_L2_All_Hits = l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hi ++ * DCache_L2_All_Miss = max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + ++ * l2_rqsts.pf_miss + l2_rqsts.rfo_miss ++ * DCache_L2_All = dcache_l2_all_hits + dcache_l2_all_miss ++ * DCache_L2_Hits = d_ratio(dcache_l2_all_hits, dcache_l2_all) ++ * DCache_L2_Misses = d_ratio(dcache_l2_all_miss, dcache_l2_all) ++ * ++ * l2_rqsts.demand_data_rd_hit = 100 ++ * l2_rqsts.pf_hit = 200 ++ * l2_rqsts.rfo_hi = 300 ++ * l2_rqsts.all_demand_data_rd = 400 ++ * l2_rqsts.pf_miss = 500 ++ * l2_rqsts.rfo_miss = 600 ++ * ++ * DCache_L2_All_Hits = 600 ++ * DCache_L2_All_Miss = MAX(400 - 100, 0) + 500 + 600 = 1400 ++ * DCache_L2_All = 600 + 1400 = 2000 ++ * DCache_L2_Hits = 600 / 2000 = 0.3 ++ * DCache_L2_Misses = 1400 / 2000 = 0.7 ++ */ ++static int test_dcache_l2(void) ++{ ++ double ratio; ++ struct value vals[] = { ++ { .event = "l2_rqsts.demand_data_rd_hit", .val = 100 }, ++ { .event = "l2_rqsts.pf_hit", .val = 200 }, ++ { .event = "l2_rqsts.rfo_hit", .val = 300 }, ++ { .event = "l2_rqsts.all_demand_data_rd", .val = 400 }, ++ { .event = "l2_rqsts.pf_miss", .val = 500 }, ++ { .event = "l2_rqsts.rfo_miss", .val = 600 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to compute metric", ++ compute_metric("DCache_L2_Hits", vals, &ratio) == 0); ++ ++ TEST_ASSERT_VAL("DCache_L2_Hits failed, wrong ratio", ++ ratio == 0.3); ++ ++ TEST_ASSERT_VAL("failed to compute metric", ++ compute_metric("DCache_L2_Misses", vals, &ratio) == 0); ++ ++ TEST_ASSERT_VAL("DCache_L2_Misses failed, wrong ratio", ++ ratio == 0.7); ++ return 0; ++} ++ + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) + { + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); + TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); ++ TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0); + return 0; + } +-- +2.27.0 + diff --git a/patches/0240-perf-metric-Add-recursion-check-when-processing-nest.patch b/patches/0240-perf-metric-Add-recursion-check-when-processing-nest.patch new file mode 100644 index 0000000..6f3a95b --- /dev/null +++ b/patches/0240-perf-metric-Add-recursion-check-when-processing-nest.patch @@ -0,0 +1,442 @@ +From 18b75e1ebc1d9cfc78278b171df06416e3ab1dea Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:16 +0200 +Subject: [PATCH 123/201] perf metric: Add recursion check when processing + nested metrics + +mainline inclusion +from mainline-v5.9-rc1 +commit f6fb0960f920e3040088992f32bbceded7a74322 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f6fb0960f920e3040088992f32bbceded7a74322 + +---------------------------------------------------------------------- + +Keeping the stack of nested metrics via 'struct expr_id' objects +and checking if we are in recursion via already processed metric. + +The stack is implemented as static array within the struct egroup +with 100 entries, which should be enough nesting depth for any +metric we have or plan to have at the moment. + +Adding test that simulates the recursion and checks we can +detect it. + +Committer notes: + +Bumped RECURSION_ID_MAX to 1000 as per Jiri's reply to Paul Clark on the +patch series e-mail discussion. + +Fixed these: + + tests/parse-metric.c:308:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + ^ + + util/metricgroup.c:924:28: error: missing field 'parent' initializer [-Werror,-Wmissing-field-initializers] + struct expr_ids ids = { 0 }; + ^ + util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] + struct expr_ids ids = { 0 }; + ^ + {} + util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] + struct expr_ids ids = { 0 }; + ^ + {} + util/metricgroup.c:924:28: error: missing field 'cnt' initializer [-Werror,-Wmissing-field-initializers] + struct expr_ids ids = { 0 }; + ^ + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-16-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: HKM13278 <1327847446@qq.com> +--- + tools/perf/tests/parse-metric.c | 34 ++++++++- + tools/perf/util/expr.c | 2 + + tools/perf/util/expr.h | 9 ++- + tools/perf/util/metricgroup.c | 122 ++++++++++++++++++++++++++++---- + 4 files changed, 152 insertions(+), 15 deletions(-) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 2df9ecae4179..fde9129eb3be 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -55,6 +55,18 @@ static struct pmu_event pme_test[] = { + .metric_expr = "d_ratio(dcache_l2_all_miss, dcache_l2_all)", + .metric_name = "DCache_L2_Misses", + }, ++{ ++ .metric_expr = "ipc + m2", ++ .metric_name = "M1", ++}, ++{ ++ .metric_expr = "ipc + m1", ++ .metric_name = "M2", ++}, ++{ ++ .metric_expr = "1/m3", ++ .metric_name = "M3", ++} + }; + + static struct pmu_events_map map = { +@@ -137,8 +149,8 @@ static int compute_metric(const char *name, struct value *vals, double *ratio) + err = metricgroup__parse_groups_test(evlist, &map, name, + false, false, + &metric_events); +- +- TEST_ASSERT_VAL("failed to parse metric", err == 0); ++ if (err) ++ return err; + + if (perf_evlist__alloc_stats(evlist, false)) + return -1; +@@ -262,11 +274,29 @@ static int test_dcache_l2(void) + return 0; + } + ++static int test_recursion_fail(void) ++{ ++ double ratio; ++ struct value vals[] = { ++ { .event = "inst_retired.any", .val = 300 }, ++ { .event = "cpu_clk_unhalted.thread", .val = 200 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to find recursion", ++ compute_metric("M1", vals, &ratio) == -1); ++ ++ TEST_ASSERT_VAL("failed to find recursion", ++ compute_metric("M3", vals, &ratio) == -1); ++ return 0; ++} ++ + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) + { + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); + TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); + TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0); ++ TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0); + return 0; + } +diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c +index c03ed6d9b0ac..77122818b519 100644 +--- a/tools/perf/util/expr.c ++++ b/tools/perf/util/expr.c +@@ -44,6 +44,8 @@ int expr__add_id(struct expr_parse_ctx *ctx, const char *id) + if (!data_ptr) + return -ENOMEM; + ++ data_ptr->parent = ctx->parent; ++ + ret = hashmap__set(&ctx->ids, id, data_ptr, + (const void **)&old_key, (void **)&old_data); + if (ret) +diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h +index 9ed208d93418..fc2b5e824a66 100644 +--- a/tools/perf/util/expr.h ++++ b/tools/perf/util/expr.h +@@ -13,8 +13,14 @@ + + struct metric_ref; + ++struct expr_id { ++ char *id; ++ struct expr_id *parent; ++}; ++ + struct expr_parse_ctx { +- struct hashmap ids; ++ struct hashmap ids; ++ struct expr_id *parent; + }; + + struct expr_id_data { +@@ -25,6 +31,7 @@ struct expr_id_data { + const char *metric_expr; + bool counted; + } ref; ++ struct expr_id *parent; + }; + + bool is_ref; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 4a3a24fab67e..c32c2574c378 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -30,6 +30,7 @@ + #include + #include + #include "util.h" ++#include + + struct metric_event *metricgroup__lookup(struct rblist *metric_events, + struct perf_evsel *evsel, +@@ -132,6 +133,28 @@ struct egroup { + bool has_constraint; + }; + ++#define RECURSION_ID_MAX 1000 ++ ++struct expr_ids { ++ struct expr_id id[RECURSION_ID_MAX]; ++ int cnt; ++}; ++ ++static struct expr_id *expr_ids__alloc(struct expr_ids *ids) ++{ ++ if (ids->cnt >= RECURSION_ID_MAX) ++ return NULL; ++ return &ids->id[ids->cnt++]; ++} ++ ++static void expr_ids__exit(struct expr_ids *ids) ++{ ++ int i; ++ ++ for (i = 0; i < ids->cnt; i++) ++ free(ids->id[i].id); ++} ++ + /** + * Find a group of events in perf_evlist that correpond to those from a parsed + * metric expression. Note, as find_evsel_group is called in the same order as +@@ -627,7 +650,9 @@ static int __add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, + int runtime, +- struct egroup **egp) ++ struct egroup **egp, ++ struct expr_id *parent, ++ struct expr_ids *ids) + { + struct metric_ref_node *ref; + struct egroup *eg; +@@ -637,7 +662,7 @@ static int __add_metric(struct list_head *group_list, + * We got in here for the parent group, + * allocate it and put it on the list. + */ +- eg = malloc(sizeof(*eg)); ++ eg = zalloc(sizeof(*eg)); + if (!eg) + return -ENOMEM; + +@@ -650,6 +675,18 @@ static int __add_metric(struct list_head *group_list, + INIT_LIST_HEAD(&eg->metric_refs); + eg->metric_refs_cnt = 0; + *egp = eg; ++ ++ parent = expr_ids__alloc(ids); ++ if (!parent) { ++ free(eg); ++ return -EINVAL; ++ } ++ ++ parent->id = strdup(pe->metric_name); ++ if (!parent->id) { ++ free(eg); ++ return -ENOMEM; ++ } + } else { + /* + * We got here for the referenced metric, via the +@@ -675,6 +712,10 @@ static int __add_metric(struct list_head *group_list, + eg->metric_refs_cnt++; + } + ++ /* Force all found IDs in metric to have us as parent ID. */ ++ WARN_ON_ONCE(!parent); ++ eg->pctx.parent = parent; ++ + /* + * For both the parent and referenced metrics, we parse + * all the metric's IDs and add it to the parent context. +@@ -735,15 +776,62 @@ static struct pmu_event *find_metric(const char *metric, struct pmu_events_map * + return NULL; + } + ++static int recursion_check(struct egroup *eg, const char *id, struct expr_id **parent, ++ struct expr_ids *ids) ++{ ++ struct expr_id_data *data; ++ struct expr_id *p; ++ int ret; ++ ++ /* ++ * We get the parent referenced by 'id' argument and ++ * traverse through all the parent object IDs to check ++ * if we already processed 'id', if we did, it's recursion ++ * and we fail. ++ */ ++ ret = expr__get_id(&eg->pctx, id, &data); ++ if (ret) ++ return ret; ++ ++ p = data->parent; ++ ++ while (p->parent) { ++ if (!strcmp(p->id, id)) { ++ pr_err("failed: recursion detected for %s\n", id); ++ return -1; ++ } ++ p = p->parent; ++ } ++ ++ /* ++ * If we are over the limit of static entris, the metric ++ * is too difficult/nested to process, fail as well. ++ */ ++ p = expr_ids__alloc(ids); ++ if (!p) { ++ pr_err("failed: too many nested metrics\n"); ++ return -EINVAL; ++ } ++ ++ p->id = strdup(id); ++ p->parent = data->parent; ++ *parent = p; ++ ++ return p->id ? 0 : -ENOMEM; ++} ++ + static int add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, +- struct egroup **egp); ++ struct egroup **egp, ++ struct expr_id *parent, ++ struct expr_ids *ids); + + static int __resolve_metric(struct egroup *eg, + bool metric_no_group, + struct list_head *group_list, +- struct pmu_events_map *map) ++ struct pmu_events_map *map, ++ struct expr_ids *ids) + { + struct hashmap_entry *cur; + size_t bkt; +@@ -757,18 +845,23 @@ static int __resolve_metric(struct egroup *eg, + do { + all = true; + hashmap__for_each_entry((&eg->pctx.ids), cur, bkt) { ++ struct expr_id *parent; + struct pmu_event *pe; + + pe = find_metric(cur->key, map); + if (!pe) + continue; + ++ ret = recursion_check(eg, cur->key, &parent, ids); ++ if (ret) ++ return ret; ++ + all = false; + /* The metric key itself needs to go out.. */ + expr__del_id(&eg->pctx, cur->key); + + /* ... and it gets resolved to the parent context. */ +- ret = add_metric(group_list, pe, metric_no_group, &eg); ++ ret = add_metric(group_list, pe, metric_no_group, &eg, parent, ids); + if (ret) + return ret; + +@@ -785,13 +878,14 @@ static int __resolve_metric(struct egroup *eg, + + static int resolve_metric(bool metric_no_group, + struct list_head *metric_list, +- struct pmu_events_map *map) ++ struct pmu_events_map *map, ++ struct expr_ids *ids) + { + struct egroup *eg; + int err; + + list_for_each_entry(eg, metric_list, nd) { +- err = __resolve_metric(eg, metric_no_group, metric_list, map); ++ err = __resolve_metric(eg, metric_no_group, metric_list, map, ids); + if (err) + return err; + } +@@ -801,7 +895,9 @@ static int resolve_metric(bool metric_no_group, + static int add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, +- struct egroup **egp) ++ struct egroup **egp, ++ struct expr_id *parent, ++ struct expr_ids *ids) + { + struct egroup *orig = *egp; + int ret = 0; +@@ -809,7 +905,7 @@ static int add_metric(struct list_head *group_list, + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __add_metric(group_list, pe, metric_no_group, 1, egp); ++ ret = __add_metric(group_list, pe, metric_no_group, 1, egp, parent, ids); + } else { + int j, count; + +@@ -821,7 +917,7 @@ static int add_metric(struct list_head *group_list, + */ + + for (j = 0; j < count && !ret; j++, *egp = orig) +- ret = __add_metric(group_list, pe, metric_no_group, j, egp); ++ ret = __add_metric(group_list, pe, metric_no_group, j, egp, parent, ids); + } + + return ret; +@@ -832,6 +928,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct list_head *group_list, + struct pmu_events_map *map) + { ++ struct expr_ids ids = { .cnt = 0, }; + struct pmu_event *pe; + struct egroup *eg; + LIST_HEAD(list); +@@ -842,7 +939,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + has_match = true; + eg = NULL; + +- ret = add_metric(&list, pe, metric_no_group, &eg); ++ ret = add_metric(&list, pe, metric_no_group, &eg, NULL, &ids); + if (ret) + return ret; + +@@ -851,7 +948,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + * included in the expression. + */ + ret = resolve_metric(metric_no_group, +- &list, map); ++ &list, map, &ids); + if (ret) + return ret; + } +@@ -874,6 +971,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + } + + list_splice(&list, group_list); ++ expr_ids__exit(&ids); + return 0; + } + +-- +2.27.0 + diff --git a/patches/0241-perf-metric-Make-compute_single-function-more-precis.patch b/patches/0241-perf-metric-Make-compute_single-function-more-precis.patch new file mode 100644 index 0000000..aaaba8b --- /dev/null +++ b/patches/0241-perf-metric-Make-compute_single-function-more-precis.patch @@ -0,0 +1,91 @@ +From c7bcaf433a7e4de4f6eee77264e719792e7c14bd Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:17 +0200 +Subject: [PATCH 124/201] perf metric: Make compute_single function more + precise + +mainline inclusion +from mainline-v5.9-rc1 +commit b81ef466ace6bf9bfd7e63a4c2bc89721ee0d495 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b81ef466ace6bf9bfd7e63a4c2bc89721ee0d495 + +---------------------------------------------------------------------- + +So far compute_single function relies on the fact, that there's only +single metric defined within evlist in all tests. In following patch we +will add test for metric group, so we need to be able to compute metric +by given name. + +Adding the name argument to compute_single and iterating evlist and +evsel's expression to find the given metric. + +Signed-off-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: John Garry +Cc: Kajol Jain +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-17-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/parse-metric.c +--- + tools/perf/tests/parse-metric.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index fde9129eb3be..f8c58f7f8e55 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -106,17 +106,21 @@ static void load_runtime_stat(struct runtime_stat *st, struct perf_evlist *evlis + } + + static double compute_single(struct rblist *metric_events, struct perf_evlist *evlist, +- struct runtime_stat *st) ++ struct runtime_stat *st, const char *name) + { +- struct perf_evsel *evsel = perf_evlist__first(evlist); ++ struct metric_expr *mexp; + struct metric_event *me; ++ struct perf_evsel *evsel; + +- me = metricgroup__lookup(metric_events, evsel, false); +- if (me != NULL) { +- struct metric_expr *mexp; +- +- mexp = list_first_entry(&me->head, struct metric_expr, nd); +- return test_generic_metric(mexp, 0, st); ++ evlist__for_each_entry(evlist, evsel) { ++ me = metricgroup__lookup(metric_events, evsel, false); ++ if (me != NULL) { ++ list_for_each_entry (mexp, &me->head, nd) { ++ if (strcmp(mexp->metric_name, name)) ++ continue; ++ return test_generic_metric(mexp, 0, st); ++ } ++ } + } + return 0.; + } +@@ -160,7 +164,7 @@ static int compute_metric(const char *name, struct value *vals, double *ratio) + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ +- *ratio = compute_single(&metric_events, evlist, &st); ++ *ratio = compute_single(&metric_events, evlist, &st, name); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); +-- +2.27.0 + diff --git a/patches/0242-perf-metric-Add-metric-group-test.patch b/patches/0242-perf-metric-Add-metric-group-test.patch new file mode 100644 index 0000000..c856fc6 --- /dev/null +++ b/patches/0242-perf-metric-Add-metric-group-test.patch @@ -0,0 +1,147 @@ +From 9b3115e0c7f96d66b85110725c05e1982aacbb6c Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:18 +0200 +Subject: [PATCH 125/201] perf metric: Add metric group test + +mainline inclusion +from mainline-v5.9-rc1 +commit dfce77c580e02c19efacfe9110261c935d1ddb60 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dfce77c580e02c19efacfe9110261c935d1ddb60 + +---------------------------------------------------------------------- + +Adding test for metric group plus compute_metric_group function to get +metrics values within the group. + +Committer notes: + +Fixed this; + + tests/parse-metric.c:327:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] + { 0 }, + ^ + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-18-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-metric.c | 48 +++++++++++++++++++++++++++++++-- + 1 file changed, 46 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index f8c58f7f8e55..007da421bf95 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -16,6 +16,7 @@ static struct pmu_event pme_test[] = { + { + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", ++ .metric_group = "group1", + }, + { + .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " +@@ -33,6 +34,7 @@ static struct pmu_event pme_test[] = { + { + .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)", + .metric_name = "cache_miss_cycles", ++ .metric_group = "group1", + }, + { + .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit", +@@ -125,7 +127,9 @@ static double compute_single(struct rblist *metric_events, struct perf_evlist *e + return 0.; + } + +-static int compute_metric(const char *name, struct value *vals, double *ratio) ++static int __compute_metric(const char *name, struct value *vals, ++ const char *name1, double *ratio1, ++ const char *name2, double *ratio2) + { + struct rblist metric_events = { + .nr_entries = 0, +@@ -164,7 +168,10 @@ static int compute_metric(const char *name, struct value *vals, double *ratio) + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ +- *ratio = compute_single(&metric_events, evlist, &st, name); ++ if (name1 && ratio1) ++ *ratio1 = compute_single(&metric_events, evlist, &st, name1); ++ if (name2 && ratio2) ++ *ratio2 = compute_single(&metric_events, evlist, &st, name2); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); +@@ -175,6 +182,18 @@ static int compute_metric(const char *name, struct value *vals, double *ratio) + return 0; + } + ++static int compute_metric(const char *name, struct value *vals, double *ratio) ++{ ++ return __compute_metric(name, vals, name, ratio, NULL, NULL); ++} ++ ++static int compute_metric_group(const char *name, struct value *vals, ++ const char *name1, double *ratio1, ++ const char *name2, double *ratio2) ++{ ++ return __compute_metric(name, vals, name1, ratio1, name2, ratio2); ++} ++ + static int test_ipc(void) + { + double ratio; +@@ -295,6 +314,30 @@ static int test_recursion_fail(void) + return 0; + } + ++static int test_metric_group(void) ++{ ++ double ratio1, ratio2; ++ struct value vals[] = { ++ { .event = "cpu_clk_unhalted.thread", .val = 200 }, ++ { .event = "l1d-loads-misses", .val = 300 }, ++ { .event = "l1i-loads-misses", .val = 200 }, ++ { .event = "inst_retired.any", .val = 400 }, ++ { .event = NULL, }, ++ }; ++ ++ TEST_ASSERT_VAL("failed to find recursion", ++ compute_metric_group("group1", vals, ++ "IPC", &ratio1, ++ "cache_miss_cycles", &ratio2) == 0); ++ ++ TEST_ASSERT_VAL("group IPC failed, wrong ratio", ++ ratio1 == 2.0); ++ ++ TEST_ASSERT_VAL("group cache_miss_cycles failed, wrong ratio", ++ ratio2 == 1.25); ++ return 0; ++} ++ + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) + { + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); +@@ -302,5 +345,6 @@ int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unu + TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); + TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0); + TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0); ++ TEST_ASSERT_VAL("test metric group", test_metric_group() == 0); + return 0; + } +-- +2.27.0 + diff --git a/patches/0243-perf-metric-Rename-struct-egroup-to-metric.patch b/patches/0243-perf-metric-Rename-struct-egroup-to-metric.patch new file mode 100644 index 0000000..d819114 --- /dev/null +++ b/patches/0243-perf-metric-Rename-struct-egroup-to-metric.patch @@ -0,0 +1,448 @@ +From d5336d6f6fd14c62e7a58c4a8a67e1ded9219557 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:19 +0200 +Subject: [PATCH 126/201] perf metric: Rename struct egroup to metric + +mainline inclusion +from mainline-v5.9-rc1 +commit a0c05b363827461a5762065c1c0f348c8ce6aa13 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a0c05b363827461a5762065c1c0f348c8ce6aa13 + +---------------------------------------------------------------------- + +Renaming struct egroup to metric, because it seems to make more sense. +Plus renaming all the variables that hold egroup to appropriate names. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-19-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 150 +++++++++++++++++----------------- + 1 file changed, 75 insertions(+), 75 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index c32c2574c378..9a371757e746 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -121,7 +121,7 @@ struct metric_ref_node { + struct list_head list; + }; + +-struct egroup { ++struct metric { + struct list_head nd; + struct expr_parse_ctx pctx; + const char *metric_name; +@@ -268,7 +268,7 @@ static int metricgroup__setup_events(struct list_head *groups, + struct metric_expr *expr; + int i = 0; + int ret = 0; +- struct egroup *eg; ++ struct metric *m; + struct perf_evsel *evsel, *tmp; + unsigned long *evlist_used; + +@@ -276,23 +276,23 @@ static int metricgroup__setup_events(struct list_head *groups, + if (!evlist_used) + return -ENOMEM; + +- list_for_each_entry (eg, groups, nd) { ++ list_for_each_entry (m, groups, nd) { + struct perf_evsel **metric_events; + struct metric_ref *metric_refs = NULL; + + metric_events = calloc(sizeof(void *), +- hashmap__size(&eg->pctx.ids) + 1); ++ hashmap__size(&m->pctx.ids) + 1); + if (!metric_events) { + ret = -ENOMEM; + break; + } +- evsel = find_evsel_group(perf_evlist, &eg->pctx, ++ evsel = find_evsel_group(perf_evlist, &m->pctx, + metric_no_merge, +- eg->has_constraint, metric_events, ++ m->has_constraint, metric_events, + evlist_used); + if (!evsel) { + pr_debug("Cannot resolve %s: %s\n", +- eg->metric_name, eg->metric_expr); ++ m->metric_name, m->metric_expr); + free(metric_events); + continue; + } +@@ -315,10 +315,10 @@ static int metricgroup__setup_events(struct list_head *groups, + * Collect and store collected nested expressions + * for metric processing. + */ +- if (eg->metric_refs_cnt) { ++ if (m->metric_refs_cnt) { + struct metric_ref_node *ref; + +- metric_refs = zalloc(sizeof(struct metric_ref) * (eg->metric_refs_cnt + 1)); ++ metric_refs = zalloc(sizeof(struct metric_ref) * (m->metric_refs_cnt + 1)); + if (!metric_refs) { + ret = -ENOMEM; + free(metric_events); +@@ -326,7 +326,7 @@ static int metricgroup__setup_events(struct list_head *groups, + } + + i = 0; +- list_for_each_entry(ref, &eg->metric_refs, list) { ++ list_for_each_entry(ref, &m->metric_refs, list) { + /* + * Intentionally passing just const char pointers, + * originally from 'struct pmu_event' object. +@@ -340,11 +340,11 @@ static int metricgroup__setup_events(struct list_head *groups, + }; + + expr->metric_refs = metric_refs; +- expr->metric_expr = eg->metric_expr; +- expr->metric_name = eg->metric_name; +- expr->metric_unit = eg->metric_unit; ++ expr->metric_expr = m->metric_expr; ++ expr->metric_name = m->metric_name; ++ expr->metric_unit = m->metric_unit; + expr->metric_events = metric_events; +- expr->runtime = eg->runtime; ++ expr->runtime = m->runtime; + list_add(&expr->nd, &me->head); + } + +@@ -650,41 +650,41 @@ static int __add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, + int runtime, +- struct egroup **egp, ++ struct metric **mp, + struct expr_id *parent, + struct expr_ids *ids) + { + struct metric_ref_node *ref; +- struct egroup *eg; ++ struct metric *m; + +- if (*egp == NULL) { ++ if (*mp == NULL) { + /* + * We got in here for the parent group, + * allocate it and put it on the list. + */ +- eg = zalloc(sizeof(*eg)); +- if (!eg) ++ m = zalloc(sizeof(*m)); ++ if (!m) + return -ENOMEM; + +- expr__ctx_init(&eg->pctx); +- eg->metric_name = pe->metric_name; +- eg->metric_expr = pe->metric_expr; +- eg->metric_unit = pe->unit; +- eg->runtime = runtime; +- eg->has_constraint = metric_no_group || metricgroup__has_constraint(pe); +- INIT_LIST_HEAD(&eg->metric_refs); +- eg->metric_refs_cnt = 0; +- *egp = eg; ++ expr__ctx_init(&m->pctx); ++ m->metric_name = pe->metric_name; ++ m->metric_expr = pe->metric_expr; ++ m->metric_unit = pe->unit; ++ m->runtime = runtime; ++ m->has_constraint = metric_no_group || metricgroup__has_constraint(pe); ++ INIT_LIST_HEAD(&m->metric_refs); ++ m->metric_refs_cnt = 0; ++ *mp = m; + + parent = expr_ids__alloc(ids); + if (!parent) { +- free(eg); ++ free(m); + return -EINVAL; + } + + parent->id = strdup(pe->metric_name); + if (!parent->id) { +- free(eg); ++ free(m); + return -ENOMEM; + } + } else { +@@ -693,7 +693,7 @@ static int __add_metric(struct list_head *group_list, + * recursive metricgroup__add_metric call, add + * it to the parent group. + */ +- eg = *egp; ++ m = *mp; + + ref = malloc(sizeof(*ref)); + if (!ref) +@@ -708,21 +708,21 @@ static int __add_metric(struct list_head *group_list, + ref->metric_name = pe->metric_name; + ref->metric_expr = pe->metric_expr; + +- list_add(&ref->list, &eg->metric_refs); +- eg->metric_refs_cnt++; ++ list_add(&ref->list, &m->metric_refs); ++ m->metric_refs_cnt++; + } + + /* Force all found IDs in metric to have us as parent ID. */ + WARN_ON_ONCE(!parent); +- eg->pctx.parent = parent; ++ m->pctx.parent = parent; + + /* + * For both the parent and referenced metrics, we parse + * all the metric's IDs and add it to the parent context. + */ +- if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { +- expr__ctx_clear(&eg->pctx); +- free(eg); ++ if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) { ++ expr__ctx_clear(&m->pctx); ++ free(m); + return -EINVAL; + } + +@@ -730,23 +730,23 @@ static int __add_metric(struct list_head *group_list, + * We add new group only in the 'parent' call, + * so bail out for referenced metric case. + */ +- if (eg->metric_refs_cnt) ++ if (m->metric_refs_cnt) + return 0; + + if (list_empty(group_list)) +- list_add(&eg->nd, group_list); ++ list_add(&m->nd, group_list); + else { + struct list_head *pos; + + /* Place the largest groups at the front. */ + list_for_each_prev(pos, group_list) { +- struct egroup *old = list_entry(pos, struct egroup, nd); ++ struct metric *old = list_entry(pos, struct metric, nd); + +- if (hashmap__size(&eg->pctx.ids) <= ++ if (hashmap__size(&m->pctx.ids) <= + hashmap__size(&old->pctx.ids)) + break; + } +- list_add(&eg->nd, pos); ++ list_add(&m->nd, pos); + } + + return 0; +@@ -776,7 +776,7 @@ static struct pmu_event *find_metric(const char *metric, struct pmu_events_map * + return NULL; + } + +-static int recursion_check(struct egroup *eg, const char *id, struct expr_id **parent, ++static int recursion_check(struct metric *m, const char *id, struct expr_id **parent, + struct expr_ids *ids) + { + struct expr_id_data *data; +@@ -789,7 +789,7 @@ static int recursion_check(struct egroup *eg, const char *id, struct expr_id **p + * if we already processed 'id', if we did, it's recursion + * and we fail. + */ +- ret = expr__get_id(&eg->pctx, id, &data); ++ ret = expr__get_id(&m->pctx, id, &data); + if (ret) + return ret; + +@@ -823,11 +823,11 @@ static int recursion_check(struct egroup *eg, const char *id, struct expr_id **p + static int add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, +- struct egroup **egp, ++ struct metric **mp, + struct expr_id *parent, + struct expr_ids *ids); + +-static int __resolve_metric(struct egroup *eg, ++static int __resolve_metric(struct metric *m, + bool metric_no_group, + struct list_head *group_list, + struct pmu_events_map *map, +@@ -844,7 +844,7 @@ static int __resolve_metric(struct egroup *eg, + */ + do { + all = true; +- hashmap__for_each_entry((&eg->pctx.ids), cur, bkt) { ++ hashmap__for_each_entry((&m->pctx.ids), cur, bkt) { + struct expr_id *parent; + struct pmu_event *pe; + +@@ -852,16 +852,16 @@ static int __resolve_metric(struct egroup *eg, + if (!pe) + continue; + +- ret = recursion_check(eg, cur->key, &parent, ids); ++ ret = recursion_check(m, cur->key, &parent, ids); + if (ret) + return ret; + + all = false; + /* The metric key itself needs to go out.. */ +- expr__del_id(&eg->pctx, cur->key); ++ expr__del_id(&m->pctx, cur->key); + + /* ... and it gets resolved to the parent context. */ +- ret = add_metric(group_list, pe, metric_no_group, &eg, parent, ids); ++ ret = add_metric(group_list, pe, metric_no_group, &m, parent, ids); + if (ret) + return ret; + +@@ -881,11 +881,11 @@ static int resolve_metric(bool metric_no_group, + struct pmu_events_map *map, + struct expr_ids *ids) + { +- struct egroup *eg; ++ struct metric *m; + int err; + +- list_for_each_entry(eg, metric_list, nd) { +- err = __resolve_metric(eg, metric_no_group, metric_list, map, ids); ++ list_for_each_entry(m, metric_list, nd) { ++ err = __resolve_metric(m, metric_no_group, metric_list, map, ids); + if (err) + return err; + } +@@ -895,17 +895,17 @@ static int resolve_metric(bool metric_no_group, + static int add_metric(struct list_head *group_list, + struct pmu_event *pe, + bool metric_no_group, +- struct egroup **egp, ++ struct metric **m, + struct expr_id *parent, + struct expr_ids *ids) + { +- struct egroup *orig = *egp; ++ struct metric *orig = *m; + int ret = 0; + + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __add_metric(group_list, pe, metric_no_group, 1, egp, parent, ids); ++ ret = __add_metric(group_list, pe, metric_no_group, 1, m, parent, ids); + } else { + int j, count; + +@@ -916,8 +916,8 @@ static int add_metric(struct list_head *group_list, + * those events to group_list. + */ + +- for (j = 0; j < count && !ret; j++, *egp = orig) +- ret = __add_metric(group_list, pe, metric_no_group, j, egp, parent, ids); ++ for (j = 0; j < count && !ret; j++, *m = orig) ++ ret = __add_metric(group_list, pe, metric_no_group, j, m, parent, ids); + } + + return ret; +@@ -930,16 +930,16 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + { + struct expr_ids ids = { .cnt = 0, }; + struct pmu_event *pe; +- struct egroup *eg; ++ struct metric *m; + LIST_HEAD(list); + int i, ret; + bool has_match = false; + + map_for_each_metric(pe, i, map, metric) { + has_match = true; +- eg = NULL; ++ m = NULL; + +- ret = add_metric(&list, pe, metric_no_group, &eg, NULL, &ids); ++ ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids); + if (ret) + return ret; + +@@ -957,16 +957,16 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + if (!has_match) + return -EINVAL; + +- list_for_each_entry(eg, &list, nd) { ++ list_for_each_entry(m, &list, nd) { + if (events->len > 0) + strbuf_addf(events, ","); + +- if (eg->has_constraint) { ++ if (m->has_constraint) { + metricgroup__add_metric_non_group(events, +- &eg->pctx); ++ &m->pctx); + } else { + metricgroup__add_metric_weak_group(events, +- &eg->pctx); ++ &m->pctx); + } + } + +@@ -1008,25 +1008,25 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + return ret; + } + +-static void egroup__free_refs(struct egroup *egroup) ++static void metric__free_refs(struct metric *metric) + { + struct metric_ref_node *ref, *tmp; + +- list_for_each_entry_safe(ref, tmp, &egroup->metric_refs, list) { ++ list_for_each_entry_safe(ref, tmp, &metric->metric_refs, list) { + list_del(&ref->list); + free(ref); + } + } + +-static void metricgroup__free_egroups(struct list_head *group_list) ++static void metricgroup__free_metrics(struct list_head *group_list) + { +- struct egroup *eg, *egtmp; ++ struct metric *m, *tmp; + +- list_for_each_entry_safe (eg, egtmp, group_list, nd) { +- egroup__free_refs(eg); +- expr__ctx_clear(&eg->pctx); +- list_del_init(&eg->nd); +- free(eg); ++ list_for_each_entry_safe (m, tmp, group_list, nd) { ++ metric__free_refs(m); ++ expr__ctx_clear(&m->pctx); ++ list_del_init(&m->nd); ++ free(m); + } + } + +@@ -1059,7 +1059,7 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + ret = metricgroup__setup_events(&group_list, metric_no_merge, + perf_evlist, metric_events); + out: +- metricgroup__free_egroups(&group_list); ++ metricgroup__free_metrics(&group_list); + return ret; + } + +-- +2.27.0 + diff --git a/patches/0244-perf-metric-Rename-group_list-to-metric_list.patch b/patches/0244-perf-metric-Rename-group_list-to-metric_list.patch new file mode 100644 index 0000000..3ce9baf --- /dev/null +++ b/patches/0244-perf-metric-Rename-group_list-to-metric_list.patch @@ -0,0 +1,207 @@ +From 13ac9c6876a9c1ddd411a619d1a8e3420390c215 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Sun, 19 Jul 2020 20:13:20 +0200 +Subject: [PATCH 127/201] perf metric: Rename group_list to metric_list + +mainline inclusion +from mainline-v5.9-rc1 +commit 119e521a9633862ec2ddf5c9d908bc167d6f0433 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=119e521a9633862ec2ddf5c9d908bc167d6f0433 + +---------------------------------------------------------------------- + +Following the previous change that rename egroup to metric, there's no +reason to call the list 'group_list' anymore, renaming it to +metric_list. + +Signed-off-by: Jiri Olsa +Reviewed-by: Kajol Jain +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: John Garry +Cc: Michael Petlan +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200719181320.785305-20-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 42 +++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 9a371757e746..edcd2b05311a 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -646,7 +646,7 @@ int __weak arch_get_runtimeparam(void) + return 1; + } + +-static int __add_metric(struct list_head *group_list, ++static int __add_metric(struct list_head *metric_list, + struct pmu_event *pe, + bool metric_no_group, + int runtime, +@@ -733,13 +733,13 @@ static int __add_metric(struct list_head *group_list, + if (m->metric_refs_cnt) + return 0; + +- if (list_empty(group_list)) +- list_add(&m->nd, group_list); ++ if (list_empty(metric_list)) ++ list_add(&m->nd, metric_list); + else { + struct list_head *pos; + + /* Place the largest groups at the front. */ +- list_for_each_prev(pos, group_list) { ++ list_for_each_prev(pos, metric_list) { + struct metric *old = list_entry(pos, struct metric, nd); + + if (hashmap__size(&m->pctx.ids) <= +@@ -820,7 +820,7 @@ static int recursion_check(struct metric *m, const char *id, struct expr_id **pa + return p->id ? 0 : -ENOMEM; + } + +-static int add_metric(struct list_head *group_list, ++static int add_metric(struct list_head *metric_list, + struct pmu_event *pe, + bool metric_no_group, + struct metric **mp, +@@ -829,7 +829,7 @@ static int add_metric(struct list_head *group_list, + + static int __resolve_metric(struct metric *m, + bool metric_no_group, +- struct list_head *group_list, ++ struct list_head *metric_list, + struct pmu_events_map *map, + struct expr_ids *ids) + { +@@ -861,7 +861,7 @@ static int __resolve_metric(struct metric *m, + expr__del_id(&m->pctx, cur->key); + + /* ... and it gets resolved to the parent context. */ +- ret = add_metric(group_list, pe, metric_no_group, &m, parent, ids); ++ ret = add_metric(metric_list, pe, metric_no_group, &m, parent, ids); + if (ret) + return ret; + +@@ -892,7 +892,7 @@ static int resolve_metric(bool metric_no_group, + return 0; + } + +-static int add_metric(struct list_head *group_list, ++static int add_metric(struct list_head *metric_list, + struct pmu_event *pe, + bool metric_no_group, + struct metric **m, +@@ -905,7 +905,7 @@ static int add_metric(struct list_head *group_list, + pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); + + if (!strstr(pe->metric_expr, "?")) { +- ret = __add_metric(group_list, pe, metric_no_group, 1, m, parent, ids); ++ ret = __add_metric(metric_list, pe, metric_no_group, 1, m, parent, ids); + } else { + int j, count; + +@@ -913,11 +913,11 @@ static int add_metric(struct list_head *group_list, + + /* This loop is added to create multiple + * events depend on count value and add +- * those events to group_list. ++ * those events to metric_list. + */ + + for (j = 0; j < count && !ret; j++, *m = orig) +- ret = __add_metric(group_list, pe, metric_no_group, j, m, parent, ids); ++ ret = __add_metric(metric_list, pe, metric_no_group, j, m, parent, ids); + } + + return ret; +@@ -925,7 +925,7 @@ static int add_metric(struct list_head *group_list, + + static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct strbuf *events, +- struct list_head *group_list, ++ struct list_head *metric_list, + struct pmu_events_map *map) + { + struct expr_ids ids = { .cnt = 0, }; +@@ -970,14 +970,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + } + } + +- list_splice(&list, group_list); ++ list_splice(&list, metric_list); + expr_ids__exit(&ids); + return 0; + } + + static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + struct strbuf *events, +- struct list_head *group_list, ++ struct list_head *metric_list, + struct pmu_events_map *map) + { + char *llist, *nlist, *p; +@@ -993,7 +993,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, + + while ((p = strsep(&llist, ",")) != NULL) { + ret = metricgroup__add_metric(p, metric_no_group, events, +- group_list, map); ++ metric_list, map); + if (ret == -EINVAL) { + fprintf(stderr, "Cannot find metric or group `%s'\n", + p); +@@ -1018,11 +1018,11 @@ static void metric__free_refs(struct metric *metric) + } + } + +-static void metricgroup__free_metrics(struct list_head *group_list) ++static void metricgroup__free_metrics(struct list_head *metric_list) + { + struct metric *m, *tmp; + +- list_for_each_entry_safe (m, tmp, group_list, nd) { ++ list_for_each_entry_safe (m, tmp, metric_list, nd) { + metric__free_refs(m); + expr__ctx_clear(&m->pctx); + list_del_init(&m->nd); +@@ -1039,13 +1039,13 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + { + struct parse_events_error parse_error; + struct strbuf extra_events; +- LIST_HEAD(group_list); ++ LIST_HEAD(metric_list); + int ret; + + if (metric_events->nr_entries == 0) + metricgroup__rblist_init(metric_events); + ret = metricgroup__add_metric_list(str, metric_no_group, +- &extra_events, &group_list, map); ++ &extra_events, &metric_list, map); + if (ret) + return ret; + pr_debug("adding %s\n", extra_events.buf); +@@ -1056,10 +1056,10 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + goto out; + } + strbuf_release(&extra_events); +- ret = metricgroup__setup_events(&group_list, metric_no_merge, ++ ret = metricgroup__setup_events(&metric_list, metric_no_merge, + perf_evlist, metric_events); + out: +- metricgroup__free_metrics(&group_list); ++ metricgroup__free_metrics(&metric_list); + return ret; + } + +-- +2.27.0 + diff --git a/patches/0245-perf-jevents-Make-json_events-static-and-ditch-jeven.patch b/patches/0245-perf-jevents-Make-json_events-static-and-ditch-jeven.patch new file mode 100644 index 0000000..5a8d75a --- /dev/null +++ b/patches/0245-perf-jevents-Make-json_events-static-and-ditch-jeven.patch @@ -0,0 +1,93 @@ +From a2f4119dfb729ac6bcf8a74d555ba42f16861e7f Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Mon, 7 Sep 2020 12:11:29 +0530 +Subject: [PATCH 128/201] perf jevents: Make json_events() static and ditch + jevents.h file + +mainline inclusion +from mainline-v5.10-rc1 +commit 0d52b7889be17076e0c9c535d74db9c4c8b506ce +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d52b7889be17076e0c9c535d74db9c4c8b506ce + +---------------------------------------------------------------------- + +This patch removes jevents.h and makes json_events function static. + +Signed-off-by: Kajol Jain +Reviewed-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jin Yao +Cc: Madhavan Srinivasan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200907064133.75090-2-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 3 +-- + tools/perf/pmu-events/jevents.h | 23 ----------------------- + 2 files changed, 1 insertion(+), 25 deletions(-) + delete mode 100644 tools/perf/pmu-events/jevents.h + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 1f7d4c53631d..e1423f0fbb0f 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -48,7 +48,6 @@ + #include + #include "jsmn.h" + #include "json.h" +-#include "jevents.h" + + int verbose; + char *prog; +@@ -513,7 +512,7 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc, + } + + /* Call func with each event in the json file */ +-int json_events(const char *fn, ++static int json_events(const char *fn, + int (*func)(void *data, char *name, char *event, char *desc, + char *long_desc, + char *pmu, char *unit, char *perpkg, +diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h +deleted file mode 100644 +index 2afc8304529e..000000000000 +--- a/tools/perf/pmu-events/jevents.h ++++ /dev/null +@@ -1,23 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-#ifndef JEVENTS_H +-#define JEVENTS_H 1 +- +-int json_events(const char *fn, +- int (*func)(void *data, char *name, char *event, char *desc, +- char *long_desc, +- char *pmu, +- char *unit, char *perpkg, char *metric_expr, +- char *metric_name, char *metric_group, +- char *deprecated, char *metric_constraint), +- void *data); +-char *get_cpu_str(void); +- +-#ifndef min +-#define min(x, y) ({ \ +- typeof(x) _min1 = (x); \ +- typeof(y) _min2 = (y); \ +- (void) (&_min1 == &_min2); \ +- _min1 < _min2 ? _min1 : _min2; }) +-#endif +- +-#endif +-- +2.27.0 + diff --git a/patches/0246-perf-jevents-Add-new-structure-to-pass-json-fields.patch b/patches/0246-perf-jevents-Add-new-structure-to-pass-json-fields.patch new file mode 100644 index 0000000..550dc43 --- /dev/null +++ b/patches/0246-perf-jevents-Add-new-structure-to-pass-json-fields.patch @@ -0,0 +1,402 @@ +From 94bc6bbea923b41dcdc80e4af14061401b39c8ec Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Mon, 7 Sep 2020 12:11:30 +0530 +Subject: [PATCH 129/201] perf jevents: Add new structure to pass json fields. + +mainline inclusion +from mainline-v5.10-rc1 +commit 71a374bb1847824b60a3bfdd3af8a13b6ec3a22d +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71a374bb1847824b60a3bfdd3af8a13b6ec3a22d + +---------------------------------------------------------------------- + +This patch adds new structure called 'json_event' inside jevents.c +file to improve the callback prototype inside jevent files. + +Initially, whenever user want to add new field, they need to update +in all function callback which make it more and more complex with +increased number of parmeters. + +With this change, we just need to add it in new structure 'json_event'. + +Signed-off-by: Kajol Jain +Reviewed-by: Andi Kleen +Reviewed-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jin Yao +Cc: Madhavan Srinivasan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200907064133.75090-3-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 212 +++++++++++++++----------------- + 1 file changed, 97 insertions(+), 115 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index e1423f0fbb0f..3722501956be 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -52,6 +52,23 @@ + int verbose; + char *prog; + ++struct json_event { ++ char *name; ++ char *event; ++ char *desc; ++ char *long_desc; ++ char *pmu; ++ char *unit; ++ char *perpkg; ++ char *metric_expr; ++ char *metric_name; ++ char *metric_group; ++ char *deprecated; ++ char *metric_constraint; ++}; ++ ++typedef int (*func)(void *data, struct json_event *je); ++ + int eprintf(int level, int var, const char *fmt, ...) + { + +@@ -70,11 +87,6 @@ int eprintf(int level, int var, const char *fmt, ...) + return ret; + } + +-__attribute__((weak)) char *get_cpu_str(void) +-{ +- return NULL; +-} +- + static void addfield(char *map, char **dst, const char *sep, + const char *a, jsmntok_t *bt) + { +@@ -318,12 +330,7 @@ static void print_events_table_prefix(FILE *fp, const char *tblname) + close_table = 1; + } + +-static int print_events_table_entry(void *data, char *name, char *event, +- char *desc, char *long_desc, +- char *pmu, char *unit, char *perpkg, +- char *metric_expr, +- char *metric_name, char *metric_group, +- char *deprecated, char *metric_constraint) ++static int print_events_table_entry(void *data, struct json_event *je) + { + struct perf_entry_data *pd = data; + FILE *outfp = pd->outfp; +@@ -335,30 +342,30 @@ static int print_events_table_entry(void *data, char *name, char *event, + */ + fprintf(outfp, "{\n"); + +- if (name) +- fprintf(outfp, "\t.name = \"%s\",\n", name); +- if (event) +- fprintf(outfp, "\t.event = \"%s\",\n", event); +- fprintf(outfp, "\t.desc = \"%s\",\n", desc); ++ if (je->name) ++ fprintf(outfp, "\t.name = \"%s\",\n", je->name); ++ if (je->event) ++ fprintf(outfp, "\t.event = \"%s\",\n", je->event); ++ fprintf(outfp, "\t.desc = \"%s\",\n", je->desc); + fprintf(outfp, "\t.topic = \"%s\",\n", topic); +- if (long_desc && long_desc[0]) +- fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc); +- if (pmu) +- fprintf(outfp, "\t.pmu = \"%s\",\n", pmu); +- if (unit) +- fprintf(outfp, "\t.unit = \"%s\",\n", unit); +- if (perpkg) +- fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg); +- if (metric_expr) +- fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr); +- if (metric_name) +- fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name); +- if (metric_group) +- fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group); +- if (deprecated) +- fprintf(outfp, "\t.deprecated = \"%s\",\n", deprecated); +- if (metric_constraint) +- fprintf(outfp, "\t.metric_constraint = \"%s\",\n", metric_constraint); ++ if (je->long_desc && je->long_desc[0]) ++ fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc); ++ if (je->pmu) ++ fprintf(outfp, "\t.pmu = \"%s\",\n", je->pmu); ++ if (je->unit) ++ fprintf(outfp, "\t.unit = \"%s\",\n", je->unit); ++ if (je->perpkg) ++ fprintf(outfp, "\t.perpkg = \"%s\",\n", je->perpkg); ++ if (je->metric_expr) ++ fprintf(outfp, "\t.metric_expr = \"%s\",\n", je->metric_expr); ++ if (je->metric_name) ++ fprintf(outfp, "\t.metric_name = \"%s\",\n", je->metric_name); ++ if (je->metric_group) ++ fprintf(outfp, "\t.metric_group = \"%s\",\n", je->metric_group); ++ if (je->deprecated) ++ fprintf(outfp, "\t.deprecated = \"%s\",\n", je->deprecated); ++ if (je->metric_constraint) ++ fprintf(outfp, "\t.metric_constraint = \"%s\",\n", je->metric_constraint); + fprintf(outfp, "},\n"); + + return 0; +@@ -380,17 +387,17 @@ struct event_struct { + char *metric_constraint; + }; + +-#define ADD_EVENT_FIELD(field) do { if (field) { \ +- es->field = strdup(field); \ ++#define ADD_EVENT_FIELD(field) do { if (je->field) { \ ++ es->field = strdup(je->field); \ + if (!es->field) \ + goto out_free; \ + } } while (0) + + #define FREE_EVENT_FIELD(field) free(es->field) + +-#define TRY_FIXUP_FIELD(field) do { if (es->field && !*field) {\ +- *field = strdup(es->field); \ +- if (!*field) \ ++#define TRY_FIXUP_FIELD(field) do { if (es->field && !je->field) {\ ++ je->field = strdup(es->field); \ ++ if (!je->field) \ + return -ENOMEM; \ + } } while (0) + +@@ -421,11 +428,7 @@ static void free_arch_std_events(void) + } + } + +-static int save_arch_std_events(void *data, char *name, char *event, +- char *desc, char *long_desc, char *pmu, +- char *unit, char *perpkg, char *metric_expr, +- char *metric_name, char *metric_group, +- char *deprecated, char *metric_constraint) ++static int save_arch_std_events(void *data, struct json_event *je) + { + struct event_struct *es; + +@@ -485,11 +488,8 @@ static char *real_event(const char *name, char *event) + } + + static int +-try_fixup(const char *fn, char *arch_std, char **event, char **desc, +- char **name, char **long_desc, char **pmu, char **filter, +- char **perpkg, char **unit, char **metric_expr, char **metric_name, +- char **metric_group, unsigned long long eventcode, +- char **deprecated, char **metric_constraint) ++try_fixup(const char *fn, char *arch_std, unsigned long long eventcode, ++ struct json_event *je) + { + /* try to find matching event from arch standard values */ + struct event_struct *es; +@@ -498,8 +498,8 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc, + if (!strcmp(arch_std, es->name)) { + if (!eventcode && es->event) { + /* allow EventCode to be overridden */ +- free(*event); +- *event = NULL; ++ free(je->event); ++ je->event = NULL; + } + FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD); + return 0; +@@ -513,13 +513,8 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc, + + /* Call func with each event in the json file */ + static int json_events(const char *fn, +- int (*func)(void *data, char *name, char *event, char *desc, +- char *long_desc, +- char *pmu, char *unit, char *perpkg, +- char *metric_expr, +- char *metric_name, char *metric_group, +- char *deprecated, char *metric_constraint), +- void *data) ++ int (*func)(void *data, struct json_event *je), ++ void *data) + { + int err; + size_t size; +@@ -537,18 +532,10 @@ static int json_events(const char *fn, + EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array"); + tok = tokens + 1; + for (i = 0; i < tokens->size; i++) { +- char *event = NULL, *desc = NULL, *name = NULL; +- char *long_desc = NULL; ++ char *event = NULL; + char *extra_desc = NULL; +- char *pmu = NULL; + char *filter = NULL; +- char *perpkg = NULL; +- char *unit = NULL; +- char *metric_expr = NULL; +- char *metric_name = NULL; +- char *metric_group = NULL; +- char *deprecated = NULL; +- char *metric_constraint = NULL; ++ struct json_event je = {}; + char *arch_std = NULL; + unsigned long long eventcode = 0; + struct msrmap *msr = NULL; +@@ -583,14 +570,14 @@ static int json_events(const char *fn, + eventcode |= strtoul(code, NULL, 0) << 21; + free(code); + } else if (json_streq(map, field, "EventName")) { +- addfield(map, &name, "", "", val); ++ addfield(map, &je.name, "", "", val); + } else if (json_streq(map, field, "BriefDescription")) { +- addfield(map, &desc, "", "", val); +- fixdesc(desc); ++ addfield(map, &je.desc, "", "", val); ++ fixdesc(je.desc); + } else if (json_streq(map, field, + "PublicDescription")) { +- addfield(map, &long_desc, "", "", val); +- fixdesc(long_desc); ++ addfield(map, &je.long_desc, "", "", val); ++ fixdesc(je.long_desc); + } else if (json_streq(map, field, "PEBS") && nz) { + precise = val; + } else if (json_streq(map, field, "MSRIndex") && nz) { +@@ -610,34 +597,34 @@ static int json_events(const char *fn, + + ppmu = field_to_perf(unit_to_pmu, map, val); + if (ppmu) { +- pmu = strdup(ppmu); ++ je.pmu = strdup(ppmu); + } else { +- if (!pmu) +- pmu = strdup("uncore_"); +- addfield(map, &pmu, "", "", val); +- for (s = pmu; *s; s++) ++ if (!je.pmu) ++ je.pmu = strdup("uncore_"); ++ addfield(map, &je.pmu, "", "", val); ++ for (s = je.pmu; *s; s++) + *s = tolower(*s); + } +- addfield(map, &desc, ". ", "Unit: ", NULL); +- addfield(map, &desc, "", pmu, NULL); +- addfield(map, &desc, "", " ", NULL); ++ addfield(map, &je.desc, ". ", "Unit: ", NULL); ++ addfield(map, &je.desc, "", je.pmu, NULL); ++ addfield(map, &je.desc, "", " ", NULL); + } else if (json_streq(map, field, "Filter")) { + addfield(map, &filter, "", "", val); + } else if (json_streq(map, field, "ScaleUnit")) { +- addfield(map, &unit, "", "", val); ++ addfield(map, &je.unit, "", "", val); + } else if (json_streq(map, field, "PerPkg")) { +- addfield(map, &perpkg, "", "", val); ++ addfield(map, &je.perpkg, "", "", val); + } else if (json_streq(map, field, "Deprecated")) { +- addfield(map, &deprecated, "", "", val); ++ addfield(map, &je.deprecated, "", "", val); + } else if (json_streq(map, field, "MetricName")) { +- addfield(map, &metric_name, "", "", val); ++ addfield(map, &je.metric_name, "", "", val); + } else if (json_streq(map, field, "MetricGroup")) { +- addfield(map, &metric_group, "", "", val); ++ addfield(map, &je.metric_group, "", "", val); + } else if (json_streq(map, field, "MetricConstraint")) { +- addfield(map, &metric_constraint, "", "", val); ++ addfield(map, &je.metric_constraint, "", "", val); + } else if (json_streq(map, field, "MetricExpr")) { +- addfield(map, &metric_expr, "", "", val); +- for (s = metric_expr; *s; s++) ++ addfield(map, &je.metric_expr, "", "", val); ++ for (s = je.metric_expr; *s; s++) + *s = tolower(*s); + } else if (json_streq(map, field, "ArchStdEvent")) { + addfield(map, &arch_std, "", "", val); +@@ -646,7 +633,7 @@ static int json_events(const char *fn, + } + /* ignore unknown fields */ + } +- if (precise && desc && !strstr(desc, "(Precise Event)")) { ++ if (precise && je.desc && !strstr(je.desc, "(Precise Event)")) { + if (json_streq(map, precise, "2")) + addfield(map, &extra_desc, " ", + "(Must be precise)", NULL); +@@ -656,48 +643,43 @@ static int json_events(const char *fn, + } + snprintf(buf, sizeof buf, "event=%#llx", eventcode); + addfield(map, &event, ",", buf, NULL); +- if (desc && extra_desc) +- addfield(map, &desc, " ", extra_desc, NULL); +- if (long_desc && extra_desc) +- addfield(map, &long_desc, " ", extra_desc, NULL); ++ if (je.desc && extra_desc) ++ addfield(map, &je.desc, " ", extra_desc, NULL); ++ if (je.long_desc && extra_desc) ++ addfield(map, &je.long_desc, " ", extra_desc, NULL); + if (filter) + addfield(map, &event, ",", filter, NULL); + if (msr != NULL) + addfield(map, &event, ",", msr->pname, msrval); +- if (name) +- fixname(name); ++ if (je.name) ++ fixname(je.name); + + if (arch_std) { + /* + * An arch standard event is referenced, so try to + * fixup any unassigned values. + */ +- err = try_fixup(fn, arch_std, &event, &desc, &name, +- &long_desc, &pmu, &filter, &perpkg, +- &unit, &metric_expr, &metric_name, +- &metric_group, eventcode, +- &deprecated, &metric_constraint); ++ err = try_fixup(fn, arch_std, eventcode, &je); + if (err) + goto free_strings; + } +- err = func(data, name, real_event(name, event), desc, long_desc, +- pmu, unit, perpkg, metric_expr, metric_name, +- metric_group, deprecated, metric_constraint); ++ je.event = real_event(je.name, event); ++ err = func(data, &je); + free_strings: + free(event); +- free(desc); +- free(name); +- free(long_desc); ++ free(je.desc); ++ free(je.name); ++ free(je.long_desc); + free(extra_desc); +- free(pmu); ++ free(je.pmu); + free(filter); +- free(perpkg); +- free(deprecated); +- free(unit); +- free(metric_expr); +- free(metric_name); +- free(metric_group); +- free(metric_constraint); ++ free(je.perpkg); ++ free(je.deprecated); ++ free(je.unit); ++ free(je.metric_expr); ++ free(je.metric_name); ++ free(je.metric_group); ++ free(je.metric_constraint); + free(arch_std); + + if (err) +-- +2.27.0 + diff --git a/patches/0247-perf-jevents-Add-support-for-parsing-perchip-percore.patch b/patches/0247-perf-jevents-Add-support-for-parsing-perchip-percore.patch new file mode 100644 index 0000000..af66756 --- /dev/null +++ b/patches/0247-perf-jevents-Add-support-for-parsing-perchip-percore.patch @@ -0,0 +1,154 @@ +From 8b9df53735696435be2b78eac99feac8e2996bb9 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Mon, 7 Sep 2020 12:11:31 +0530 +Subject: [PATCH 130/201] perf jevents: Add support for parsing perchip/percore + events + +mainline inclusion +from mainline-v5.10-rc1 +commit 560ccbc4a52c567096023e0c6a9b920048e59017 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=560ccbc4a52c567096023e0c6a9b920048e59017 + +---------------------------------------------------------------------- + +Initially, every time we want to add new terms like chip, core thread etc, +we need to create corrsponding fields in pmu_events and event struct. + +This patch adds an enum called 'aggr_mode_class' which store all these +aggregation like perchip/percore. It also adds new field 'aggr_mode' +to capture these terms. + +Now, if user wants to add any new term, they just need to add it in +the enum defined. + +Signed-off-by: Kajol Jain +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jin Yao +Cc: John Garry +Cc: Madhavan Srinivasan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200907064133.75090-4-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 20 ++++++++++++++++++++ + tools/perf/pmu-events/pmu-events.h | 6 ++++++ + 2 files changed, 26 insertions(+) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 3722501956be..4a1bc82e68bd 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -48,6 +48,7 @@ + #include + #include "jsmn.h" + #include "json.h" ++#include "pmu-events.h" + + int verbose; + char *prog; +@@ -60,6 +61,7 @@ struct json_event { + char *pmu; + char *unit; + char *perpkg; ++ char *aggr_mode; + char *metric_expr; + char *metric_name; + char *metric_group; +@@ -67,6 +69,17 @@ struct json_event { + char *metric_constraint; + }; + ++enum aggr_mode_class convert(const char *aggr_mode) ++{ ++ if (!strcmp(aggr_mode, "PerCore")) ++ return PerCore; ++ else if (!strcmp(aggr_mode, "PerChip")) ++ return PerChip; ++ ++ pr_err("%s: Wrong AggregationMode value '%s'\n", prog, aggr_mode); ++ return -1; ++} ++ + typedef int (*func)(void *data, struct json_event *je); + + int eprintf(int level, int var, const char *fmt, ...) +@@ -356,6 +369,8 @@ static int print_events_table_entry(void *data, struct json_event *je) + fprintf(outfp, "\t.unit = \"%s\",\n", je->unit); + if (je->perpkg) + fprintf(outfp, "\t.perpkg = \"%s\",\n", je->perpkg); ++ if (je->aggr_mode) ++ fprintf(outfp, "\t.aggr_mode = \"%d\",\n", convert(je->aggr_mode)); + if (je->metric_expr) + fprintf(outfp, "\t.metric_expr = \"%s\",\n", je->metric_expr); + if (je->metric_name) +@@ -380,6 +395,7 @@ struct event_struct { + char *pmu; + char *unit; + char *perpkg; ++ char *aggr_mode; + char *metric_expr; + char *metric_name; + char *metric_group; +@@ -409,6 +425,7 @@ struct event_struct { + op(pmu); \ + op(unit); \ + op(perpkg); \ ++ op(aggr_mode); \ + op(metric_expr); \ + op(metric_name); \ + op(metric_group); \ +@@ -614,6 +631,8 @@ static int json_events(const char *fn, + addfield(map, &je.unit, "", "", val); + } else if (json_streq(map, field, "PerPkg")) { + addfield(map, &je.perpkg, "", "", val); ++ } else if (json_streq(map, field, "AggregationMode")) { ++ addfield(map, &je.aggr_mode, "", "", val); + } else if (json_streq(map, field, "Deprecated")) { + addfield(map, &je.deprecated, "", "", val); + } else if (json_streq(map, field, "MetricName")) { +@@ -674,6 +693,7 @@ static int json_events(const char *fn, + free(je.pmu); + free(filter); + free(je.perpkg); ++ free(je.aggr_mode); + free(je.deprecated); + free(je.unit); + free(je.metric_expr); +diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h +index 53e76d5d5b37..fb712bb0f59e 100644 +--- a/tools/perf/pmu-events/pmu-events.h ++++ b/tools/perf/pmu-events/pmu-events.h +@@ -2,6 +2,11 @@ + #ifndef PMU_EVENTS_H + #define PMU_EVENTS_H + ++enum aggr_mode_class { ++ PerChip = 1, ++ PerCore ++}; ++ + /* + * Describe each PMU event. Each CPU has a table of PMU events. + */ +@@ -14,6 +19,7 @@ struct pmu_event { + const char *pmu; + const char *unit; + const char *perpkg; ++ const char *aggr_mode; + const char *metric_expr; + const char *metric_name; + const char *metric_group; +-- +2.27.0 + diff --git a/patches/0248-perf-metricgroup-Pass-pmu_event-structure-as-a-param.patch b/patches/0248-perf-metricgroup-Pass-pmu_event-structure-as-a-param.patch new file mode 100644 index 0000000..6119b3a --- /dev/null +++ b/patches/0248-perf-metricgroup-Pass-pmu_event-structure-as-a-param.patch @@ -0,0 +1,113 @@ +From 5a195bd859f2468392df4a0aad9fde4ab80498d1 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Mon, 7 Sep 2020 12:11:32 +0530 +Subject: [PATCH 131/201] perf metricgroup: Pass pmu_event structure as a + parameter for arch_get_runtimeparam() + +mainline inclusion +from mainline-v5.10-rc1 +commit f5a489dc8189bd6a6a418e408bada1ed5b9d02b1 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5a489dc8189bd6a6a418e408bada1ed5b9d02b1 + +---------------------------------------------------------------------- + +This patch adds passing of pmu_event as a parameter in function +'arch_get_runtimeparam' which can be used to get details like if the +event is percore/perchip. + +Signed-off-by: Kajol Jain +Acked-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jin Yao +Cc: John Garry +Cc: Madhavan Srinivasan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20200907064133.75090-5-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/arch/powerpc/util/header.c | 7 +++++-- + tools/perf/util/metricgroup.c | 5 ++--- + tools/perf/util/metricgroup.h | 3 ++- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c +index 0a3816692252..823c663d2296 100644 +--- a/tools/perf/arch/powerpc/util/header.c ++++ b/tools/perf/arch/powerpc/util/header.c +@@ -48,8 +48,11 @@ get_cpuid_str(struct perf_pmu *pmu __maybe_unused) + return bufp; + } + +-int arch_get_runtimeparam(void) ++int arch_get_runtimeparam(struct pmu_event *pe) + { + int count; +- return sysfs__read_int("/devices/hv_24x7/interface/sockets", &count) < 0 ? 1 : count; ++ char path[PATH_MAX] = "/devices/hv_24x7/interface/"; ++ ++ atoi(pe->aggr_mode) == PerChip ? strcat(path, "sockets") : strcat(path, "coresperchip"); ++ return sysfs__read_int(path, &count) < 0 ? 1 : count; + } +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index edcd2b05311a..2d505fa62a6c 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -23,7 +23,6 @@ + #include "rblist.h" + #include + #include +-#include "pmu-events/pmu-events.h" + #include "strlist.h" + #include + #include +@@ -641,7 +640,7 @@ static bool metricgroup__has_constraint(struct pmu_event *pe) + return false; + } + +-int __weak arch_get_runtimeparam(void) ++int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused) + { + return 1; + } +@@ -909,7 +908,7 @@ static int add_metric(struct list_head *metric_list, + } else { + int j, count; + +- count = arch_get_runtimeparam(); ++ count = arch_get_runtimeparam(pe); + + /* This loop is added to create multiple + * events depend on count value and add +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 23b4f44b3f39..3670a8528ca5 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include "pmu-events/pmu-events.h" + + struct perf_evsel; + struct perf_evlist; +@@ -52,6 +53,6 @@ int metricgroup__parse_groups_test(struct perf_evlist *evlist, + void metricgroup__print(bool metrics, bool groups, char *filter, + bool raw, bool details); + bool metricgroup__has_metric(const char *metric); +-int arch_get_runtimeparam(void); ++int arch_get_runtimeparam(struct pmu_event *pe __maybe_unused); + void metricgroup__rblist_exit(struct rblist *metric_events); + #endif +-- +2.27.0 + diff --git a/patches/0249-perf-list-Do-not-print-Metric-Groups-unnecessarily.patch b/patches/0249-perf-list-Do-not-print-Metric-Groups-unnecessarily.patch new file mode 100644 index 0000000..90e6dfa --- /dev/null +++ b/patches/0249-perf-list-Do-not-print-Metric-Groups-unnecessarily.patch @@ -0,0 +1,74 @@ +From db7edc915c851ef0ce02ab60f76bad12d4b388a8 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Wed, 9 Sep 2020 14:58:48 +0900 +Subject: [PATCH 132/201] perf list: Do not print 'Metric Groups:' + unnecessarily + +mainline inclusion +from mainline-v5.10-rc1 +commit fac49a3bc4030524c155d9d59f3d7d14e771fe6f +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fac49a3bc4030524c155d9d59f3d7d14e771fe6f + +---------------------------------------------------------------------- + +It was printed unconditionally even if nothing is printed. +Check if the output list empty when filter is given. + +Before: + $ ./perf list duration + + List of pre-defined events (to be used in -e): + + duration_time [Tool event] + + Metric Groups: + +After: + $ ./perf list duration + + List of pre-defined events (to be used in -e): + + duration_time [Tool event] + +Signed-off-by: Namhyung Kim +Tested-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200909055849.469612-2-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 2d505fa62a6c..906041a72a90 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -541,10 +541,12 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + } + } + +- if (metricgroups && !raw) +- printf("\nMetric Groups:\n\n"); +- else if (metrics && !raw) +- printf("\nMetrics:\n\n"); ++ if (!filter || !rblist__empty(&groups)) { ++ if (metricgroups && !raw) ++ printf("\nMetric Groups:\n\n"); ++ else if (metrics && !raw) ++ printf("\nMetrics:\n\n"); ++ } + + for (node = rb_first(&groups.entries); node; node = next) { + struct mep *me = container_of(node, struct mep, nd); +-- +2.27.0 + diff --git a/patches/0250-perf-metricgroup-Fix-typo-in-comment.patch b/patches/0250-perf-metricgroup-Fix-typo-in-comment.patch new file mode 100644 index 0000000..72f02df --- /dev/null +++ b/patches/0250-perf-metricgroup-Fix-typo-in-comment.patch @@ -0,0 +1,51 @@ +From 028138c3636fcdcfc13b04425829a919f5738c5f Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 9 Sep 2020 20:26:31 -0700 +Subject: [PATCH 133/201] perf metricgroup: Fix typo in comment. + +mainline inclusion +from mainline-v5.10-rc1 +commit 9e34c1c87e56dc4a53e95fa2a68191c75e10b46d +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9e34c1c87e56dc4a53e95fa2a68191c75e10b46d + +---------------------------------------------------------------------- + +Add missing character. + +Signed-off-by: Ian Rogers +Acked-by: Namhyung Kim +Cc: Alexander Shishkin +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Kan Liang +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Richter +Link: http://lore.kernel.org/lkml/20200910032632.511566-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 906041a72a90..b874343f4b45 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -155,7 +155,7 @@ static void expr_ids__exit(struct expr_ids *ids) + } + + /** +- * Find a group of events in perf_evlist that correpond to those from a parsed ++ * Find a group of events in perf_evlist that correspond to those from a parsed + * metric expression. Note, as find_evsel_group is called in the same order as + * perf_evlist was constructed, metric_no_merge doesn't need to test for + * underfilling a group. +-- +2.27.0 + diff --git a/patches/0251-perf-test-Free-aliases-for-PMU-event-map-aliases-tes.patch b/patches/0251-perf-test-Free-aliases-for-PMU-event-map-aliases-tes.patch new file mode 100644 index 0000000..eb1d5c1 --- /dev/null +++ b/patches/0251-perf-test-Free-aliases-for-PMU-event-map-aliases-tes.patch @@ -0,0 +1,103 @@ +From 9dee26683020e4eb40070d3a6bbf09e06d9e1690 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:18 +0900 +Subject: [PATCH 134/201] perf test: Free aliases for PMU event map aliases + test + +mainline inclusion +from mainline-v5.9-rc6 +commit 22fe5a25b5d8c4f8008dc4a8738d6d8a5f5ddbe9 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=22fe5a25b5d8c4f8008dc4a8738d6d8a5f5ddbe9 + +---------------------------------------------------------------------- + +The aliases were never released causing the following leaks: + Indirect leak of 1224 byte(s) in 9 object(s) allocated from: + #0 0x7feefb830628 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x107628) + #1 0x56332c8f1b62 in __perf_pmu__new_alias util/pmu.c:322 + #2 0x56332c8f401f in pmu_add_cpu_aliases_map util/pmu.c:778 + #3 0x56332c792ce9 in __test__pmu_event_aliases tests/pmu-events.c:295 + #4 0x56332c792ce9 in test_aliases tests/pmu-events.c:367 + #5 0x56332c76a09b in run_test tests/builtin-test.c:410 + #6 0x56332c76a09b in test_and_print tests/builtin-test.c:440 + #7 0x56332c76ce69 in __cmd_test tests/builtin-test.c:695 + #8 0x56332c76ce69 in cmd_test tests/builtin-test.c:807 + #9 0x56332c7d2214 in run_builtin /home/namhyung/project/linux/tools/perf/perf.c:312 + #10 0x56332c6701a8 in handle_internal_command /home/namhyung/project/linux/tools/perf/perf.c:364 + #11 0x56332c6701a8 in run_argv /home/namhyung/project/linux/tools/perf/perf.c:408 + #12 0x56332c6701a8 in main /home/namhyung/project/linux/tools/perf/perf.c:538 + #13 0x7feefb359cc9 in __libc_start_main ../csu/libc-start.c:308 + +Fixes: 956a78356c24c ("perf test: Test pmu-events aliases") +Signed-off-by: Namhyung Kim +Reviewed-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-11-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 5 +++++ + tools/perf/util/pmu.c | 2 +- + tools/perf/util/pmu.h | 1 + + 3 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 7a3cad2ac94e..83712bde93f4 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -274,6 +274,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + int res = 0; + bool use_uncore_table; + struct pmu_events_map *map = __test_pmu_get_events_map(); ++ struct perf_pmu_alias *a, *tmp; + + if (!map) + return -1; +@@ -347,6 +348,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + pmu_name, alias->name); + } + ++ list_for_each_entry_safe(a, tmp, &aliases, list) { ++ list_del(&a->list); ++ perf_pmu_free_alias(a); ++ } + free(pmu); + return res; + } +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 713d1c6204a2..cce165d80146 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -272,7 +272,7 @@ static void perf_pmu_update_alias(struct perf_pmu_alias *old, + } + + /* Delete an alias entry. */ +-static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) ++void perf_pmu_free_alias(struct perf_pmu_alias *newalias) + { + zfree(&newalias->name); + zfree(&newalias->desc); +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index c44c4a701bf4..555a917406e6 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -102,6 +102,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, + + struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); + bool pmu_uncore_alias_match(const char *pmu_name, const char *name); ++void perf_pmu_free_alias(struct perf_pmu_alias *alias); + + int perf_pmu__convert_scale(const char *scale, char **end, double *sval); + +-- +2.27.0 + diff --git a/patches/0252-perf-metric-Fix-some-memory-leaks.patch b/patches/0252-perf-metric-Fix-some-memory-leaks.patch new file mode 100644 index 0000000..7b7968a --- /dev/null +++ b/patches/0252-perf-metric-Fix-some-memory-leaks.patch @@ -0,0 +1,76 @@ +From 6897464a67827e592c7edfebc0505373d9a02f9e Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:09 +0900 +Subject: [PATCH 135/201] perf metric: Fix some memory leaks + +mainline inclusion +from mainline-v5.9-rc6 +commit 4f57a1ed749a81ec553d89233cab53db9365e193 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f57a1ed749a81ec553d89233cab53db9365e193 + +---------------------------------------------------------------------- + +I found some memory leaks while reading the metric code. Some are real +and others only occur in the error path. When it failed during metric +or event parsing, it should release all resources properly. + +Fixes: b18f3e365019d ("perf stat: Support JSON metrics in perf stat") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: John Garry +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-2-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index b874343f4b45..a6cd69f4a306 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -536,6 +536,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + continue; + strlist__add(me->metrics, s); + } ++ ++ if (!raw) ++ free(s); + } + free(omg); + } +@@ -1048,7 +1051,7 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + ret = metricgroup__add_metric_list(str, metric_no_group, + &extra_events, &metric_list, map); + if (ret) +- return ret; ++ goto out; + pr_debug("adding %s\n", extra_events.buf); + memset(&parse_error, 0, sizeof(struct parse_events_error)); + ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); +@@ -1056,11 +1059,11 @@ static int parse_groups(struct perf_evlist *perf_evlist, const char *str, + parse_events_print_error(&parse_error, extra_events.buf); + goto out; + } +- strbuf_release(&extra_events); + ret = metricgroup__setup_events(&metric_list, metric_no_merge, + perf_evlist, metric_events); + out: + metricgroup__free_metrics(&metric_list); ++ strbuf_release(&extra_events); + return ret; + } + +-- +2.27.0 + diff --git a/patches/0253-perf-metric-Fix-some-memory-leaks-part-2.patch b/patches/0253-perf-metric-Fix-some-memory-leaks-part-2.patch new file mode 100644 index 0000000..c8a4cf8 --- /dev/null +++ b/patches/0253-perf-metric-Fix-some-memory-leaks-part-2.patch @@ -0,0 +1,59 @@ +From dc1272a008a4a49e531fbaa323f509db0641cb80 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:10 +0900 +Subject: [PATCH 136/201] perf metric: Fix some memory leaks - part 2 + +mainline inclusion +from mainline-v5.9-rc6 +commit b033ab11ad0c7f9a9c9fa4a1ac2ffad14454a9f3 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b033ab11ad0c7f9a9c9fa4a1ac2ffad14454a9f3 + +---------------------------------------------------------------------- + +The metric_event_delete() missed to free expr->metric_events and it +should free an expr when metric_refs allocation failed. + +Fixes: 4ea2896715e67 ("perf metric: Collect referenced metrics in struct metric_expr") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: John Garry +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-3-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index a6cd69f4a306..d42bf52f798c 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -90,6 +90,7 @@ static void metric_event_delete(struct rblist *rblist __maybe_unused, + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { + free(expr->metric_refs); ++ free(expr->metric_events); + free(expr); + } + +@@ -321,6 +322,7 @@ static int metricgroup__setup_events(struct list_head *groups, + if (!metric_refs) { + ret = -ENOMEM; + free(metric_events); ++ free(expr); + break; + } + +-- +2.27.0 + diff --git a/patches/0254-perf-evlist-Fix-cpu-thread-map-leak.patch b/patches/0254-perf-evlist-Fix-cpu-thread-map-leak.patch new file mode 100644 index 0000000..9337e11 --- /dev/null +++ b/patches/0254-perf-evlist-Fix-cpu-thread-map-leak.patch @@ -0,0 +1,77 @@ +From 71469a97f9b50ec8dcd23ddfe6bf492d996ae338 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:11 +0900 +Subject: [PATCH 137/201] perf evlist: Fix cpu/thread map leak + +mainline inclusion +from mainline-v5.9-rc6 +commit bfd1b83d75e44a9f65de30accb3dd3b5940bd3ac +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bfd1b83d75e44a9f65de30accb3dd3b5940bd3ac + +---------------------------------------------------------------------- + +Asan reported leak of cpu and thread maps as they have one more refcount +than released. I found that after setting evlist maps it should release +it's refcount. + +It seems to be broken from the beginning so I chose the original commit +as the culprit. But not sure how it's applied to stable trees since +there are many changes in the code after that. + +Fixes: 7e2ed097538c5 ("perf evlist: Store pointer to the cpu and thread maps") +Fixes: 4112eb1899c0e ("perf evlist: Default to syswide target when no thread/cpu maps set") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-4-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/evlist.c +--- + tools/perf/util/evlist.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c +index 18c61f77cc2c..bd791f9af49b 100644 +--- a/tools/perf/util/evlist.c ++++ b/tools/perf/util/evlist.c +@@ -1123,6 +1123,10 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) + + perf_evlist__set_maps(evlist, cpus, threads); + ++ /* as evlist now has references, put count here */ ++ cpu_map__put(cpus); ++ thread_map__put(threads); ++ + return 0; + + out_delete_threads: +@@ -1406,11 +1410,12 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) + goto out_put; + + perf_evlist__set_maps(evlist, cpus, threads); +-out: +- return err; ++ ++ thread_map__put(threads); + out_put: + cpu_map__put(cpus); +- goto out; ++out: ++ return err; + } + + int perf_evlist__open(struct perf_evlist *evlist) +-- +2.27.0 + diff --git a/patches/0255-perf-parse-event-Fix-memory-leak-in-evsel-unit.patch b/patches/0255-perf-parse-event-Fix-memory-leak-in-evsel-unit.patch new file mode 100644 index 0000000..a7d9d65 --- /dev/null +++ b/patches/0255-perf-parse-event-Fix-memory-leak-in-evsel-unit.patch @@ -0,0 +1,74 @@ +From 50e91d8eb4ac16279f7eac0604f03c24824da57b Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:13 +0900 +Subject: [PATCH 138/201] perf parse-event: Fix memory leak in evsel->unit + +mainline inclusion +from mainline-v5.9-rc6 +commit b12eea5ad8e77f8a380a141e3db67c07432dde16 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b12eea5ad8e77f8a380a141e3db67c07432dde16 + +---------------------------------------------------------------------- + +The evsel->unit borrows a pointer of pmu event or alias instead of +owns a string. But tool event (duration_time) passes a result of +strdup() caused a leak. + +It was found by ASAN during metric test: + + Direct leak of 210 byte(s) in 70 object(s) allocated from: + #0 0x7fe366fca0b5 in strdup (/lib/x86_64-linux-gnu/libasan.so.5+0x920b5) + #1 0x559fbbcc6ea3 in add_event_tool util/parse-events.c:414 + #2 0x559fbbcc6ea3 in parse_events_add_tool util/parse-events.c:1414 + #3 0x559fbbd8474d in parse_events_parse util/parse-events.y:439 + #4 0x559fbbcc95da in parse_events__scanner util/parse-events.c:2096 + #5 0x559fbbcc95da in __parse_events util/parse-events.c:2141 + #6 0x559fbbc28555 in check_parse_id tests/pmu-events.c:406 + #7 0x559fbbc28555 in check_parse_id tests/pmu-events.c:393 + #8 0x559fbbc28555 in check_parse_cpu tests/pmu-events.c:415 + #9 0x559fbbc28555 in test_parsing tests/pmu-events.c:498 + #10 0x559fbbc0109b in run_test tests/builtin-test.c:410 + #11 0x559fbbc0109b in test_and_print tests/builtin-test.c:440 + #12 0x559fbbc03e69 in __cmd_test tests/builtin-test.c:695 + #13 0x559fbbc03e69 in cmd_test tests/builtin-test.c:807 + #14 0x559fbbc691f4 in run_builtin /home/namhyung/project/linux/tools/perf/perf.c:312 + #15 0x559fbbb071a8 in handle_internal_command /home/namhyung/project/linux/tools/perf/perf.c:364 + #16 0x559fbbb071a8 in run_argv /home/namhyung/project/linux/tools/perf/perf.c:408 + #17 0x559fbbb071a8 in main /home/namhyung/project/linux/tools/perf/perf.c:538 + #18 0x7fe366b68cc9 in __libc_start_main ../csu/libc-start.c:308 + +Fixes: f0fbb114e3025 ("perf stat: Implement duration_time as a proper event") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-6-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/parse-events.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index b96fe0525b1b..2d20b54866ad 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -367,7 +367,7 @@ static int add_event_tool(struct list_head *list, int *idx, + return -ENOMEM; + evsel->tool_event = tool_event; + if (tool_event == PERF_TOOL_DURATION_TIME) +- evsel->unit = strdup("ns"); ++ evsel->unit = "ns"; + return 0; + } + +-- +2.27.0 + diff --git a/patches/0256-perf-test-Fix-memory-leaks-in-parse-metric-test.patch b/patches/0256-perf-test-Fix-memory-leaks-in-parse-metric-test.patch new file mode 100644 index 0000000..3fcf1ae --- /dev/null +++ b/patches/0256-perf-test-Fix-memory-leaks-in-parse-metric-test.patch @@ -0,0 +1,87 @@ +From e620e326e3e9f742aab5d960b61e1c24108ec909 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:14 +0900 +Subject: [PATCH 139/201] perf test: Fix memory leaks in parse-metric test + +mainline inclusion +from mainline-v5.9-rc6 +commit f5a56570a3f2c01e5307a972ae7d4636edff7b13 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5a56570a3f2c01e5307a972ae7d4636edff7b13 + +---------------------------------------------------------------------- + +It didn't release resources when there's an error so the +test_recursion_fail() will leak some memory. + +Fixes: 0a507af9c681a ("perf tests: Add parse metric test for ipc metric") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-7-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/parse-metric.c +--- + tools/perf/tests/parse-metric.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 007da421bf95..936953991347 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -148,8 +148,10 @@ static int __compute_metric(const char *name, struct value *vals, + return -ENOMEM; + + cpus = cpu_map__new("0"); +- if (!cpus) ++ if (!cpus) { ++ perf_evlist__delete(evlist); + return -ENOMEM; ++ } + + perf_evlist__set_maps(evlist, cpus, NULL); + +@@ -158,10 +160,11 @@ static int __compute_metric(const char *name, struct value *vals, + false, false, + &metric_events); + if (err) +- return err; ++ goto out; + +- if (perf_evlist__alloc_stats(evlist, false)) +- return -1; ++ err = perf_evlist__alloc_stats(evlist, false); ++ if (err) ++ goto out; + + /* Load the runtime stats with given numbers for events. */ + runtime_stat__init(&st); +@@ -173,13 +176,14 @@ static int __compute_metric(const char *name, struct value *vals, + if (name2 && ratio2) + *ratio2 = compute_single(&metric_events, evlist, &st, name2); + ++out: + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + perf_evlist__free_stats(evlist); + cpu_map__put(cpus); + perf_evlist__delete(evlist); +- return 0; ++ return err; + } + + static int compute_metric(const char *name, struct value *vals, double *ratio) +-- +2.27.0 + diff --git a/patches/0257-perf-metric-Release-expr_parse_ctx-after-testing.patch b/patches/0257-perf-metric-Release-expr_parse_ctx-after-testing.patch new file mode 100644 index 0000000..6b8c980 --- /dev/null +++ b/patches/0257-perf-metric-Release-expr_parse_ctx-after-testing.patch @@ -0,0 +1,84 @@ +From 7101da9fa3f4e09c172ad02aca7c5b767b1639d3 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:15 +0900 +Subject: [PATCH 140/201] perf metric: Release expr_parse_ctx after testing + +mainline inclusion +from mainline-v5.9-rc6 +commit 437822bf38c1dc3bda6ffde52689e4e667046a6a +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=437822bf38c1dc3bda6ffde52689e4e667046a6a + +---------------------------------------------------------------------- + +The test_generic_metric() missed to release entries in the pctx. Asan +reported following leak (and more): + + Direct leak of 128 byte(s) in 1 object(s) allocated from: + #0 0x7f4c9396980e in calloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10780e) + #1 0x55f7e748cc14 in hashmap_grow (/home/namhyung/project/linux/tools/perf/perf+0x90cc14) + #2 0x55f7e748d497 in hashmap__insert (/home/namhyung/project/linux/tools/perf/perf+0x90d497) + #3 0x55f7e7341667 in hashmap__set /home/namhyung/project/linux/tools/perf/util/hashmap.h:111 + #4 0x55f7e7341667 in expr__add_ref util/expr.c:120 + #5 0x55f7e7292436 in prepare_metric util/stat-shadow.c:783 + #6 0x55f7e729556d in test_generic_metric util/stat-shadow.c:858 + #7 0x55f7e712390b in compute_single tests/parse-metric.c:128 + #8 0x55f7e712390b in __compute_metric tests/parse-metric.c:180 + #9 0x55f7e712446d in compute_metric tests/parse-metric.c:196 + #10 0x55f7e712446d in test_dcache_l2 tests/parse-metric.c:295 + #11 0x55f7e712446d in test__parse_metric tests/parse-metric.c:355 + #12 0x55f7e70be09b in run_test tests/builtin-test.c:410 + #13 0x55f7e70be09b in test_and_print tests/builtin-test.c:440 + #14 0x55f7e70c101a in __cmd_test tests/builtin-test.c:661 + #15 0x55f7e70c101a in cmd_test tests/builtin-test.c:807 + #16 0x55f7e7126214 in run_builtin /home/namhyung/project/linux/tools/perf/perf.c:312 + #17 0x55f7e6fc41a8 in handle_internal_command /home/namhyung/project/linux/tools/perf/perf.c:364 + #18 0x55f7e6fc41a8 in run_argv /home/namhyung/project/linux/tools/perf/perf.c:408 + #19 0x55f7e6fc41a8 in main /home/namhyung/project/linux/tools/perf/perf.c:538 + #20 0x7f4c93492cc9 in __libc_start_main ../csu/libc-start.c:308 + +Fixes: 6d432c4c8aa56 ("perf tools: Add test_generic_metric function") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-8-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/stat-shadow.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c +index 48a2a58e282f..5fe084048ed3 100644 +--- a/tools/perf/util/stat-shadow.c ++++ b/tools/perf/util/stat-shadow.c +@@ -850,14 +850,16 @@ static void generic_metric(struct perf_stat_config *config, + double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) + { + struct expr_parse_ctx pctx; +- double ratio; ++ double ratio = 0.0; + + if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0) +- return 0.; ++ goto out; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) +- return 0.; ++ ratio = 0.0; + ++out: ++ expr__ctx_clear(&pctx); + return ratio; + } + +-- +2.27.0 + diff --git a/patches/0258-perf-metric-Free-metric-when-it-failed-to-resolve.patch b/patches/0258-perf-metric-Free-metric-when-it-failed-to-resolve.patch new file mode 100644 index 0000000..915b556 --- /dev/null +++ b/patches/0258-perf-metric-Free-metric-when-it-failed-to-resolve.patch @@ -0,0 +1,109 @@ +From 692618b55edbdf1807d7b6f58689d7a419ed9934 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:16 +0900 +Subject: [PATCH 141/201] perf metric: Free metric when it failed to resolve + +mainline inclusion +from mainline-v5.9-rc6 +commit 27adafcda3d8b8a818e85d58eea95b85b5f513f9 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=27adafcda3d8b8a818e85d58eea95b85b5f513f9 + +---------------------------------------------------------------------- + +The metricgroup__add_metric() can find multiple match for a metric group +and it's possible to fail. Also it can fail in the middle like in +resolve_metric() even for single metric. + +In those cases, the intermediate list and ids will be leaked like: + + Direct leak of 3 byte(s) in 1 object(s) allocated from: + #0 0x7f4c938f40b5 in strdup (/lib/x86_64-linux-gnu/libasan.so.5+0x920b5) + #1 0x55f7e71c1bef in __add_metric util/metricgroup.c:683 + #2 0x55f7e71c31d0 in add_metric util/metricgroup.c:906 + #3 0x55f7e71c3844 in metricgroup__add_metric util/metricgroup.c:940 + #4 0x55f7e71c488d in metricgroup__add_metric_list util/metricgroup.c:993 + #5 0x55f7e71c488d in parse_groups util/metricgroup.c:1045 + #6 0x55f7e71c60a4 in metricgroup__parse_groups_test util/metricgroup.c:1087 + #7 0x55f7e71235ae in __compute_metric tests/parse-metric.c:164 + #8 0x55f7e7124650 in compute_metric tests/parse-metric.c:196 + #9 0x55f7e7124650 in test_recursion_fail tests/parse-metric.c:318 + #10 0x55f7e7124650 in test__parse_metric tests/parse-metric.c:356 + #11 0x55f7e70be09b in run_test tests/builtin-test.c:410 + #12 0x55f7e70be09b in test_and_print tests/builtin-test.c:440 + #13 0x55f7e70c101a in __cmd_test tests/builtin-test.c:661 + #14 0x55f7e70c101a in cmd_test tests/builtin-test.c:807 + #15 0x55f7e7126214 in run_builtin /home/namhyung/project/linux/tools/perf/perf.c:312 + #16 0x55f7e6fc41a8 in handle_internal_command /home/namhyung/project/linux/tools/perf/perf.c:364 + #17 0x55f7e6fc41a8 in run_argv /home/namhyung/project/linux/tools/perf/perf.c:408 + #18 0x55f7e6fc41a8 in main /home/namhyung/project/linux/tools/perf/perf.c:538 + #19 0x7f4c93492cc9 in __libc_start_main ../csu/libc-start.c:308 + +Fixes: 83de0b7d535de ("perf metric: Collect referenced metrics in struct metric_ref_node") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-9-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index d42bf52f798c..c7fe63714cfe 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -947,7 +947,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + + ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids); + if (ret) +- return ret; ++ goto out; + + /* + * Process any possible referenced metrics +@@ -956,12 +956,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + ret = resolve_metric(metric_no_group, + &list, map, &ids); + if (ret) +- return ret; ++ goto out; + } + + /* End of pmu events. */ +- if (!has_match) +- return -EINVAL; ++ if (!has_match) { ++ ret = -EINVAL; ++ goto out; ++ } + + list_for_each_entry(m, &list, nd) { + if (events->len > 0) +@@ -976,9 +978,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + } + } + ++out: ++ /* ++ * add to metric_list so that they can be released ++ * even if it's failed ++ */ + list_splice(&list, metric_list); + expr_ids__exit(&ids); +- return 0; ++ return ret; + } + + static int metricgroup__add_metric_list(const char *list, bool metric_no_group, +-- +2.27.0 + diff --git a/patches/0259-perf-metric-Do-not-free-metric-when-failed-to-resolv.patch b/patches/0259-perf-metric-Do-not-free-metric-when-failed-to-resolv.patch new file mode 100644 index 0000000..34c0285 --- /dev/null +++ b/patches/0259-perf-metric-Do-not-free-metric-when-failed-to-resolv.patch @@ -0,0 +1,77 @@ +From 8789980267b2e5f42aeeef63d9a5a53fcc531c84 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:17 +0900 +Subject: [PATCH 142/201] perf metric: Do not free metric when failed to + resolve + +mainline inclusion +from mainline-v5.9-rc6 +commit 6f47ed6cd12a0ea9b55b19b5d6e4a3b490a97bdf +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6f47ed6cd12a0ea9b55b19b5d6e4a3b490a97bdf + +---------------------------------------------------------------------- + +It's dangerous to free the original metric when it's called from +resolve_metric() as it's already in the metric_list and might have other +resources too. Instead, it'd better let them bail out and be released +properly at the later stage. + +So add a check when it's called from metricgroup__add_metric() and +release it. Also make sure that mp is set properly. + +Fixes: 83de0b7d535de ("perf metric: Collect referenced metrics in struct metric_ref_node") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-10-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index c7fe63714cfe..0e33f3f82478 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -680,7 +680,6 @@ static int __add_metric(struct list_head *metric_list, + m->has_constraint = metric_no_group || metricgroup__has_constraint(pe); + INIT_LIST_HEAD(&m->metric_refs); + m->metric_refs_cnt = 0; +- *mp = m; + + parent = expr_ids__alloc(ids); + if (!parent) { +@@ -693,6 +692,7 @@ static int __add_metric(struct list_head *metric_list, + free(m); + return -ENOMEM; + } ++ *mp = m; + } else { + /* + * We got here for the referenced metric, via the +@@ -727,8 +727,11 @@ static int __add_metric(struct list_head *metric_list, + * all the metric's IDs and add it to the parent context. + */ + if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) { +- expr__ctx_clear(&m->pctx); +- free(m); ++ if (m->metric_refs_cnt == 0) { ++ expr__ctx_clear(&m->pctx); ++ free(m); ++ *mp = NULL; ++ } + return -EINVAL; + } + +-- +2.27.0 + diff --git a/patches/0260-perf-test-Free-formats-for-perf-pmu-parse-test.patch b/patches/0260-perf-test-Free-formats-for-perf-pmu-parse-test.patch new file mode 100644 index 0000000..def4358 --- /dev/null +++ b/patches/0260-perf-test-Free-formats-for-perf-pmu-parse-test.patch @@ -0,0 +1,100 @@ +From 44233997362ff5cabc1fe802df0b37098cd58154 Mon Sep 17 00:00:00 2001 +From: Namhyung Kim +Date: Tue, 15 Sep 2020 12:18:19 +0900 +Subject: [PATCH 143/201] perf test: Free formats for perf pmu parse test + +mainline inclusion +from mainline-v5.9-rc6 +commit d26383dcb2b4b8629fde05270b4e3633be9e3d4b +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d26383dcb2b4b8629fde05270b4e3633be9e3d4b + +---------------------------------------------------------------------- + +The following leaks were detected by ASAN: + + Indirect leak of 360 byte(s) in 9 object(s) allocated from: + #0 0x7fecc305180e in calloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10780e) + #1 0x560578f6dce5 in perf_pmu__new_format util/pmu.c:1333 + #2 0x560578f752fc in perf_pmu_parse util/pmu.y:59 + #3 0x560578f6a8b7 in perf_pmu__format_parse util/pmu.c:73 + #4 0x560578e07045 in test__pmu tests/pmu.c:155 + #5 0x560578de109b in run_test tests/builtin-test.c:410 + #6 0x560578de109b in test_and_print tests/builtin-test.c:440 + #7 0x560578de401a in __cmd_test tests/builtin-test.c:661 + #8 0x560578de401a in cmd_test tests/builtin-test.c:807 + #9 0x560578e49354 in run_builtin /home/namhyung/project/linux/tools/perf/perf.c:312 + #10 0x560578ce71a8 in handle_internal_command /home/namhyung/project/linux/tools/perf/perf.c:364 + #11 0x560578ce71a8 in run_argv /home/namhyung/project/linux/tools/perf/perf.c:408 + #12 0x560578ce71a8 in main /home/namhyung/project/linux/tools/perf/perf.c:538 + #13 0x7fecc2b7acc9 in __libc_start_main ../csu/libc-start.c:308 + +Fixes: cff7f956ec4a1 ("perf tests: Move pmu tests into separate object") +Signed-off-by: Namhyung Kim +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200915031819.386559-12-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu.c | 1 + + tools/perf/util/pmu.c | 11 +++++++++++ + tools/perf/util/pmu.h | 1 + + 3 files changed, 13 insertions(+) + +diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c +index 7bedf8608fdd..3e183eef6f85 100644 +--- a/tools/perf/tests/pmu.c ++++ b/tools/perf/tests/pmu.c +@@ -172,6 +172,7 @@ int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused) + ret = 0; + } while (0); + ++ perf_pmu__del_formats(&formats); + test_format_dir_put(format); + return ret; + } +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index cce165d80146..6f646252a18b 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -1331,6 +1331,17 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to) + set_bit(b, bits); + } + ++void perf_pmu__del_formats(struct list_head *formats) ++{ ++ struct perf_pmu_format *fmt, *tmp; ++ ++ list_for_each_entry_safe(fmt, tmp, formats, list) { ++ list_del(&fmt->list); ++ free(fmt->name); ++ free(fmt); ++ } ++} ++ + static int sub_non_neg(int a, int b) + { + if (b > a) +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 555a917406e6..aeb7bce2ab87 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -83,6 +83,7 @@ int perf_pmu__new_format(struct list_head *list, char *name, + int config, unsigned long *bits); + void perf_pmu__set_format(unsigned long *bits, long from, long to); + int perf_pmu__format_parse(char *dir, struct list_head *head); ++void perf_pmu__del_formats(struct list_head *formats); + + struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); + +-- +2.27.0 + diff --git a/patches/0261-perf-metricgroup-Fix-uncore-metric-expressions.patch b/patches/0261-perf-metricgroup-Fix-uncore-metric-expressions.patch new file mode 100644 index 0000000..367096e --- /dev/null +++ b/patches/0261-perf-metricgroup-Fix-uncore-metric-expressions.patch @@ -0,0 +1,204 @@ +From 0c2fda9edf394462458adf6adae2ec77792f5f87 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Thu, 17 Sep 2020 13:18:07 -0700 +Subject: [PATCH 144/201] perf metricgroup: Fix uncore metric expressions + +mainline inclusion +from mainline-v5.10-rc1 +commit dcc81be0fc4e66943041e6e19a5faf8f8704a27e +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dcc81be0fc4e66943041e6e19a5faf8f8704a27e + +---------------------------------------------------------------------- + +A metric like DRAM_BW_Use has on SkylakeX events uncore_imc/cas_count_read/ +and uncore_imc/case_count_write/. + +These events open 6 events per socket with pmu names of +uncore_imc_[0-5]. + +The current metric setup code in find_evsel_group assumes one ID will +map to 1 event to be recorded in metric_events. + +For events with multiple matches, the first event is recorded in +metric_events (avoiding matching >1 event with the same name) and the +evlist_used updated so that duplicate events aren't removed when the +evlist has unused events removed. + +Before this change: + + $ /tmp/perf/perf stat -M DRAM_BW_Use -a -- sleep 1 + + Performance counter stats for 'system wide': + + 41.14 MiB uncore_imc/cas_count_read/ + 1,002,614,251 ns duration_time + + 1.002614251 seconds time elapsed + +After this change: + + $ /tmp/perf/perf stat -M DRAM_BW_Use -a -- sleep 1 + + Performance counter stats for 'system wide': + + 157.47 MiB uncore_imc/cas_count_read/ # 0.00 DRAM_BW_Use + 126.97 MiB uncore_imc/cas_count_write/ + 1,003,019,728 ns duration_time + +Erroneous duplication introduced in: +commit 2440689d62e9 ("perf metricgroup: Remove duped metric group events"). + +Fixes: ded80bda8bc9 ("perf expr: Migrate expr ids table to a hashmap"). +Reported-by: Jin Yao +Signed-off-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Alexei Starovoitov +Cc: Andi Kleen +Cc: Andrii Nakryiko +Cc: Athira Jajeev +Cc: Daniel Borkmann +Cc: Jiri Olsa +Cc: John Fastabend +Cc: KP Singh +Cc: Mark Rutland +Cc: Martin KaFai Lau +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Stephane Eranian +Cc: Yonghong Song +Cc: bpf@vger.kernel.org +Cc: netdev@vger.kernel.org +Link: http://lore.kernel.org/lkml/20200917201807.4090224-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 75 ++++++++++++++++++++++++++--------- + 1 file changed, 56 insertions(+), 19 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 0e33f3f82478..10b5f92ccad8 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -155,6 +155,18 @@ static void expr_ids__exit(struct expr_ids *ids) + free(ids->id[i].id); + } + ++static bool contains_event(struct perf_evsel **metric_events, int num_events, ++ const char *event_name) ++{ ++ int i; ++ ++ for (i = 0; i < num_events; i++) { ++ if (!strcmp(metric_events[i]->name, event_name)) ++ return true; ++ } ++ return false; ++} ++ + /** + * Find a group of events in perf_evlist that correspond to those from a parsed + * metric expression. Note, as find_evsel_group is called in the same order as +@@ -185,7 +197,11 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + int i = 0, matched_events = 0, events_to_match; + const int idnum = (int)hashmap__size(&pctx->ids); + +- /* duration_time is grouped separately. */ ++ /* ++ * duration_time is always grouped separately, when events are grouped ++ * (ie has_constraint is false) then ignore it in the matching loop and ++ * add it to metric_events at the end. ++ */ + if (!has_constraint && + hashmap__find(&pctx->ids, "duration_time", (void **)&val_ptr)) + events_to_match = idnum - 1; +@@ -212,23 +228,20 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + sizeof(struct perf_evsel *) * idnum); + current_leader = ev->leader; + } +- if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) { +- if (has_constraint) { +- /* +- * Events aren't grouped, ensure the same event +- * isn't matched from two groups. +- */ +- for (i = 0; i < matched_events; i++) { +- if (!strcmp(ev->name, +- metric_events[i]->name)) { +- break; +- } +- } +- if (i != matched_events) +- continue; +- } ++ /* ++ * Check for duplicate events with the same name. For example, ++ * uncore_imc/cas_count_read/ will turn into 6 events per socket ++ * on skylakex. Only the first such event is placed in ++ * metric_events. If events aren't grouped then this also ++ * ensures that the same event in different sibling groups ++ * aren't both added to metric_events. ++ */ ++ if (contains_event(metric_events, matched_events, ev->name)) ++ continue; ++ /* Does this event belong to the parse context? */ ++ if (hashmap__find(&pctx->ids, ev->name, (void **)&val_ptr)) + metric_events[matched_events++] = ev; +- } ++ + if (matched_events == events_to_match) + break; + } +@@ -244,7 +257,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + } + + if (matched_events != idnum) { +- /* Not whole match */ ++ /* Not a whole match */ + return NULL; + } + +@@ -252,8 +265,32 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + + for (i = 0; i < idnum; i++) { + ev = metric_events[i]; +- ev->metric_leader = ev; ++ /* Don't free the used events. */ + set_bit(ev->idx, evlist_used); ++ /* ++ * The metric leader points to the identically named event in ++ * metric_events. ++ */ ++ ev->metric_leader = ev; ++ /* ++ * Mark two events with identical names in the same group (or ++ * globally) as being in use as uncore events may be duplicated ++ * for each pmu. Set the metric leader of such events to be the ++ * event that appears in metric_events. ++ */ ++ evlist__for_each_entry_continue(perf_evlist, ev) { ++ /* ++ * If events are grouped then the search can terminate ++ * when then group is left. ++ */ ++ if (!has_constraint && ++ ev->leader != metric_events[i]->leader) ++ break; ++ if (!strcmp(metric_events[i]->name, ev->name)) { ++ set_bit(ev->idx, evlist_used); ++ ev->metric_leader = metric_events[i]; ++ } ++ } + } + + return metric_events[0]; +-- +2.27.0 + diff --git a/patches/0262-perf-metricgroup-Make-find_metric-public-with-name-c.patch b/patches/0262-perf-metricgroup-Make-find_metric-public-with-name-c.patch new file mode 100644 index 0000000..a8eebac --- /dev/null +++ b/patches/0262-perf-metricgroup-Make-find_metric-public-with-name-c.patch @@ -0,0 +1,84 @@ +From 5df8ed259257857d75454161bfaa79c315674747 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:45 +0800 +Subject: [PATCH 145/201] perf metricgroup: Make find_metric() public with name + change + +mainline inclusion +from mainline-v5.13-rc1 +commit dedb76d3598618e67b3a9af89bf4f418430acbe4 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dedb76d3598618e67b3a9af89bf4f418430acbe4 + +---------------------------------------------------------------------- + +Function find_metric() is required for the metric processing in the +pmu-events testcase, so make it public. Also change the name to include +"metricgroup". + +Tested-by: Paul A. Clarke +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linuxarm@huawei.com +Cc: linux-arm-kernel@lists.infradead.org +Link: https://lore.kernel.org/r/1617791570-165223-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 5 +++-- + tools/perf/util/metricgroup.h | 2 ++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 10b5f92ccad8..21418ad88cb5 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -809,7 +809,8 @@ static int __add_metric(struct list_head *metric_list, + (match_metric(__pe->metric_group, __metric) || \ + match_metric(__pe->metric_name, __metric))) + +-static struct pmu_event *find_metric(const char *metric, struct pmu_events_map *map) ++struct pmu_event *metricgroup__find_metric(const char *metric, ++ struct pmu_events_map *map) + { + struct pmu_event *pe; + int i; +@@ -894,7 +895,7 @@ static int __resolve_metric(struct metric *m, + struct expr_id *parent; + struct pmu_event *pe; + +- pe = find_metric(cur->key, map); ++ pe = metricgroup__find_metric(cur->key, map); + if (!pe) + continue; + +diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h +index 3670a8528ca5..75266dcd8830 100644 +--- a/tools/perf/util/metricgroup.h ++++ b/tools/perf/util/metricgroup.h +@@ -43,6 +43,8 @@ int metricgroup__parse_groups(const struct option *opt, + bool metric_no_merge, + struct rblist *metric_events); + ++struct pmu_event *metricgroup__find_metric(const char *metric, ++ struct pmu_events_map *map); + int metricgroup__parse_groups_test(struct perf_evlist *evlist, + struct pmu_events_map *map, + const char *str, +-- +2.27.0 + diff --git a/patches/0263-perf-test-Handle-metric-reuse-in-pmu-events-parsing-.patch b/patches/0263-perf-test-Handle-metric-reuse-in-pmu-events-parsing-.patch new file mode 100644 index 0000000..d52dce7 --- /dev/null +++ b/patches/0263-perf-test-Handle-metric-reuse-in-pmu-events-parsing-.patch @@ -0,0 +1,176 @@ +From cff01f714e1f3dca7c7a48b98a0e24576a59c262 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:46 +0800 +Subject: [PATCH 146/201] perf test: Handle metric reuse in pmu-events parsing + test + +mainline inclusion +from mainline-v5.13-rc1 +commit a48a995edcde832f2d4c4ec1bfb73e0da93810fb +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a48a995edcde832f2d4c4ec1bfb73e0da93810fb + +---------------------------------------------------------------------- + +The pmu-events parsing test does not handle metric reuse at all. + +Introduce some simple handling to resolve metrics who reference other +metrics. + +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Tested-by: Paul A. Clarke +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linuxarm@huawei.com +Cc: linux-arm-kernel@lists.infradead.org +Link: https://lore.kernel.org/r/1617791570-165223-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 81 +++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 83712bde93f4..cde921bb8e0a 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -12,6 +12,7 @@ + #include "util/evlist.h" + #include "util/expr.h" + #include "util/parse-events.h" ++#include "metricgroup.h" + + struct perf_pmu_test_event { + struct pmu_event event; +@@ -453,6 +454,71 @@ static void expr_failure(const char *msg, + pr_debug("On expression %s\n", pe->metric_expr); + } + ++struct metric { ++ struct list_head list; ++ struct metric_ref metric_ref; ++}; ++ ++static int resolve_metric_simple(struct expr_parse_ctx *pctx, ++ struct list_head *compound_list, ++ struct pmu_events_map *map, ++ const char *metric_name) ++{ ++ struct hashmap_entry *cur, *cur_tmp; ++ struct metric *metric, *tmp; ++ size_t bkt; ++ bool all; ++ int rc; ++ ++ do { ++ all = true; ++ hashmap__for_each_entry_safe((&pctx->ids), cur, cur_tmp, bkt) { ++ struct metric_ref *ref; ++ struct pmu_event *pe; ++ ++ pe = metricgroup__find_metric(cur->key, map); ++ if (!pe) ++ continue; ++ ++ if (!strcmp(metric_name, (char *)cur->key)) { ++ pr_warning("Recursion detected for metric %s\n", metric_name); ++ rc = -1; ++ goto out_err; ++ } ++ ++ all = false; ++ ++ /* The metric key itself needs to go out.. */ ++ expr__del_id(pctx, cur->key); ++ ++ metric = malloc(sizeof(*metric)); ++ if (!metric) { ++ rc = -ENOMEM; ++ goto out_err; ++ } ++ ++ ref = &metric->metric_ref; ++ ref->metric_name = pe->metric_name; ++ ref->metric_expr = pe->metric_expr; ++ list_add_tail(&metric->list, compound_list); ++ ++ rc = expr__find_other(pe->metric_expr, NULL, pctx, 0); ++ if (rc) ++ goto out_err; ++ break; /* The hashmap has been modified, so restart */ ++ } ++ } while (!all); ++ ++ return 0; ++ ++out_err: ++ list_for_each_entry_safe(metric, tmp, compound_list, list) ++ free(metric); ++ ++ return rc; ++ ++} ++ + static int test_parsing(void) + { + struct pmu_events_map *cpus_map = perf_pmu__find_map(NULL); +@@ -470,7 +536,9 @@ static int test_parsing(void) + break; + j = 0; + for (;;) { ++ struct metric *metric, *tmp; + struct hashmap_entry *cur; ++ LIST_HEAD(compound_list); + size_t bkt; + + pe = &map->table[j++]; +@@ -486,6 +554,13 @@ static int test_parsing(void) + continue; + } + ++ if (resolve_metric_simple(&ctx, &compound_list, map, ++ pe->metric_name)) { ++ expr_failure("Could not resolve metrics", map, pe); ++ ret++; ++ goto exit; /* Don't tolerate errors due to severity */ ++ } ++ + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to +@@ -501,6 +576,11 @@ static int test_parsing(void) + ret++; + } + ++ list_for_each_entry_safe(metric, tmp, &compound_list, list) { ++ expr__add_ref(&ctx, &metric->metric_ref); ++ free(metric); ++ } ++ + if (expr__parse(&result, &ctx, pe->metric_expr, 0)) { + expr_failure("Parse failed", map, pe); + ret++; +@@ -509,6 +589,7 @@ static int test_parsing(void) + } + } + /* TODO: fail when not ok */ ++exit: + return ret == 0 ? TEST_OK : TEST_SKIP; + } + +-- +2.27.0 + diff --git a/patches/0264-perf-pmu-Add-pmu_events_map__find-function-to-find-t.patch b/patches/0264-perf-pmu-Add-pmu_events_map__find-function-to-find-t.patch new file mode 100644 index 0000000..9bca8ce --- /dev/null +++ b/patches/0264-perf-pmu-Add-pmu_events_map__find-function-to-find-t.patch @@ -0,0 +1,174 @@ +From 77464e0f1abfaedecccf7a69a07938f6b1f2f040 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:47 +0800 +Subject: [PATCH 147/201] perf pmu: Add pmu_events_map__find() function to find + the common PMU map for the system + +mainline inclusion +from mainline-v5.13-rc1 +commit e126bef55f1dfb44440d632f9aae66af3240a435 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e126bef55f1dfb44440d632f9aae66af3240a435 + +---------------------------------------------------------------------- + +Add a function to find the common PMU map for the system. + +For arm64, a special variant is added. This is because arm64 supports +heterogeneous CPU systems. As such, it cannot be guaranteed that the +cpumap is same for all CPUs. So in case of heterogeneous systems, don't +return a cpumap. + +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Tested-by: Paul A. Clarke +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: https://lore.kernel.org/r/1617791570-165223-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/arch/arm64/util/Build + tools/perf/util/metricgroup.c +--- + tools/perf/arch/arm64/util/Build | 1 + + tools/perf/arch/arm64/util/pmu.c | 25 +++++++++++++++++++++++++ + tools/perf/tests/pmu-events.c | 2 +- + tools/perf/util/metricgroup.c | 6 +++--- + tools/perf/util/pmu.c | 5 +++++ + tools/perf/util/pmu.h | 1 + + 6 files changed, 36 insertions(+), 4 deletions(-) + create mode 100644 tools/perf/arch/arm64/util/pmu.c + +diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build +index 393b9895c247..4d8b90987f2d 100644 +--- a/tools/perf/arch/arm64/util/Build ++++ b/tools/perf/arch/arm64/util/Build +@@ -1,5 +1,6 @@ + libperf-y += header.o + libperf-y += tsc.o ++libperf-y += pmu.o + libperf-y += sym-handling.o + libperf-y += kvm-stat.o + libperf-$(CONFIG_DWARF) += dwarf-regs.o +diff --git a/tools/perf/arch/arm64/util/pmu.c b/tools/perf/arch/arm64/util/pmu.c +new file mode 100644 +index 000000000000..d3259d61ca75 +--- /dev/null ++++ b/tools/perf/arch/arm64/util/pmu.c +@@ -0,0 +1,25 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "../../util/cpumap.h" ++#include "../../util/pmu.h" ++ ++struct pmu_events_map *pmu_events_map__find(void) ++{ ++ struct perf_pmu *pmu = NULL; ++ ++ while ((pmu = perf_pmu__scan(pmu))) { ++ if (!is_pmu_core(pmu->name)) ++ continue; ++ ++ /* ++ * The cpumap should cover all CPUs. Otherwise, some CPUs may ++ * not support some events or have different event IDs. ++ */ ++ if (pmu->cpus->nr != cpu__max_cpu()) ++ return NULL; ++ ++ return perf_pmu__find_map(pmu); ++ } ++ ++ return NULL; ++} +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index cde921bb8e0a..bc7d75f24d59 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -521,7 +521,7 @@ static int resolve_metric_simple(struct expr_parse_ctx *pctx, + + static int test_parsing(void) + { +- struct pmu_events_map *cpus_map = perf_pmu__find_map(NULL); ++ struct pmu_events_map *cpus_map = pmu_events_map__find(); + struct pmu_events_map *map; + struct pmu_event *pe; + int i, j, k; +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 21418ad88cb5..ac27441a0e28 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -499,7 +499,7 @@ static void metricgroup__print_strlist(struct strlist *metrics, bool raw) + void metricgroup__print(bool metrics, bool metricgroups, char *filter, + bool raw, bool details) + { +- struct pmu_events_map *map = perf_pmu__find_map(NULL); ++ struct pmu_events_map *map = pmu_events_map__find(); + struct pmu_event *pe; + int i; + struct rblist groups; +@@ -1124,7 +1124,7 @@ int metricgroup__parse_groups(const struct option *opt, + struct rblist *metric_events) + { + struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; +- struct pmu_events_map *map = perf_pmu__find_map(NULL); ++ struct pmu_events_map *map = pmu_events_map__find(); + + if (!map) + return 0; +@@ -1146,7 +1146,7 @@ int metricgroup__parse_groups_test(struct perf_evlist *evlist, + + bool metricgroup__has_metric(const char *metric) + { +- struct pmu_events_map *map = perf_pmu__find_map(NULL); ++ struct pmu_events_map *map = pmu_events_map__find(); + struct pmu_event *pe; + int i; + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 6f646252a18b..b8594a6c0c23 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -747,6 +747,11 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) + return map; + } + ++struct pmu_events_map *__weak pmu_events_map__find(void) ++{ ++ return perf_pmu__find_map(NULL); ++} ++ + bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + { + char *tmp = NULL, *tok, *str; +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index aeb7bce2ab87..b440053bf4e7 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -102,6 +102,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, + struct pmu_events_map *map); + + struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); ++struct pmu_events_map *pmu_events_map__find(void); + bool pmu_uncore_alias_match(const char *pmu_name, const char *name); + void perf_pmu_free_alias(struct perf_pmu_alias *alias); + +-- +2.27.0 + diff --git a/patches/0265-perf-vendor-events-arm64-Add-Hisi-hip08-L1-metrics.patch b/patches/0265-perf-vendor-events-arm64-Add-Hisi-hip08-L1-metrics.patch new file mode 100644 index 0000000..2b819f2 --- /dev/null +++ b/patches/0265-perf-vendor-events-arm64-Add-Hisi-hip08-L1-metrics.patch @@ -0,0 +1,82 @@ +From 81da9cc08bdff46a0d2e71cb5c703b4337d59e1a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:48 +0800 +Subject: [PATCH 148/201] perf vendor events arm64: Add Hisi hip08 L1 metrics + +mainline inclusion +from mainline-v5.13-rc1 +commit c4e1dc4a94931805fd4c69de71117dc040d8db2a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c4e1dc4a94931805fd4c69de71117dc040d8db2a + +---------------------------------------------------------------------- + +Add L1 metrics. Formula is as consistent as possible with MAN pages +description for these metrics. + +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: https://lore.kernel.org/r/1617791570-165223-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/arm64/hisilicon/hip08/metrics.json | 30 +++++++++++++++++++ + 1 file changed, 30 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +new file mode 100644 +index 000000000000..dc5ff3051639 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +@@ -0,0 +1,30 @@ ++[ ++ { ++ "MetricExpr": "FETCH_BUBBLE / (4 * CPU_CYCLES)", ++ "PublicDescription": "Frontend bound L1 topdown metric", ++ "BriefDescription": "Frontend bound L1 topdown metric", ++ "MetricGroup": "TopDownL1", ++ "MetricName": "frontend_bound" ++ }, ++ { ++ "MetricExpr": "(INST_SPEC - INST_RETIRED) / (4 * CPU_CYCLES)", ++ "PublicDescription": "Bad Speculation L1 topdown metric", ++ "BriefDescription": "Bad Speculation L1 topdown metric", ++ "MetricGroup": "TopDownL1", ++ "MetricName": "bad_speculation" ++ }, ++ { ++ "MetricExpr": "INST_RETIRED / (CPU_CYCLES * 4)", ++ "PublicDescription": "Retiring L1 topdown metric", ++ "BriefDescription": "Retiring L1 topdown metric", ++ "MetricGroup": "TopDownL1", ++ "MetricName": "retiring" ++ }, ++ { ++ "MetricExpr": "1 - (frontend_bound + bad_speculation + retiring)", ++ "PublicDescription": "Backend Bound L1 topdown metric", ++ "BriefDescription": "Backend Bound L1 topdown metric", ++ "MetricGroup": "TopDownL1", ++ "MetricName": "backend_bound" ++ }, ++] +-- +2.27.0 + diff --git a/patches/0266-perf-vendor-events-arm64-Add-Hisi-hip08-L2-metrics.patch b/patches/0266-perf-vendor-events-arm64-Add-Hisi-hip08-L2-metrics.patch new file mode 100644 index 0000000..4101741 --- /dev/null +++ b/patches/0266-perf-vendor-events-arm64-Add-Hisi-hip08-L2-metrics.patch @@ -0,0 +1,95 @@ +From d78a77dcad718be645b3aa5b269a4694346ba598 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:49 +0800 +Subject: [PATCH 149/201] perf vendor events arm64: Add Hisi hip08 L2 metrics + +mainline inclusion +from mainline-v5.13-rc1 +commit 03837173487a1c664b71f047e97209112be37dd5 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=03837173487a1c664b71f047e97209112be37dd5 + +---------------------------------------------------------------------- + +Add L2 metrics. + +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: https://lore.kernel.org/r/1617791570-165223-6-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/arm64/hisilicon/hip08/metrics.json | 42 +++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +index dc5ff3051639..dda898d23c2d 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +@@ -27,4 +27,46 @@ + "MetricGroup": "TopDownL1", + "MetricName": "backend_bound" + }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x201d@ / CPU_CYCLES", ++ "PublicDescription": "Fetch latency bound L2 topdown metric", ++ "BriefDescription": "Fetch latency bound L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "fetch_latency_bound" ++ }, ++ { ++ "MetricExpr": "frontend_bound - fetch_latency_bound", ++ "PublicDescription": "Fetch bandwidth bound L2 topdown metric", ++ "BriefDescription": "Fetch bandwidth bound L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "fetch_bandwidth_bound" ++ }, ++ { ++ "MetricExpr": "(bad_speculation * BR_MIS_PRED) / (BR_MIS_PRED + armv8_pmuv3_0@event\\=0x2013@)", ++ "PublicDescription": "Branch mispredicts L2 topdown metric", ++ "BriefDescription": "Branch mispredicts L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "branch_mispredicts" ++ }, ++ { ++ "MetricExpr": "bad_speculation - branch_mispredicts", ++ "PublicDescription": "Machine clears L2 topdown metric", ++ "BriefDescription": "Machine clears L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "machine_clears" ++ }, ++ { ++ "MetricExpr": "(EXE_STALL_CYCLE - (MEM_STALL_ANYLOAD + armv8_pmuv3_0@event\\=0x7005@)) / CPU_CYCLES", ++ "PublicDescription": "Core bound L2 topdown metric", ++ "BriefDescription": "Core bound L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "core_bound" ++ }, ++ { ++ "MetricExpr": "(MEM_STALL_ANYLOAD + armv8_pmuv3_0@event\\=0x7005@) / CPU_CYCLES", ++ "PublicDescription": "Memory bound L2 topdown metric", ++ "BriefDescription": "Memory bound L2 topdown metric", ++ "MetricGroup": "TopDownL2", ++ "MetricName": "memory_bound" ++ }, + ] +-- +2.27.0 + diff --git a/patches/0267-perf-vendor-events-arm64-Add-Hisi-hip08-L3-metrics.patch b/patches/0267-perf-vendor-events-arm64-Add-Hisi-hip08-L3-metrics.patch new file mode 100644 index 0000000..7f5f96a --- /dev/null +++ b/patches/0267-perf-vendor-events-arm64-Add-Hisi-hip08-L3-metrics.patch @@ -0,0 +1,214 @@ +From 857cc96689206dfaf15be1c3bc5174c3304fc2d6 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Wed, 7 Apr 2021 18:32:50 +0800 +Subject: [PATCH 150/201] perf vendor events arm64: Add Hisi hip08 L3 metrics + +mainline inclusion +from mainline-v5.13-rc1 +commit 0cc177cfc95d565e1a458136a592b0bd6d487db0 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0cc177cfc95d565e1a458136a592b0bd6d487db0 + +---------------------------------------------------------------------- + +Add L3 metrics. + +Reviewed-by: Kajol Jain +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: https://lore.kernel.org/r/1617791570-165223-7-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/arm64/hisilicon/hip08/metrics.json | 161 ++++++++++++++++++ + 1 file changed, 161 insertions(+) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +index dda898d23c2d..dda8e59149d2 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +@@ -69,4 +69,165 @@ + "MetricGroup": "TopDownL2", + "MetricName": "memory_bound" + }, ++ { ++ "MetricExpr": "(((L2I_TLB - L2I_TLB_REFILL) * 15) + (L2I_TLB_REFILL * 100)) / CPU_CYCLES", ++ "PublicDescription": "Idle by itlb miss L3 topdown metric", ++ "BriefDescription": "Idle by itlb miss L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "idle_by_itlb_miss" ++ }, ++ { ++ "MetricExpr": "(((L2I_CACHE - L2I_CACHE_REFILL) * 15) + (L2I_CACHE_REFILL * 100)) / CPU_CYCLES", ++ "PublicDescription": "Idle by icache miss L3 topdown metric", ++ "BriefDescription": "Idle by icache miss L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "idle_by_icache_miss" ++ }, ++ { ++ "MetricExpr": "(BR_MIS_PRED * 5) / CPU_CYCLES", ++ "PublicDescription": "BP misp flush L3 topdown metric", ++ "BriefDescription": "BP misp flush L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "bp_misp_flush" ++ }, ++ { ++ "MetricExpr": "(armv8_pmuv3_0@event\\=0x2013@ * 5) / CPU_CYCLES", ++ "PublicDescription": "OOO flush L3 topdown metric", ++ "BriefDescription": "OOO flush L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "ooo_flush" ++ }, ++ { ++ "MetricExpr": "(armv8_pmuv3_0@event\\=0x1001@ * 5) / CPU_CYCLES", ++ "PublicDescription": "Static predictor flush L3 topdown metric", ++ "BriefDescription": "Static predictor flush L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "sp_flush" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x1010@ / BR_MIS_PRED", ++ "PublicDescription": "Indirect branch L3 topdown metric", ++ "BriefDescription": "Indirect branch L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "indirect_branch" ++ }, ++ { ++ "MetricExpr": "(armv8_pmuv3_0@event\\=0x1014@ + armv8_pmuv3_0@event\\=0x1018@) / BR_MIS_PRED", ++ "PublicDescription": "Push branch L3 topdown metric", ++ "BriefDescription": "Push branch L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "push_branch" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x100c@ / BR_MIS_PRED", ++ "PublicDescription": "Pop branch L3 topdown metric", ++ "BriefDescription": "Pop branch L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "pop_branch" ++ }, ++ { ++ "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\\=0x1010@ - armv8_pmuv3_0@event\\=0x1014@ - armv8_pmuv3_0@event\\=0x1018@ - armv8_pmuv3_0@event\\=0x100c@) / BR_MIS_PRED", ++ "PublicDescription": "Other branch L3 topdown metric", ++ "BriefDescription": "Other branch L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "other_branch" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x2012@ / armv8_pmuv3_0@event\\=0x2013@", ++ "PublicDescription": "Nuke flush L3 topdown metric", ++ "BriefDescription": "Nuke flush L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "nuke_flush" ++ }, ++ { ++ "MetricExpr": "1 - nuke_flush", ++ "PublicDescription": "Other flush L3 topdown metric", ++ "BriefDescription": "Other flush L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "other_flush" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x2010@ / CPU_CYCLES", ++ "PublicDescription": "Sync stall L3 topdown metric", ++ "BriefDescription": "Sync stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "sync_stall" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x2004@ / CPU_CYCLES", ++ "PublicDescription": "Rob stall L3 topdown metric", ++ "BriefDescription": "Rob stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "rob_stall" ++ }, ++ { ++ "MetricExpr": "(armv8_pmuv3_0@event\\=0x2006@ + armv8_pmuv3_0@event\\=0x2007@ + armv8_pmuv3_0@event\\=0x2008@) / CPU_CYCLES", ++ "PublicDescription": "Ptag stall L3 topdown metric", ++ "BriefDescription": "Ptag stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "ptag_stall" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x201e@ / CPU_CYCLES", ++ "PublicDescription": "SaveOpQ stall L3 topdown metric", ++ "BriefDescription": "SaveOpQ stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "saveopq_stall" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x2005@ / CPU_CYCLES", ++ "PublicDescription": "PC buffer stall L3 topdown metric", ++ "BriefDescription": "PC buffer stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "pc_buffer_stall" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x7002@ / CPU_CYCLES", ++ "PublicDescription": "Divider L3 topdown metric", ++ "BriefDescription": "Divider L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "divider" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x7003@ / CPU_CYCLES", ++ "PublicDescription": "FSU stall L3 topdown metric", ++ "BriefDescription": "FSU stall L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "fsu_stall" ++ }, ++ { ++ "MetricExpr": "core_bound - divider - fsu_stall", ++ "PublicDescription": "EXE ports util L3 topdown metric", ++ "BriefDescription": "EXE ports util L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "exe_ports_util" ++ }, ++ { ++ "MetricExpr": "(MEM_STALL_ANYLOAD - MEM_STALL_L1MISS) / CPU_CYCLES", ++ "PublicDescription": "L1 bound L3 topdown metric", ++ "BriefDescription": "L1 bound L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "l1_bound" ++ }, ++ { ++ "MetricExpr": "(MEM_STALL_L1MISS - MEM_STALL_L2MISS) / CPU_CYCLES", ++ "PublicDescription": "L2 bound L3 topdown metric", ++ "BriefDescription": "L2 bound L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "l2_bound" ++ }, ++ { ++ "MetricExpr": "MEM_STALL_L2MISS / CPU_CYCLES", ++ "PublicDescription": "Mem bound L3 topdown metric", ++ "BriefDescription": "Mem bound L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "mem_bound" ++ }, ++ { ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x7005@ / CPU_CYCLES", ++ "PublicDescription": "Store bound L3 topdown metric", ++ "BriefDescription": "Store bound L3 topdown metric", ++ "MetricGroup": "TopDownL3", ++ "MetricName": "store_bound" ++ }, + ] +-- +2.27.0 + diff --git a/patches/0268-perf-jevents-Fix-event-code-for-events-referencing-s.patch b/patches/0268-perf-jevents-Fix-event-code-for-events-referencing-s.patch new file mode 100644 index 0000000..556c54f --- /dev/null +++ b/patches/0268-perf-jevents-Fix-event-code-for-events-referencing-s.patch @@ -0,0 +1,76 @@ +From b0124f451ccc06ed5130b04217b60a613dc05566 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 8 Oct 2020 23:19:28 +0800 +Subject: [PATCH 151/201] perf jevents: Fix event code for events referencing + std arch events + +mainline inclusion +from mainline-v5.10-rc1 +commit caf7f9685dd339d4fe7c3cbc0b5d7fabd3df784d +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=caf7f9685dd339d4fe7c3cbc0b5d7fabd3df784d + +---------------------------------------------------------------------- + +The event code for events referencing std arch events is incorrectly +evaluated in json_events(). + +The issue is that je.event is evaluated properly from try_fixup(), but +later NULLified from the real_event() call, as "event" may be NULL. + +Fix by setting "event" same je.event in try_fixup(). + +Also remove support for overwriting event code for events using std arch +events, as it is not used. + +Signed-off-by: John Garry +Reviewed-By: Kajol Jain +Acked-by: Jiri Olsa +Link: https://lore.kernel.org/r/1602170368-11892-1-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 4a1bc82e68bd..572b6d41d725 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -505,20 +505,15 @@ static char *real_event(const char *name, char *event) + } + + static int +-try_fixup(const char *fn, char *arch_std, unsigned long long eventcode, +- struct json_event *je) ++try_fixup(const char *fn, char *arch_std, struct json_event *je, char **event) + { + /* try to find matching event from arch standard values */ + struct event_struct *es; + + list_for_each_entry(es, &arch_std_events, list) { + if (!strcmp(arch_std, es->name)) { +- if (!eventcode && es->event) { +- /* allow EventCode to be overridden */ +- free(je->event); +- je->event = NULL; +- } + FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD); ++ *event = je->event; + return 0; + } + } +@@ -678,7 +673,7 @@ static int json_events(const char *fn, + * An arch standard event is referenced, so try to + * fixup any unassigned values. + */ +- err = try_fixup(fn, arch_std, eventcode, &je); ++ err = try_fixup(fn, arch_std, &je, &event); + if (err) + goto free_strings; + } +-- +2.27.0 + diff --git a/patches/0269-perf-jevents-Fix-getting-maximum-number-of-fds.patch b/patches/0269-perf-jevents-Fix-getting-maximum-number-of-fds.patch new file mode 100644 index 0000000..ce6015e --- /dev/null +++ b/patches/0269-perf-jevents-Fix-getting-maximum-number-of-fds.patch @@ -0,0 +1,52 @@ +From 1bdc66b453275d2095f488df92bb436408ddd8c8 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Tue, 25 May 2021 18:07:58 +0200 +Subject: [PATCH 152/201] perf jevents: Fix getting maximum number of fds + +mainline inclusion +from mainline-v5.13-rc4 +commit 75ea44e356b5de8c817f821c9dd68ae329e82add +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=75ea44e356b5de8c817f821c9dd68ae329e82add + +---------------------------------------------------------------------- + +On some hosts, rlim.rlim_max can be returned as RLIM_INFINITY. +By casting it to int, it is interpreted as -1, which will cause get_maxfds +to return 0, causing "Invalid argument" errors in nftw() calls. +Fix this by casting the second argument of min() to rlim_t instead. + +Fixes: 80eeb67fe577 ("perf jevents: Program to convert JSON file") +Signed-off-by: Felix Fietkau +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Sukadev Bhattiprolu +Link: http://lore.kernel.org/lkml/20210525160758.97829-1-nbd@nbd.name +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 572b6d41d725..d547dc5e6efa 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -894,7 +894,7 @@ static int get_maxfds(void) + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) +- return min((int)rlim.rlim_max / 2, 512); ++ return min(rlim.rlim_max / 2, (rlim_t)512); + + return 512; + } +-- +2.27.0 + diff --git a/patches/0270-perf-jevents-Fix-event-syntax-error-caused-by-ExtSel.patch b/patches/0270-perf-jevents-Fix-event-syntax-error-caused-by-ExtSel.patch new file mode 100644 index 0000000..e42bb0e --- /dev/null +++ b/patches/0270-perf-jevents-Fix-event-syntax-error-caused-by-ExtSel.patch @@ -0,0 +1,70 @@ +From 576ac10f0805c4dd6385a6acf53dd129e9052312 Mon Sep 17 00:00:00 2001 +From: Zhengjun Xing +Date: Wed, 25 May 2022 22:04:10 +0800 +Subject: [PATCH 153/201] perf jevents: Fix event syntax error caused by ExtSel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.19-rc1 +commit f4df0dbbe62ee8e4405a57b27ccd54393971c773 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f4df0dbbe62ee8e4405a57b27ccd54393971c773 + +---------------------------------------------------------------------- + +Content-Transfer-Encoding: 8bit + +In the origin code, when "ExtSel" is 1, the eventcode will change to +"eventcode |= 1 << 21”. For event “UNC_Q_RxL_CREDITS_CONSUMED_VN0.DRS", +its "ExtSel" is "1", its eventcode will change from 0x1E to 0x20001E, +but in fact the eventcode should <=0x1FF, so this will cause the parse +fail: + + # perf stat -e "UNC_Q_RxL_CREDITS_CONSUMED_VN0.DRS" -a sleep 0.1 + event syntax error: '.._RxL_CREDITS_CONSUMED_VN0.DRS' + \___ value too big for format, maximum is 511 + +On the perf kernel side, the kernel assumes the valid bits are continuous. +It will adjust the 0x100 (bit 8 for perf tool) to bit 21 in HW. + +DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21"); + +So the perf tool follows the kernel side and just set bit8 other than bit21. + +Fixes: fedb2b518239cbc0 ("perf jevents: Add support for parsing uncore json files") +Reviewed-by: Kan Liang +Signed-off-by: Xing Zhengjun +Acked-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20220525140410.1706851-1-zhengjun.xing@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index d547dc5e6efa..c84180b7fd3d 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -579,7 +579,7 @@ static int json_events(const char *fn, + } else if (json_streq(map, field, "ExtSel")) { + char *code = NULL; + addfield(map, &code, "", "", val); +- eventcode |= strtoul(code, NULL, 0) << 21; ++ eventcode |= strtoul(code, NULL, 0) << 8; + free(code); + } else if (json_streq(map, field, "EventName")) { + addfield(map, &je.name, "", "", val); +-- +2.27.0 + diff --git a/patches/0271-perf-jevents-Tidy-error-handling.patch b/patches/0271-perf-jevents-Tidy-error-handling.patch new file mode 100644 index 0000000..516dec7 --- /dev/null +++ b/patches/0271-perf-jevents-Tidy-error-handling.patch @@ -0,0 +1,168 @@ +From b3f4cadee6a1f296fe265bb64f3b5e18d5da043b Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 22 Oct 2020 19:02:26 +0800 +Subject: [PATCH 154/201] perf jevents: Tidy error handling + +mainline inclusion +from mainline-v5.11-rc1 +commit fa1b41a74d1136cbdd6960f36d7b9c7aa35c8139 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fa1b41a74d1136cbdd6960f36d7b9c7aa35c8139 + +---------------------------------------------------------------------- + +There is much duplication in the error handling for directory transvering +for prcessing JSONs. + +Factor out the common code to tidy a bit. + +Signed-off-by: John Garry +Reviewed-By: Kajol Jain +Link: https://lore.kernel.org/r/1603364547-197086-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 83 ++++++++++++++------------------- + 1 file changed, 35 insertions(+), 48 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index c84180b7fd3d..b988fa2fa270 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -1100,12 +1100,13 @@ static int process_one_file(const char *fpath, const struct stat *sb, + */ + int main(int argc, char *argv[]) + { +- int rc, ret = 0; ++ int rc, ret = 0, empty_map = 0; + int maxfds; + char ldirname[PATH_MAX]; + const char *arch; + const char *output_file; + const char *start_dirname; ++ char *err_string_ext = ""; + struct stat stbuf; + + prog = basename(argv[0]); +@@ -1133,7 +1134,8 @@ int main(int argc, char *argv[]) + /* If architecture does not have any event lists, bail out */ + if (stat(ldirname, &stbuf) < 0) { + pr_info("%s: Arch %s has no PMU event lists\n", prog, arch); +- goto empty_map; ++ empty_map = 1; ++ goto err_close_eventsfp; + } + + /* Include pmu-events.h first */ +@@ -1150,75 +1152,60 @@ int main(int argc, char *argv[]) + */ + + maxfds = get_maxfds(); +- mapfile = NULL; + rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0); +- if (rc && verbose) { +- pr_info("%s: Error preprocessing arch standard files %s\n", +- prog, ldirname); +- goto empty_map; +- } else if (rc < 0) { +- /* Make build fail */ +- fclose(eventsfp); +- free_arch_std_events(); +- return 1; +- } else if (rc) { +- goto empty_map; +- } ++ if (rc) ++ goto err_processing_std_arch_event_dir; + + rc = nftw(ldirname, process_one_file, maxfds, 0); +- if (rc && verbose) { +- pr_info("%s: Error walking file tree %s\n", prog, ldirname); +- goto empty_map; +- } else if (rc < 0) { +- /* Make build fail */ +- fclose(eventsfp); +- free_arch_std_events(); +- ret = 1; +- goto out_free_mapfile; +- } else if (rc) { +- goto empty_map; +- } ++ if (rc) ++ goto err_processing_dir; + + sprintf(ldirname, "%s/test", start_dirname); + + rc = nftw(ldirname, process_one_file, maxfds, 0); +- if (rc && verbose) { +- pr_info("%s: Error walking file tree %s rc=%d for test\n", +- prog, ldirname, rc); +- goto empty_map; +- } else if (rc < 0) { +- /* Make build fail */ +- free_arch_std_events(); +- ret = 1; +- goto out_free_mapfile; +- } else if (rc) { +- goto empty_map; +- } ++ if (rc) ++ goto err_processing_dir; + + if (close_table) + print_events_table_suffix(eventsfp); + + if (!mapfile) { + pr_info("%s: No CPU->JSON mapping?\n", prog); +- goto empty_map; ++ empty_map = 1; ++ goto err_close_eventsfp; + } + +- if (process_mapfile(eventsfp, mapfile)) { ++ rc = process_mapfile(eventsfp, mapfile); ++ fclose(eventsfp); ++ if (rc) { + pr_info("%s: Error processing mapfile %s\n", prog, mapfile); + /* Make build fail */ +- fclose(eventsfp); +- free_arch_std_events(); + ret = 1; ++ goto err_out; + } + ++ free_arch_std_events(); ++ free(mapfile); ++ return 0; + +- goto out_free_mapfile; +- +-empty_map: ++err_processing_std_arch_event_dir: ++ err_string_ext = " for std arch event"; ++err_processing_dir: ++ if (verbose) { ++ pr_info("%s: Error walking file tree %s%s\n", prog, ldirname, ++ err_string_ext); ++ empty_map = 1; ++ } else if (rc < 0) { ++ ret = 1; ++ } else { ++ empty_map = 1; ++ } ++err_close_eventsfp: + fclose(eventsfp); +- create_empty_mapping(output_file); ++ if (empty_map) ++ create_empty_mapping(output_file); ++err_out: + free_arch_std_events(); +-out_free_mapfile: + free(mapfile); + return ret; + } +-- +2.27.0 + diff --git a/patches/0272-perf-jevents-Add-support-for-an-extra-directory-leve.patch b/patches/0272-perf-jevents-Add-support-for-an-extra-directory-leve.patch new file mode 100644 index 0000000..d900f10 --- /dev/null +++ b/patches/0272-perf-jevents-Add-support-for-an-extra-directory-leve.patch @@ -0,0 +1,93 @@ +From f6d50e0a533366718c134f351042ca0cbc4dfbf4 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:07 +0800 +Subject: [PATCH 155/201] perf jevents: Add support for an extra directory + level + +mainline inclusion +from mainline-v5.11-rc1 +commit 4853f1caa43ea41a544c50a7cefc42e147aafeda +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4853f1caa43ea41a544c50a7cefc42e147aafeda + +---------------------------------------------------------------------- + +Currently only upto a level 2 directory is supported, in form +vendor/platform. + +Add support for a further level, to support vendor/platform +sub-directories in future, which will be vendor/platform/cpu and +vendor/platform/sys. + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index b988fa2fa270..152acb5d7a39 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -978,15 +978,20 @@ static int process_one_file(const char *fpath, const struct stat *sb, + int level = ftwbuf->level; + int err = 0; + +- if (level == 2 && is_dir) { ++ if (level >= 2 && is_dir) { ++ int count = 0; + /* + * For level 2 directory, bname will include parent name, + * like vendor/platform. So search back from platform dir + * to find this. ++ * Something similar for level 3 directory, but we're a PMU ++ * category folder, like vendor/platform/cpu. + */ + bname = (char *) fpath + ftwbuf->base - 2; + for (;;) { + if (*bname == '/') ++ count++; ++ if (count == level - 1) + break; + bname--; + } +@@ -999,13 +1004,13 @@ static int process_one_file(const char *fpath, const struct stat *sb, + level, sb->st_size, bname, fpath); + + /* base dir or too deep */ +- if (level == 0 || level > 3) ++ if (level == 0 || level > 4) + return 0; + + + /* model directory, reset topic */ + if ((level == 1 && is_dir && is_leaf_dir(fpath)) || +- (level == 2 && is_dir)) { ++ (level >= 2 && is_dir && is_leaf_dir(fpath))) { + if (close_table) + print_events_table_suffix(eventsfp); + +-- +2.27.0 + diff --git a/patches/0273-perf-jevents-Add-support-for-system-events-tables.patch b/patches/0273-perf-jevents-Add-support-for-system-events-tables.patch new file mode 100644 index 0000000..ea2a2d9 --- /dev/null +++ b/patches/0273-perf-jevents-Add-support-for-system-events-tables.patch @@ -0,0 +1,356 @@ +From 8704307b6512f90db89e90c62a0134988fdf89e1 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:08 +0800 +Subject: [PATCH 156/201] perf jevents: Add support for system events tables + +mainline inclusion +from mainline-v5.11-rc1 +commit 4689f56796f87abee190d8a959dd318e006c5b5a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4689f56796f87abee190d8a959dd318e006c5b5a + +---------------------------------------------------------------------- + +Process the JSONs to find support for "system" events, which are not +tied to a specific CPUID. + +A "COMPAT" property is now used to match against the namespace ID from +the kernel PMU driver. + +The generated pmu-events.c will now have 2 tables: + +a. CPU events, as before. +b. New pmu_sys_event_tables[] table, which will have events matched to + specific SoCs. + +It will look like this: + +struct pmu_event pme_hisilicon_hip09_sys[] = { +{ + .name = "cycles", + .compat = "0x00030736", + .event = "event=0", + .desc = "Clock cycles", + .topic = "smmu v3 pmcg", + .long_desc = "Clock cycles", +}, +{ + .name = "smmuv3_pmcg.l1_tlb", + .compat = "0x00030736", + .event = "event=0x8a", + .desc = "SMMUv3 PMCG l1_tlb. Unit: smmuv3_pmcg ", + .topic = "smmu v3 pmcg", + .long_desc = "SMMUv3 PMCG l1_tlb", + .pmu = "smmuv3_pmcg", +}, +... +}; + +struct pmu_event pme_arm_cortex_a53[] = { +{ + .name = "ext_mem_req", + .event = "event=0xc0", + .desc = "External memory request", + .topic = "memory", +}, +{ + .name = "ext_mem_req_nc", + .event = "event=0xc1", + .desc = "Non-cacheable external memory request", + .topic = "memory", +}, +... +}; + +struct pmu_event pme_hisilicon_hip09_cpu[] = { +{ + .name = "l2d_cache_refill_wr", + .event = "event=0x53", + .desc = "L2D cache refill, write", + .topic = "core imp def", + .long_desc = "Attributable Level 2 data cache refill, write", +}, +... +}; + +struct pmu_events_map pmu_events_map[] = { +{ + .cpuid = "0x00000000410fd030", + .version = "v1", + .type = "core", + .table = pme_arm_cortex_a53 +}, +{ + .cpuid = "0x00000000480fd010", + .version = "v1", + .type = "core", + .table = pme_hisilicon_hip09_cpu +}, + { + .table = 0 + }, +}; + +struct pmu_event pme_hisilicon_hip09_cpu[] = { +{ + .name = "uncore_hisi_l3c.rd_cpipe", + .event = "event=0", + .desc = "Total read accesses. Unit: hisi_sccl,l3c ", + .topic = "uncore l3c", + .long_desc = "Total read accesses", + .pmu = "hisi_sccl,l3c", +}, +{ + .name = "uncore_hisi_l3c.wr_cpipe", + .event = "event=0x1", + .desc = "Total write accesses. Unit: hisi_sccl,l3c ", + .topic = "uncore l3c", + .long_desc = "Total write accesses", + .pmu = "hisi_sccl,l3c", +}, +... +}; + +struct pmu_sys_events pmu_sys_event_tables[] = { +{ + .table = pme_hisilicon_hip09_sys, +}, +... +}; + +Committer notes: + +Added the fix for architectures without PMU events, provided by John +after I reported the build failing in such systems. + +Link: https://lore.kernel.org/lkml/650baaf2-36b6-a9e2-ff49-963ef864c1f3@huawei.com/ + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 86 +++++++++++++++++++++++++++++- + tools/perf/pmu-events/pmu-events.h | 6 +++ + 2 files changed, 91 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 152acb5d7a39..8d99dfacb3bc 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -55,6 +55,7 @@ char *prog; + + struct json_event { + char *name; ++ char *compat; + char *event; + char *desc; + char *long_desc; +@@ -82,6 +83,23 @@ enum aggr_mode_class convert(const char *aggr_mode) + + typedef int (*func)(void *data, struct json_event *je); + ++static LIST_HEAD(sys_event_tables); ++ ++struct sys_event_table { ++ struct list_head list; ++ char *soc_id; ++}; ++ ++static void free_sys_event_tables(void) ++{ ++ struct sys_event_table *et, *next; ++ ++ list_for_each_entry_safe(et, next, &sys_event_tables, list) { ++ free(et->soc_id); ++ free(et); ++ } ++} ++ + int eprintf(int level, int var, const char *fmt, ...) + { + +@@ -360,6 +378,8 @@ static int print_events_table_entry(void *data, struct json_event *je) + if (je->event) + fprintf(outfp, "\t.event = \"%s\",\n", je->event); + fprintf(outfp, "\t.desc = \"%s\",\n", je->desc); ++ if (je->compat) ++ fprintf(outfp, "\t.compat = \"%s\",\n", je->compat); + fprintf(outfp, "\t.topic = \"%s\",\n", topic); + if (je->long_desc && je->long_desc[0]) + fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc); +@@ -390,6 +410,7 @@ struct event_struct { + struct list_head list; + char *name; + char *event; ++ char *compat; + char *desc; + char *long_desc; + char *pmu; +@@ -583,6 +604,8 @@ static int json_events(const char *fn, + free(code); + } else if (json_streq(map, field, "EventName")) { + addfield(map, &je.name, "", "", val); ++ } else if (json_streq(map, field, "Compat")) { ++ addfield(map, &je.compat, "", "", val); + } else if (json_streq(map, field, "BriefDescription")) { + addfield(map, &je.desc, "", "", val); + fixdesc(je.desc); +@@ -683,6 +706,7 @@ static int json_events(const char *fn, + free(event); + free(je.desc); + free(je.name); ++ free(je.compat); + free(je.long_desc); + free(extra_desc); + free(je.pmu); +@@ -747,6 +771,15 @@ static char *file_name_to_table_name(char *fname) + return tblname; + } + ++static bool is_sys_dir(char *fname) ++{ ++ size_t len = strlen(fname), len2 = strlen("/sys"); ++ ++ if (len2 > len) ++ return false; ++ return !strcmp(fname+len-len2, "/sys"); ++} ++ + static void print_mapping_table_prefix(FILE *outfp) + { + fprintf(outfp, "struct pmu_events_map pmu_events_map[] = {\n"); +@@ -781,6 +814,33 @@ static void print_mapping_test_table(FILE *outfp) + fprintf(outfp, "},\n"); + } + ++static void print_system_event_mapping_table_prefix(FILE *outfp) ++{ ++ fprintf(outfp, "\nstruct pmu_sys_events pmu_sys_event_tables[] = {"); ++} ++ ++static void print_system_event_mapping_table_suffix(FILE *outfp) ++{ ++ fprintf(outfp, "\n\t{\n\t\t.table = 0\n\t},"); ++ fprintf(outfp, "\n};\n"); ++} ++ ++static int process_system_event_tables(FILE *outfp) ++{ ++ struct sys_event_table *sys_event_table; ++ ++ print_system_event_mapping_table_prefix(outfp); ++ ++ list_for_each_entry(sys_event_table, &sys_event_tables, list) { ++ fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t},", ++ sys_event_table->soc_id); ++ } ++ ++ print_system_event_mapping_table_suffix(outfp); ++ ++ return 0; ++} ++ + static int process_mapfile(FILE *outfp, char *fpath) + { + int n = 16384; +@@ -886,6 +946,8 @@ static void create_empty_mapping(const char *output_file) + fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n"); + print_mapping_table_prefix(outfp); + print_mapping_table_suffix(outfp); ++ print_system_event_mapping_table_prefix(outfp); ++ print_system_event_mapping_table_suffix(outfp); + fclose(outfp); + } + +@@ -1026,6 +1088,22 @@ static int process_one_file(const char *fpath, const struct stat *sb, + return -1; + } + ++ if (is_sys_dir(bname)) { ++ struct sys_event_table *sys_event_table; ++ ++ sys_event_table = malloc(sizeof(*sys_event_table)); ++ if (!sys_event_table) ++ return -1; ++ ++ sys_event_table->soc_id = strdup(tblname); ++ if (!sys_event_table->soc_id) { ++ free(sys_event_table); ++ return -1; ++ } ++ list_add_tail(&sys_event_table->list, ++ &sys_event_tables); ++ } ++ + print_events_table_prefix(eventsfp, tblname); + return 0; + } +@@ -1181,10 +1259,16 @@ int main(int argc, char *argv[]) + } + + rc = process_mapfile(eventsfp, mapfile); +- fclose(eventsfp); + if (rc) { + pr_info("%s: Error processing mapfile %s\n", prog, mapfile); + /* Make build fail */ ++ ret = 1; ++ goto err_close_eventsfp; ++ } ++ ++ rc = process_system_event_tables(eventsfp); ++ fclose(eventsfp); ++ if (rc) { + ret = 1; + goto err_out; + } +diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h +index fb712bb0f59e..70b9c37ed957 100644 +--- a/tools/perf/pmu-events/pmu-events.h ++++ b/tools/perf/pmu-events/pmu-events.h +@@ -12,6 +12,7 @@ enum aggr_mode_class { + */ + struct pmu_event { + const char *name; ++ const char *compat; + const char *event; + const char *desc; + const char *topic; +@@ -43,10 +44,15 @@ struct pmu_events_map { + struct pmu_event *table; + }; + ++struct pmu_sys_events { ++ struct pmu_event *table; ++}; ++ + /* + * Global table mapping each known CPU for the architecture to its + * table of PMU events. + */ + extern struct pmu_events_map pmu_events_map[]; ++extern struct pmu_sys_events pmu_sys_event_tables[]; + + #endif +-- +2.27.0 + diff --git a/patches/0274-perf-pmu-Add-pmu_id.patch b/patches/0274-perf-pmu-Add-pmu_id.patch new file mode 100644 index 0000000..5f47aa8 --- /dev/null +++ b/patches/0274-perf-pmu-Add-pmu_id.patch @@ -0,0 +1,105 @@ +From 5f55790d197eb2a55f645e5f30fc8f08e034ec28 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:09 +0800 +Subject: [PATCH 157/201] perf pmu: Add pmu_id() + +mainline inclusion +from mainline-v5.11-rc1 +commit 51d548471510843e56d9f427aa6473ca0981c4a4 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=51d548471510843e56d9f427aa6473ca0981c4a4 + +---------------------------------------------------------------------- + +Add a function to read the PMU id sysfs entry. This is only done for uncore +PMUs where this would possibly be relevant. + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/pmu.c +--- + tools/perf/util/pmu.c | 18 ++++++++++++++++++ + tools/perf/util/pmu.h | 1 + + 2 files changed, 19 insertions(+) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index b8594a6c0c23..8fdcf3b63a19 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -597,6 +597,7 @@ static struct cpu_map *__pmu_cpumask(const char *path) + * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) + * may have a "cpus" file. + */ ++#define SYS_TEMPLATE_ID "./bus/event_source/devices/%s/identifier" + #define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask" + #define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus" + +@@ -638,6 +639,21 @@ static bool pmu_is_uncore(const char *name) + return !!cpus; + } + ++static char *pmu_id(const char *name) ++{ ++ char path[PATH_MAX], *str; ++ size_t len; ++ ++ snprintf(path, PATH_MAX, SYS_TEMPLATE_ID, name); ++ ++ if (sysfs__read_str(path, &str, &len) < 0) ++ return NULL; ++ ++ str[len - 1] = 0; /* remove line feed */ ++ ++ return str; ++} ++ + /* + * PMU CORE devices have different name other than cpu in sysfs on some + * platforms. +@@ -885,6 +901,8 @@ static struct perf_pmu *pmu_lookup(const char *name) + pmu->name = strdup(name); + pmu->type = type; + pmu->is_uncore = pmu_is_uncore(name); ++ if (pmu->is_uncore) ++ pmu->id = pmu_id(name); + pmu_add_cpu_aliases(&aliases, pmu); + + INIT_LIST_HEAD(&pmu->format); +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index b440053bf4e7..cc055cb1c841 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -22,6 +22,7 @@ struct perf_event_attr; + + struct perf_pmu { + char *name; ++ char *id; + __u32 type; + bool selectable; + bool is_uncore; +-- +2.27.0 + diff --git a/patches/0275-perf-pmu-Add-pmu_add_sys_aliases.patch b/patches/0275-perf-pmu-Add-pmu_add_sys_aliases.patch new file mode 100644 index 0000000..909a5a8 --- /dev/null +++ b/patches/0275-perf-pmu-Add-pmu_add_sys_aliases.patch @@ -0,0 +1,163 @@ +From 60a568338a860966e4dfb7d2cad4f5a246dd09a8 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:10 +0800 +Subject: [PATCH 158/201] perf pmu: Add pmu_add_sys_aliases() + +mainline inclusion +from mainline-v5.11-rc1 +commit 4513c719c6f1ccf0c362c8dcef1f9b476f8f5c9c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4513c719c6f1ccf0c362c8dcef1f9b476f8f5c9c + +---------------------------------------------------------------------- + +Add pmu_add_sys_aliases() to add system PMU events aliases. + +For adding system PMU events, iterate through all the events for all SoC +event tables in pmu_sys_event_tables[]. + +Matches must satisfy both: +- PMU identifier matches event "compat" value +- event "Unit" member must match, same as uncore event aliases matched by + CPUID + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 78 +++++++++++++++++++++++++++++++++++++++++++ + tools/perf/util/pmu.h | 2 ++ + 2 files changed, 80 insertions(+) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 8fdcf3b63a19..c924e68a368f 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -863,6 +863,83 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) + pmu_add_cpu_aliases_map(head, pmu, map); + } + ++void pmu_for_each_sys_event(pmu_sys_event_iter_fn fn, void *data) ++{ ++ int i = 0; ++ ++ while (1) { ++ struct pmu_sys_events *event_table; ++ int j = 0; ++ ++ event_table = &pmu_sys_event_tables[i++]; ++ ++ if (!event_table->table) ++ break; ++ ++ while (1) { ++ struct pmu_event *pe = &event_table->table[j++]; ++ int ret; ++ ++ if (!pe->name && !pe->metric_group && !pe->metric_name) ++ break; ++ ++ ret = fn(pe, data); ++ if (ret) ++ break; ++ } ++ } ++} ++ ++struct pmu_sys_event_iter_data { ++ struct list_head *head; ++ struct perf_pmu *pmu; ++}; ++ ++static int pmu_add_sys_aliases_iter_fn(struct pmu_event *pe, void *data) ++{ ++ struct pmu_sys_event_iter_data *idata = data; ++ struct perf_pmu *pmu = idata->pmu; ++ ++ if (!pe->name) { ++ if (pe->metric_group || pe->metric_name) ++ return 0; ++ return -EINVAL; ++ } ++ ++ if (!pe->compat || !pe->pmu) ++ return 0; ++ ++ if (!strcmp(pmu->id, pe->compat) && ++ pmu_uncore_alias_match(pe->pmu, pmu->name)) { ++ __perf_pmu__new_alias(idata->head, NULL, ++ (char *)pe->name, ++ (char *)pe->desc, ++ (char *)pe->event, ++ (char *)pe->long_desc, ++ (char *)pe->topic, ++ (char *)pe->unit, ++ (char *)pe->perpkg, ++ (char *)pe->metric_expr, ++ (char *)pe->metric_name, ++ (char *)pe->deprecated); ++ } ++ ++ return 0; ++} ++ ++static void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu) ++{ ++ struct pmu_sys_event_iter_data idata = { ++ .head = head, ++ .pmu = pmu, ++ }; ++ ++ if (!pmu->id) ++ return; ++ ++ pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); ++} ++ + struct perf_event_attr * __weak + perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) + { +@@ -904,6 +981,7 @@ static struct perf_pmu *pmu_lookup(const char *name) + if (pmu->is_uncore) + pmu->id = pmu_id(name); + pmu_add_cpu_aliases(&aliases, pmu); ++ pmu_add_sys_aliases(&aliases, pmu); + + INIT_LIST_HEAD(&pmu->format); + INIT_LIST_HEAD(&pmu->aliases); +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index cc055cb1c841..2da3d2016245 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -107,6 +107,8 @@ struct pmu_events_map *pmu_events_map__find(void); + bool pmu_uncore_alias_match(const char *pmu_name, const char *name); + void perf_pmu_free_alias(struct perf_pmu_alias *alias); + ++typedef int (*pmu_sys_event_iter_fn)(struct pmu_event *pe, void *data); ++void pmu_for_each_sys_event(pmu_sys_event_iter_fn fn, void *data); + int perf_pmu__convert_scale(const char *scale, char **end, double *sval); + + #endif /* __PMU_H */ +-- +2.27.0 + diff --git a/patches/0276-perf-evlist-Change-evlist__splice_list_tail-ordering.patch b/patches/0276-perf-evlist-Change-evlist__splice_list_tail-ordering.patch new file mode 100644 index 0000000..d6f6baf --- /dev/null +++ b/patches/0276-perf-evlist-Change-evlist__splice_list_tail-ordering.patch @@ -0,0 +1,85 @@ +From 3f6276d1f80d0ccef037e1e684f54d6b4db8c4c3 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:11 +0800 +Subject: [PATCH 159/201] perf evlist: Change evlist__splice_list_tail() + ordering + +mainline inclusion +from mainline-v5.11-rc1 +commit 6d2783fe365fa5f571cf1416b5f5b1e352447a0e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6d2783fe365fa5f571cf1416b5f5b1e352447a0e + +---------------------------------------------------------------------- + +Function find_evsel_group() expects events to be ordered such that they +are grouped after their leader. + +Modify evlist__splice_list_tail() to guarantee this (ordering). + +[Should prob also change the function name] + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-6-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/evlist.c +--- + tools/perf/util/evlist.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c +index bd791f9af49b..39b41d9d2a24 100644 +--- a/tools/perf/util/evlist.c ++++ b/tools/perf/util/evlist.c +@@ -200,11 +200,22 @@ void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel) + void perf_evlist__splice_list_tail(struct perf_evlist *evlist, + struct list_head *list) + { +- struct perf_evsel *evsel, *temp; ++ while (!list_empty(list)) { ++ struct perf_evsel *evsel, *temp, *leader = NULL; + +- __evlist__for_each_entry_safe(list, temp, evsel) { +- list_del_init(&evsel->node); +- perf_evlist__add(evlist, evsel); ++ __evlist__for_each_entry_safe(list, temp, evsel) { ++ list_del_init(&evsel->node); ++ perf_evlist__add(evlist, evsel); ++ leader = evsel; ++ break; ++ } ++ ++ __evlist__for_each_entry_safe(list, temp, evsel) { ++ if (evsel->leader == leader) { ++ list_del_init(&evsel->node); ++ perf_evlist__add(evlist, evsel); ++ } ++ } + } + } + +-- +2.27.0 + diff --git a/patches/0277-perf-metricgroup-Fix-metrics-using-aliases-covering-.patch b/patches/0277-perf-metricgroup-Fix-metrics-using-aliases-covering-.patch new file mode 100644 index 0000000..8c44ea0 --- /dev/null +++ b/patches/0277-perf-metricgroup-Fix-metrics-using-aliases-covering-.patch @@ -0,0 +1,106 @@ +From ba26335b1bb03a3a4ff5365c01f3427777c8ed94 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:12 +0800 +Subject: [PATCH 160/201] perf metricgroup: Fix metrics using aliases covering + multiple PMUs + +mainline inclusion +from mainline-v5.11-rc1 +commit c2337d67199a1ea1c75083da5d376aced1ab2c40 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c2337d67199a1ea1c75083da5d376aced1ab2c40 + +---------------------------------------------------------------------- + +Support for metric expressions using aliases which cover multiple PMUs +is broken. Consider the following test metric expression: + + "MetricExpr": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE * UNC_CBO_XSNP_RESPONSE.MISS_EVICTION" + +When used on my broadwell, "perf stat" gives: + + unc_cbo_xsnp_response.miss_eviction -> uncore_cbox_1/umask=0x81,event=0x22/ + unc_cbo_xsnp_response.miss_eviction -> uncore_cbox_0/umask=0x81,event=0x22/ + unc_cbo_xsnp_response.miss_xcore -> uncore_cbox_1/umask=0x41,event=0x22/ + unc_cbo_xsnp_response.miss_xcore -> uncore_cbox_0/umask=0x41,event=0x22/ + Control descriptor is not initialized + unc_cbo_xsnp_response.miss_eviction: 3645925 1000850523 1000850523 + unc_cbo_xsnp_response.miss_xcore: 106850 1000850523 1000850523 + + Performance counter stats for 'system wide': + + 3,645,925 unc_cbo_xsnp_response.miss_eviction # 389567086250.00 test_metric_inc + 106,850 unc_cbo_xsnp_response.miss_xcore + + 1.000883096 seconds time elapsed + +Notice that only the results from one PMU are included. Fix the logic of +find_evsel_group() to enable events which apply to multiple PMUs, by +checking if the event pmu_name matches that of the metric event. + +With that, "perf stat" now gives: + + unc_cbo_xsnp_response.miss_eviction -> uncore_cbox_1/umask=0x81,event=0x22/ + unc_cbo_xsnp_response.miss_eviction -> uncore_cbox_0/umask=0x81,event=0x22/ + unc_cbo_xsnp_response.miss_xcore -> uncore_cbox_1/umask=0x41,event=0x22/ + unc_cbo_xsnp_response.miss_xcore -> uncore_cbox_0/umask=0x41,event=0x22/ + Control descriptor is not initialized + unc_cbo_xsnp_response.miss_eviction: 4237983 1000904100 1000904100 + unc_cbo_xsnp_response.miss_xcore: 218643 1000904100 1000904100 + unc_cbo_xsnp_response.miss_eviction: 4254148 1000902629 1000902629 + unc_cbo_xsnp_response.miss_xcore: 213352 1000902629 1000902629 + + Performance counter stats for 'system wide': + + 4,237,983 unc_cbo_xsnp_response.miss_eviction # 3668558131345.00 test_metric_inc + 218,643 unc_cbo_xsnp_response.miss_xcore + 4,254,148 unc_cbo_xsnp_response.miss_eviction + 213,352 unc_cbo_xsnp_response.miss_xcore + + 1.000938151 seconds time elapsed + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-7-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index ac27441a0e28..df85d04ee869 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -284,7 +284,9 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + * when then group is left. + */ + if (!has_constraint && +- ev->leader != metric_events[i]->leader) ++ ev->leader != metric_events[i]->leader && ++ !strcmp(ev->leader->pmu_name, ++ metric_events[i]->leader->pmu_name)) + break; + if (!strcmp(metric_events[i]->name, ev->name)) { + set_bit(ev->idx, evlist_used); +-- +2.27.0 + diff --git a/patches/0278-perf-metricgroup-Split-up-metricgroup__print.patch b/patches/0278-perf-metricgroup-Split-up-metricgroup__print.patch new file mode 100644 index 0000000..b29cb40 --- /dev/null +++ b/patches/0278-perf-metricgroup-Split-up-metricgroup__print.patch @@ -0,0 +1,202 @@ +From f1f6bf891ff3fde37a66b88f3e76da73e0bf9152 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:13 +0800 +Subject: [PATCH 161/201] perf metricgroup: Split up metricgroup__print() + +mainline inclusion +from mainline-v5.11-rc1 +commit f6fe1e48ae185d028dfcabecb7d79036e2d89d27 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f6fe1e48ae185d028dfcabecb7d79036e2d89d27 + +---------------------------------------------------------------------- + +To aid supporting system event metric groups, break up the function +metricgroup__print() into a part which iterates metrics and a part which +actually "prints" the metric. + +No functional change intended. + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-8-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 126 +++++++++++++++++++--------------- + 1 file changed, 71 insertions(+), 55 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index df85d04ee869..3ebd9190a87b 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -498,6 +498,73 @@ static void metricgroup__print_strlist(struct strlist *metrics, bool raw) + putchar('\n'); + } + ++static int metricgroup__print_pmu_event(struct pmu_event *pe, ++ bool metricgroups, char *filter, ++ bool raw, bool details, ++ struct rblist *groups, ++ struct strlist *metriclist) ++{ ++ const char *g; ++ char *omg, *mg; ++ ++ g = pe->metric_group; ++ if (!g && pe->metric_name) { ++ if (pe->name) ++ return 0; ++ g = "No_group"; ++ } ++ ++ if (!g) ++ return 0; ++ ++ mg = strdup(g); ++ ++ if (!mg) ++ return -ENOMEM; ++ omg = mg; ++ while ((g = strsep(&mg, ";")) != NULL) { ++ struct mep *me; ++ char *s; ++ ++ if (*g == 0) ++ g = "No_group"; ++ while (isspace(*g)) ++ g++; ++ if (filter && !strstr(g, filter)) ++ continue; ++ if (raw) ++ s = (char *)pe->metric_name; ++ else { ++ if (asprintf(&s, "%s\n%*s%s]", ++ pe->metric_name, 8, "[", pe->desc) < 0) ++ return -1; ++ if (details) { ++ if (asprintf(&s, "%s\n%*s%s]", ++ s, 8, "[", pe->metric_expr) < 0) ++ return -1; ++ } ++ } ++ ++ if (!s) ++ continue; ++ ++ if (!metricgroups) { ++ strlist__add(metriclist, s); ++ } else { ++ me = mep_lookup(groups, g); ++ if (!me) ++ continue; ++ strlist__add(me->metrics, s); ++ } ++ ++ if (!raw) ++ free(s); ++ } ++ free(omg); ++ ++ return 0; ++} ++ + void metricgroup__print(bool metrics, bool metricgroups, char *filter, + bool raw, bool details) + { +@@ -522,67 +589,16 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + groups.node_cmp = mep_cmp; + groups.node_delete = mep_delete; + for (i = 0; ; i++) { +- const char *g; + pe = &map->table[i]; + + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; +- g = pe->metric_group; +- if (!g && pe->metric_name) { +- if (pe->name) +- continue; +- g = "No_group"; +- } +- if (g) { +- char *omg; +- char *mg = strdup(g); +- +- if (!mg) +- return; +- omg = mg; +- while ((g = strsep(&mg, ";")) != NULL) { +- struct mep *me; +- char *s; +- +- if (*g == 0) +- g = "No_group"; +- while (isspace(*g)) +- g++; +- if (filter && !strstr(g, filter)) +- continue; +- if (raw) +- s = (char *)pe->metric_name; +- else { +- if (asprintf(&s, "%s\n%*s%s]", +- pe->metric_name, 8, "[", pe->desc) < 0) +- return; +- +- if (details) { +- if (asprintf(&s, "%s\n%*s%s]", +- s, 8, "[", pe->metric_expr) < 0) +- return; +- } +- } +- +- if (!s) +- continue; +- +- if (!metricgroups) { +- strlist__add(metriclist, s); +- } else { +- me = mep_lookup(&groups, g); +- if (!me) +- continue; +- strlist__add(me->metrics, s); +- } +- +- if (!raw) +- free(s); +- } +- free(omg); +- } ++ if (metricgroup__print_pmu_event(pe, metricgroups, filter, ++ raw, details, &groups, ++ metriclist) < 0) ++ return; + } + + if (!filter || !rblist__empty(&groups)) { +-- +2.27.0 + diff --git a/patches/0279-perf-metricgroup-Support-printing-metric-groups-for-.patch b/patches/0279-perf-metricgroup-Support-printing-metric-groups-for-.patch new file mode 100644 index 0000000..fbc7d91 --- /dev/null +++ b/patches/0279-perf-metricgroup-Support-printing-metric-groups-for-.patch @@ -0,0 +1,146 @@ +From d9d8d8a8618f7da18025f35c10de8f8b16f4ac63 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:14 +0800 +Subject: [PATCH 162/201] perf metricgroup: Support printing metric groups for + system PMUs + +mainline inclusion +from mainline-v5.11-rc1 +commit a36fadb17c27b4b5360db69acc80f5f4ad8dde7e +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a36fadb17c27b4b5360db69acc80f5f4ad8dde7e + +---------------------------------------------------------------------- + +Currently printing metricgroups for core- or uncore-based events matched +by CPUID is supported. + +Extend this for system events. + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-9-git-send-email-john.garry@huawei.com +[ Reorder 'struct metricgroup_print_sys_idata' field to avoid alignment holes ] +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 64 ++++++++++++++++++++++++++++++++--- + 1 file changed, 60 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 3ebd9190a87b..db5224115fe5 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -565,6 +565,49 @@ static int metricgroup__print_pmu_event(struct pmu_event *pe, + return 0; + } + ++struct metricgroup_print_sys_idata { ++ struct strlist *metriclist; ++ char *filter; ++ struct rblist *groups; ++ bool metricgroups; ++ bool raw; ++ bool details; ++}; ++ ++typedef int (*metricgroup_sys_event_iter_fn)(struct pmu_event *pe, void *); ++ ++struct metricgroup_iter_data { ++ metricgroup_sys_event_iter_fn fn; ++ void *data; ++}; ++ ++static int metricgroup__sys_event_iter(struct pmu_event *pe, void *data) ++{ ++ struct metricgroup_iter_data *d = data; ++ struct perf_pmu *pmu = NULL; ++ ++ if (!pe->metric_expr || !pe->compat) ++ return 0; ++ ++ while ((pmu = perf_pmu__scan(pmu))) { ++ ++ if (!pmu->id || strcmp(pmu->id, pe->compat)) ++ continue; ++ ++ return d->fn(pe, d->data); ++ } ++ ++ return 0; ++} ++ ++static int metricgroup__print_sys_event_iter(struct pmu_event *pe, void *data) ++{ ++ struct metricgroup_print_sys_idata *d = data; ++ ++ return metricgroup__print_pmu_event(pe, d->metricgroups, d->filter, d->raw, ++ d->details, d->groups, d->metriclist); ++} ++ + void metricgroup__print(bool metrics, bool metricgroups, char *filter, + bool raw, bool details) + { +@@ -575,9 +618,6 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + struct rb_node *node, *next; + struct strlist *metriclist = NULL; + +- if (!map) +- return; +- + if (!metricgroups) { + metriclist = strlist__new(NULL, NULL); + if (!metriclist) +@@ -588,7 +628,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + groups.node_new = mep_new; + groups.node_cmp = mep_cmp; + groups.node_delete = mep_delete; +- for (i = 0; ; i++) { ++ for (i = 0; map; i++) { + pe = &map->table[i]; + + if (!pe->name && !pe->metric_group && !pe->metric_name) +@@ -601,6 +641,22 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, + return; + } + ++ { ++ struct metricgroup_iter_data data = { ++ .fn = metricgroup__print_sys_event_iter, ++ .data = (void *) &(struct metricgroup_print_sys_idata){ ++ .metriclist = metriclist, ++ .metricgroups = metricgroups, ++ .filter = filter, ++ .raw = raw, ++ .details = details, ++ .groups = &groups, ++ }, ++ }; ++ ++ pmu_for_each_sys_event(metricgroup__sys_event_iter, &data); ++ } ++ + if (!filter || !rblist__empty(&groups)) { + if (metricgroups && !raw) + printf("\nMetric Groups:\n\n"); +-- +2.27.0 + diff --git a/patches/0280-perf-metricgroup-Support-adding-metrics-for-system-P.patch b/patches/0280-perf-metricgroup-Support-adding-metrics-for-system-P.patch new file mode 100644 index 0000000..d98de37 --- /dev/null +++ b/patches/0280-perf-metricgroup-Support-adding-metrics-for-system-P.patch @@ -0,0 +1,162 @@ +From 3751843f58692cb837d3e3ace46c5929c7f1c0bd Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 4 Dec 2020 19:10:15 +0800 +Subject: [PATCH 163/201] perf metricgroup: Support adding metrics for system + PMUs + +mainline inclusion +from mainline-v5.11-rc1 +commit be335ec28efa89d6bff8f4c6ce8daba88acf2b1a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=be335ec28efa89d6bff8f4c6ce8daba88acf2b1a + +---------------------------------------------------------------------- + +Currently adding metrics for core- or uncore-based events matched by CPUID +is supported. + +Extend this for system events. + +Signed-off-by: John Garry +Acked-by: Kajol Jain +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Joakim Zhang +Cc: Kan Liang +Cc: Kim Phillips +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/1607080216-36968-10-git-send-email-john.garry@huawei.com +[ Reorder 'struct metricgroup_add_iter_data' field to avoid alignment holes ] +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 66 +++++++++++++++++++++++++++++++---- + 1 file changed, 60 insertions(+), 6 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index db5224115fe5..2eaaa96d009a 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -420,6 +420,12 @@ static bool match_metric(const char *n, const char *list) + return false; + } + ++static bool match_pe_metric(struct pmu_event *pe, const char *metric) ++{ ++ return match_metric(pe->metric_group, metric) || ++ match_metric(pe->metric_name, metric); ++} ++ + struct mep { + struct rb_node nd; + const char *name; +@@ -763,6 +769,16 @@ int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused) + return 1; + } + ++struct metricgroup_add_iter_data { ++ struct list_head *metric_list; ++ const char *metric; ++ struct metric **m; ++ struct expr_ids *ids; ++ int *ret; ++ bool *has_match; ++ bool metric_no_group; ++}; ++ + static int __add_metric(struct list_head *metric_list, + struct pmu_event *pe, + bool metric_no_group, +@@ -872,10 +888,11 @@ static int __add_metric(struct list_head *metric_list, + return 0; + } + +-#define map_for_each_event(__pe, __idx, __map) \ +- for (__idx = 0, __pe = &__map->table[__idx]; \ +- __pe->name || __pe->metric_group || __pe->metric_name; \ +- __pe = &__map->table[++__idx]) ++#define map_for_each_event(__pe, __idx, __map) \ ++ if (__map) \ ++ for (__idx = 0, __pe = &__map->table[__idx]; \ ++ __pe->name || __pe->metric_group || __pe->metric_name; \ ++ __pe = &__map->table[++__idx]) + + #define map_for_each_metric(__pe, __idx, __map, __metric) \ + map_for_each_event(__pe, __idx, __map) \ +@@ -1044,6 +1061,29 @@ static int add_metric(struct list_head *metric_list, + return ret; + } + ++static int metricgroup__add_metric_sys_event_iter(struct pmu_event *pe, ++ void *data) ++{ ++ struct metricgroup_add_iter_data *d = data; ++ int ret; ++ ++ if (!match_pe_metric(pe, d->metric)) ++ return 0; ++ ++ ret = add_metric(d->metric_list, pe, d->metric_no_group, d->m, NULL, d->ids); ++ if (ret) ++ return ret; ++ ++ ret = resolve_metric(d->metric_no_group, ++ d->metric_list, NULL, d->ids); ++ if (ret) ++ return ret; ++ ++ *(d->has_match) = true; ++ ++ return *d->ret; ++} ++ + static int metricgroup__add_metric(const char *metric, bool metric_no_group, + struct strbuf *events, + struct list_head *metric_list, +@@ -1074,6 +1114,22 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + goto out; + } + ++ { ++ struct metricgroup_iter_data data = { ++ .fn = metricgroup__add_metric_sys_event_iter, ++ .data = (void *) &(struct metricgroup_add_iter_data) { ++ .metric_list = &list, ++ .metric = metric, ++ .metric_no_group = metric_no_group, ++ .m = &m, ++ .ids = &ids, ++ .has_match = &has_match, ++ .ret = &ret, ++ }, ++ }; ++ ++ pmu_for_each_sys_event(metricgroup__sys_event_iter, &data); ++ } + /* End of pmu events. */ + if (!has_match) { + ret = -EINVAL; +@@ -1200,8 +1256,6 @@ int metricgroup__parse_groups(const struct option *opt, + struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; + struct pmu_events_map *map = pmu_events_map__find(); + +- if (!map) +- return 0; + + return parse_groups(perf_evlist, str, metric_no_group, + metric_no_merge, NULL, metric_events, map); +-- +2.27.0 + diff --git a/patches/0281-perf-jevents-Add-test-for-arch-std-events.patch b/patches/0281-perf-jevents-Add-test-for-arch-std-events.patch new file mode 100644 index 0000000..a38dec1 --- /dev/null +++ b/patches/0281-perf-jevents-Add-test-for-arch-std-events.patch @@ -0,0 +1,138 @@ +From bb6fe321bab3caea3f1f3acc51cec9f15b37ca98 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 22 Oct 2020 19:02:27 +0800 +Subject: [PATCH 164/201] perf jevents: Add test for arch std events + +mainline inclusion +from mainline-v5.11-rc1 +commit 644bf4b0f7acde641d3db200b4db66977e96c3bd +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=644bf4b0f7acde641d3db200b4db66977e96c3bd + +---------------------------------------------------------------------- + +Recently there was an undetected breakage for std arch event support. + +Add support in "PMU events" testcase to detect such breakages. + +For this, the "test" arch needs has support added to process std arch +events. And a test event is added for the test, ifself. + +Also add a few code comments to help understand the code a bit better. + +Committer testing: + +Before: + + # perf test -vv pmu |& grep l3_cache_rd + # + +After: + + # perf test -vv pmu |& grep l3_cache_rd + testing event table l3_cache_rd: pass + testing aliases PMU cpu: matched event l3_cache_rd + # + +Signed-off-by: John Garry +Reviewed-By: Kajol Jain +Tested-by: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/r/1603364547-197086-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../perf/pmu-events/arch/test/arch-std-events.json | 8 ++++++++ + .../perf/pmu-events/arch/test/test_cpu/cache.json | 5 +++++ + tools/perf/pmu-events/jevents.c | 4 ++++ + tools/perf/tests/pmu-events.c | 14 ++++++++++++++ + 4 files changed, 31 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/test/arch-std-events.json + create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/cache.json + +diff --git a/tools/perf/pmu-events/arch/test/arch-std-events.json b/tools/perf/pmu-events/arch/test/arch-std-events.json +new file mode 100644 +index 000000000000..43f6f729d6ae +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/arch-std-events.json +@@ -0,0 +1,8 @@ ++[ ++ { ++ "PublicDescription": "Attributable Level 3 cache access, read", ++ "EventCode": "0x40", ++ "EventName": "L3_CACHE_RD", ++ "BriefDescription": "L3 cache access, read" ++ } ++] +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/cache.json b/tools/perf/pmu-events/arch/test/test_cpu/cache.json +new file mode 100644 +index 000000000000..036d0efdb2bb +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/test_cpu/cache.json +@@ -0,0 +1,5 @@ ++[ ++ { ++ "ArchStdEvent": "L3_CACHE_RD" ++ } ++] +\ No newline at end of file +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 8d99dfacb3bc..776a0c660050 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -1245,6 +1245,10 @@ int main(int argc, char *argv[]) + + sprintf(ldirname, "%s/test", start_dirname); + ++ rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0); ++ if (rc) ++ goto err_processing_std_arch_event_dir; ++ + rc = nftw(ldirname, process_one_file, maxfds, 0); + if (rc) + goto err_processing_dir; +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index bc7d75f24d59..14c927166935 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -15,8 +15,10 @@ + #include "metricgroup.h" + + struct perf_pmu_test_event { ++ /* used for matching against events from generated pmu-events.c */ + struct pmu_event event; + ++ /* used for matching against event aliases */ + /* extra events for aliases */ + const char *alias_str; + +@@ -79,6 +81,17 @@ static struct perf_pmu_test_event test_cpu_events[] = { + .alias_str = "umask=0,(null)=0x30d40,event=0x3a", + .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", + }, ++ { ++ .event = { ++ .name = "l3_cache_rd", ++ .event = "event=0x40", ++ .desc = "L3 cache access, read", ++ .long_desc = "Attributable Level 3 cache access, read", ++ .topic = "cache", ++ }, ++ .alias_str = "event=0x40", ++ .alias_long_desc = "Attributable Level 3 cache access, read", ++ }, + { /* sentinel */ + .event = { + .name = NULL, +@@ -358,6 +371,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + } + + ++/* Test that aliases generated are as expected */ + static int test_aliases(void) + { + struct perf_pmu *pmu = NULL; +-- +2.27.0 + diff --git a/patches/0282-perf-tools-Fix-pattern-matching-for-same-substring-i.patch b/patches/0282-perf-tools-Fix-pattern-matching-for-same-substring-i.patch new file mode 100644 index 0000000..fce8a13 --- /dev/null +++ b/patches/0282-perf-tools-Fix-pattern-matching-for-same-substring-i.patch @@ -0,0 +1,168 @@ +From 47526f62bdbb2725486d3cefc73222bc243dda4f Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Thu, 1 Jul 2021 14:42:53 +0800 +Subject: [PATCH 165/201] perf tools: Fix pattern matching for same substring + in different PMU type + +mainline inclusion +from mainline-v5.14-rc1 +commit c47a5599eda324bacdacd125227a0925d6c50fbe +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c47a5599eda324bacdacd125227a0925d6c50fbe + +---------------------------------------------------------------------- + +Some different PMU types may have the same substring. For example, on +Icelake server we have PMU types "uncore_imc" and +"uncore_imc_free_running". Both PMU types have the substring +"uncore_imc". But the parser wrongly thinks they are the same PMU type. + +We enable an imc event, +perf stat -e uncore_imc/event=0xe3/ -a -- sleep 1 + +Perf actually expands the event to: + + uncore_imc_0/event=0xe3/ + uncore_imc_1/event=0xe3/ + uncore_imc_2/event=0xe3/ + uncore_imc_3/event=0xe3/ + uncore_imc_4/event=0xe3/ + uncore_imc_5/event=0xe3/ + uncore_imc_6/event=0xe3/ + uncore_imc_7/event=0xe3/ + uncore_imc_free_running_0/event=0xe3/ + uncore_imc_free_running_1/event=0xe3/ + uncore_imc_free_running_3/event=0xe3/ + uncore_imc_free_running_4/event=0xe3/ + +That's because the "uncore_imc_free_running" matches the +pattern "uncore_imc*". + +Now we check that the last characters of PMU name is '_'. + +For example, for pattern "uncore_imc*", "uncore_imc_0" is parsed ok, but +"uncore_imc_free_running_0" fails. + +Fixes: b2b9d3a3f0211c5d ("perf pmu: Support wildcards on pmu name in dynamic pmu events") +Signed-off-by: Jin Yao +Reviewed-by: Kan Liang +Acked-by: Jiri Olsa +Cc: Agustin Vega-Frias +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/20210701064253.1175-1-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/parse-events.y + tools/perf/util/pmu.c + tools/perf/util/pmu.h +--- + tools/perf/util/parse-events.y | 2 +- + tools/perf/util/pmu.c | 36 +++++++++++++++++++++++++++++++++- + tools/perf/util/pmu.h | 2 ++ + 3 files changed, 38 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y +index f03da974770c..f870a209f931 100644 +--- a/tools/perf/util/parse-events.y ++++ b/tools/perf/util/parse-events.y +@@ -261,7 +261,7 @@ PE_NAME opt_pmu_config + if (!strncmp(name, "uncore_", 7) && + strncmp($1, "uncore_", 7)) + name += 7; +- if (!fnmatch(pattern, name, 0)) { ++ if (!perf_pmu__match(pattern, name, $1)) { + if (parse_events_copy_term_list(orig_terms, &terms)) { + free(pattern); + YYABORT; +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index c924e68a368f..a31ce1613161 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + #include + #include ++#include + #include + #include + #include +@@ -14,6 +15,7 @@ + #include + #include + #include "util.h" ++#include + #include "pmu.h" + #include "parse-events.h" + #include "cpumap.h" +@@ -768,6 +770,27 @@ struct pmu_events_map *__weak pmu_events_map__find(void) + return perf_pmu__find_map(NULL); + } + ++static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) ++{ ++ char *p; ++ ++ if (strncmp(pmu_name, tok, strlen(tok))) ++ return false; ++ ++ p = pmu_name + strlen(tok); ++ if (*p == 0) ++ return true; ++ ++ if (*p != '_') ++ return false; ++ ++ ++p; ++ if (*p == 0 || !isdigit(*p)) ++ return false; ++ ++ return true; ++} ++ + bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + { + char *tmp = NULL, *tok, *str; +@@ -796,7 +819,7 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + */ + for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) { + name = strstr(name, tok); +- if (!name) { ++ if (!name || !perf_pmu__valid_suffix((char *)name, tok)) { + res = false; + goto out; + } +@@ -1716,3 +1739,14 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, + va_end(args); + return ret; + } ++ ++int perf_pmu__match(char *pattern, char *name, char *tok) ++{ ++ if (fnmatch(pattern, name, 0)) ++ return -1; ++ ++ if (tok && !perf_pmu__valid_suffix(name, tok)) ++ return -1; ++ ++ return 0; ++} +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 2da3d2016245..118a2871e717 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -111,4 +111,6 @@ typedef int (*pmu_sys_event_iter_fn)(struct pmu_event *pe, void *data); + void pmu_for_each_sys_event(pmu_sys_event_iter_fn fn, void *data); + int perf_pmu__convert_scale(const char *scale, char **end, double *sval); + ++int perf_pmu__match(char *pattern, char *name, char *tok); ++ + #endif /* __PMU_H */ +-- +2.27.0 + diff --git a/patches/0283-perf-pmu-Fix-alias-matching.patch b/patches/0283-perf-pmu-Fix-alias-matching.patch new file mode 100644 index 0000000..beba100 --- /dev/null +++ b/patches/0283-perf-pmu-Fix-alias-matching.patch @@ -0,0 +1,119 @@ +From 187616c6ef70366f6d688810d8ab4f0ee4b042d5 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 20 Jul 2021 23:10:19 +0800 +Subject: [PATCH 166/201] perf pmu: Fix alias matching + +mainline inclusion +from mainline-v5.14-rc4 +commit c07d5c9226980ca5ae21c6a2714baa95be2ce164 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c07d5c9226980ca5ae21c6a2714baa95be2ce164 + +---------------------------------------------------------------------- + +Commit c47a5599eda324ba ("perf tools: Fix pattern matching for same +substring in different PMU type"), may have fixed some alias matching, +but has broken some others. + +Firstly it cannot handle the simple scenario of PMU name in form +pmu_name{digits} - it can only handle pmu_name_{digits}. + +Secondly it cannot handle more complex matching in the case where we +have multiple tokens. In this scenario, the code failed to realise that +we may examine multiple substrings in the PMU name. + +Fix in two ways: + +- Change perf_pmu__valid_suffix() to accept a PMU name without '_' in the + suffix + +- Only pay attention to perf_pmu__valid_suffix() for the final token + +Also add const qualifiers as necessary to avoid casting. + +Fixes: c47a5599eda324ba ("perf tools: Fix pattern matching for same substring in different PMU type") +Signed-off-by: John Garry +Tested-by: Jin Yao +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/1626793819-79090-1-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index a31ce1613161..cad765e75ace 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -770,9 +770,13 @@ struct pmu_events_map *__weak pmu_events_map__find(void) + return perf_pmu__find_map(NULL); + } + +-static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) ++/* ++ * Suffix must be in form tok_{digits}, or tok{digits}, or same as pmu_name ++ * to be valid. ++ */ ++static bool perf_pmu__valid_suffix(const char *pmu_name, char *tok) + { +- char *p; ++ const char *p; + + if (strncmp(pmu_name, tok, strlen(tok))) + return false; +@@ -781,12 +785,16 @@ static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) + if (*p == 0) + return true; + +- if (*p != '_') +- return false; ++ if (*p == '_') ++ ++p; + +- ++p; +- if (*p == 0 || !isdigit(*p)) +- return false; ++ /* Ensure we end in a number */ ++ while (1) { ++ if (!isdigit(*p)) ++ return false; ++ if (*(++p) == 0) ++ break; ++ } + + return true; + } +@@ -817,12 +825,19 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) + * match "socket" in "socketX_pmunameY" and then "pmuname" in + * "pmunameY". + */ +- for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) { ++ while (1) { ++ char *next_tok = strtok_r(NULL, ",", &tmp); ++ + name = strstr(name, tok); +- if (!name || !perf_pmu__valid_suffix((char *)name, tok)) { ++ if (!name || ++ (!next_tok && !perf_pmu__valid_suffix(name, tok))) { + res = false; + goto out; + } ++ if (!next_tok) ++ break; ++ tok = next_tok; ++ name += strlen(tok); + } + + res = true; +-- +2.27.0 + diff --git a/patches/0284-perf-pmu-Add-alias-match-method-to-fit-pmu_name-of-H.patch b/patches/0284-perf-pmu-Add-alias-match-method-to-fit-pmu_name-of-H.patch new file mode 100644 index 0000000..47a70fa --- /dev/null +++ b/patches/0284-perf-pmu-Add-alias-match-method-to-fit-pmu_name-of-H.patch @@ -0,0 +1,37 @@ +From 0a04df5ad6928c7ed6b3954273f7469a2e3d90a9 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:16 +0800 +Subject: [PATCH 167/201] perf pmu: Add alias match method to fit pmu_name of + HiSilicon DDRC + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +pmu_name of DDRC PMU on Hip09 platform is set as "hisi_sllcX_ddrcY_Z", +current match method of pmu_name cannot fit DDRC pmu, so modify the method. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +--- + tools/perf/util/pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index cad765e75ace..529236890a43 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -790,7 +790,7 @@ static bool perf_pmu__valid_suffix(const char *pmu_name, char *tok) + + /* Ensure we end in a number */ + while (1) { +- if (!isdigit(*p)) ++ if (!isdigit(*p) && (*p != '_')) + return false; + if (*(++p) == 0) + break; +-- +2.27.0 + diff --git a/patches/0285-perf-pmu-Simplify-arguments-of-__perf_pmu__new_alias.patch b/patches/0285-perf-pmu-Simplify-arguments-of-__perf_pmu__new_alias.patch new file mode 100644 index 0000000..212dd47 --- /dev/null +++ b/patches/0285-perf-pmu-Simplify-arguments-of-__perf_pmu__new_alias.patch @@ -0,0 +1,109 @@ +From fbcb99fb4cc2a8ed5ca7c860006911f6dcb3804c Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Tue, 27 Apr 2021 15:01:16 +0800 +Subject: [PATCH 168/201] perf pmu: Simplify arguments of __perf_pmu__new_alias + +mainline inclusion +from mainline-v5.13-rc1 +commit eab35953e67b48c763fbb0e0ffc64dd3152361ea +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eab35953e67b48c763fbb0e0ffc64dd3152361ea + +---------------------------------------------------------------------- + +Simplify the arguments of __perf_pmu__new_alias() by passing the whole +'struct pme_event' pointer. + +Signed-off-by: Jin Yao +Reviewed-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20210427070139.25256-4-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 36 ++++++++++++++++-------------------- + 1 file changed, 16 insertions(+), 20 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 529236890a43..bc85c8896db9 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -306,18 +306,25 @@ static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, + } + + static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, +- char *desc, char *val, +- char *long_desc, char *topic, +- char *unit, char *perpkg, +- char *metric_expr, +- char *metric_name, +- char *deprecated) ++ char *desc, char *val, struct pmu_event *pe) + { + struct parse_events_term *term; + struct perf_pmu_alias *alias; + int ret; + int num; + char newval[256]; ++ char *long_desc = NULL, *topic = NULL, *unit = NULL, *perpkg = NULL, ++ *metric_expr = NULL, *metric_name = NULL, *deprecated = NULL; ++ ++ if (pe) { ++ long_desc = (char *)pe->long_desc; ++ topic = (char *)pe->topic; ++ unit = (char *)pe->unit; ++ perpkg = (char *)pe->perpkg; ++ metric_expr = (char *)pe->metric_expr; ++ metric_name = (char *)pe->metric_name; ++ deprecated = (char *)pe->deprecated; ++ } + + alias = malloc(sizeof(*alias)); + if (!alias) +@@ -406,8 +413,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI + /* Remove trailing newline from sysfs file */ + rtrim(buf); + +- return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL); ++ return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL); + } + + static inline bool pmu_alias_info_file(char *name) +@@ -882,11 +888,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, + /* need type casts to override 'const' */ + __perf_pmu__new_alias(head, NULL, (char *)pe->name, + (char *)pe->desc, (char *)pe->event, +- (char *)pe->long_desc, (char *)pe->topic, +- (char *)pe->unit, (char *)pe->perpkg, +- (char *)pe->metric_expr, +- (char *)pe->metric_name, +- (char *)pe->deprecated); ++ pe); + } + } + +@@ -953,13 +955,7 @@ static int pmu_add_sys_aliases_iter_fn(struct pmu_event *pe, void *data) + (char *)pe->name, + (char *)pe->desc, + (char *)pe->event, +- (char *)pe->long_desc, +- (char *)pe->topic, +- (char *)pe->unit, +- (char *)pe->perpkg, +- (char *)pe->metric_expr, +- (char *)pe->metric_name, +- (char *)pe->deprecated); ++ pe); + } + + return 0; +-- +2.27.0 + diff --git a/patches/0286-perf-pmu-Save-pmu-name.patch b/patches/0286-perf-pmu-Save-pmu-name.patch new file mode 100644 index 0000000..2b41307 --- /dev/null +++ b/patches/0286-perf-pmu-Save-pmu-name.patch @@ -0,0 +1,100 @@ +From 6308ca084108657d3e8f1adb63112edf7d83cdd8 Mon Sep 17 00:00:00 2001 +From: Jin Yao +Date: Tue, 27 Apr 2021 15:01:17 +0800 +Subject: [PATCH 169/201] perf pmu: Save pmu name + +mainline inclusion +from mainline-v5.13-rc1 +commit 32705de7d45d0ed989517a63454c2b3e5e5ea267 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=32705de7d45d0ed989517a63454c2b3e5e5ea267 + +---------------------------------------------------------------------- + +On hybrid platform, one event is available on one pmu +(such as, available on cpu_core or on cpu_atom). + +This patch saves the pmu name to the pmu field of struct perf_pmu_alias. +Then next we can know the pmu which the event can be enabled on. + +Signed-off-by: Jin Yao +Reviewed-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20210427070139.25256-5-yao.jin@linux.intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 10 +++++++++- + tools/perf/util/pmu.h | 1 + + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index bc85c8896db9..089b5af03f98 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -283,6 +283,7 @@ void perf_pmu_free_alias(struct perf_pmu_alias *newalias) + zfree(&newalias->str); + zfree(&newalias->metric_expr); + zfree(&newalias->metric_name); ++ zfree(&newalias->pmu_name); + parse_events_terms__purge(&newalias->terms); + free(newalias); + } +@@ -297,6 +298,10 @@ static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, + + list_for_each_entry(a, alist, list) { + if (!strcasecmp(newalias->name, a->name)) { ++ if (newalias->pmu_name && a->pmu_name && ++ !strcasecmp(newalias->pmu_name, a->pmu_name)) { ++ continue; ++ } + perf_pmu_update_alias(a, newalias); + perf_pmu_free_alias(newalias); + return true; +@@ -314,7 +319,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + int num; + char newval[256]; + char *long_desc = NULL, *topic = NULL, *unit = NULL, *perpkg = NULL, +- *metric_expr = NULL, *metric_name = NULL, *deprecated = NULL; ++ *metric_expr = NULL, *metric_name = NULL, *deprecated = NULL, ++ *pmu_name = NULL; + + if (pe) { + long_desc = (char *)pe->long_desc; +@@ -324,6 +330,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + metric_expr = (char *)pe->metric_expr; + metric_name = (char *)pe->metric_name; + deprecated = (char *)pe->deprecated; ++ pmu_name = (char *)pe->pmu; + } + + alias = malloc(sizeof(*alias)); +@@ -389,6 +396,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + } + alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1; + alias->str = strdup(newval); ++ alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; + + if (deprecated) + alias->deprecated = true; +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index 118a2871e717..a9942e5b076d 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -62,6 +62,7 @@ struct perf_pmu_alias { + bool deprecated; + char *metric_expr; + char *metric_name; ++ char *pmu_name; + }; + + struct perf_pmu *perf_pmu__find(const char *name); +-- +2.27.0 + diff --git a/patches/0287-perf-jevents-Make-build-dependency-on-test-JSONs.patch b/patches/0287-perf-jevents-Make-build-dependency-on-test-JSONs.patch new file mode 100644 index 0000000..c16e299 --- /dev/null +++ b/patches/0287-perf-jevents-Make-build-dependency-on-test-JSONs.patch @@ -0,0 +1,59 @@ +From ea7c8f3686529a92bfbe2913216fcc457675566b Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 3 Aug 2021 08:44:09 +0100 +Subject: [PATCH 170/201] perf jevents: Make build dependency on test JSONs + +mainline inclusion +from mainline-v5.15-rc1 +commit 517db3b59537a59f6cc251b1926df93e93bb9c87 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=517db3b59537a59f6cc251b1926df93e93bb9c87 + +---------------------------------------------------------------------- + +Currently all JSONs and the mapfile for an arch are dependencies for +building pmu-events.c + +The test JSONs are missing as a dependency, so add them. + +Signed-off-by: John Garry +Reported-by: Arnaldo Carvalho de Melo +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: http://lore.kernel.org/lkml/90094733-741c-50e5-ac7d-f5640b5f0bdd@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/Build | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build +index 215ba30b8534..a055dee6a46a 100644 +--- a/tools/perf/pmu-events/Build ++++ b/tools/perf/pmu-events/Build +@@ -6,10 +6,13 @@ pmu-events-y += pmu-events.o + JDIR = pmu-events/arch/$(SRCARCH) + JSON = $(shell [ -d $(JDIR) ] && \ + find $(JDIR) -name '*.json' -o -name 'mapfile.csv') ++JDIR_TEST = pmu-events/arch/test ++JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \ ++ find $(JDIR_TEST) -name '*.json') + + # + # Locate/process JSON files in pmu-events/arch/ + # directory and create tables in pmu-events.c. + # +-$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS) ++$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JSON_TEST) $(JEVENTS) + $(Q)$(call echo-cmd,gen)$(JEVENTS) $(SRCARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V) +-- +2.27.0 + diff --git a/patches/0288-perf-test-Factor-out-pmu-events-event-comparison.patch b/patches/0288-perf-test-Factor-out-pmu-events-event-comparison.patch new file mode 100644 index 0000000..a86080e --- /dev/null +++ b/patches/0288-perf-test-Factor-out-pmu-events-event-comparison.patch @@ -0,0 +1,177 @@ +From b22bcc244c4e05e6fef9c8d3818797a323b87b88 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:16 +0800 +Subject: [PATCH 171/201] perf test: Factor out pmu-events event comparison + +mainline inclusion +from mainline-v5.15-rc1 +commit 19ac3df32f883a8341b1ceaad40be33b3ac85f23 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=19ac3df32f883a8341b1ceaad40be33b3ac85f23 + +---------------------------------------------------------------------- + +Factor out event comparison which will be used in multiple places. + +Also test "pmu" and "compat" fields. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 119 +++++++++++++++++++--------------- + 1 file changed, 66 insertions(+), 53 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 14c927166935..47b5fec7edbf 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -161,6 +161,71 @@ static struct pmu_events_map *__test_pmu_get_events_map(void) + return NULL; + } + ++static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) ++{ ++ if (!is_same(e1->desc, e2->desc)) { ++ pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n", ++ e1->name, e1->desc, e2->desc); ++ return -1; ++ } ++ ++ if (!is_same(e1->topic, e2->topic)) { ++ pr_debug2("testing event e1 %s: mismatched topic, %s vs %s\n", ++ e1->name, e1->topic, e2->topic); ++ return -1; ++ } ++ ++ if (!is_same(e1->long_desc, e2->long_desc)) { ++ pr_debug2("testing event e1 %s: mismatched long_desc, %s vs %s\n", ++ e1->name, e1->long_desc, e2->long_desc); ++ return -1; ++ } ++ ++ if (!is_same(e1->unit, e2->unit)) { ++ pr_debug2("testing event e1 %s: mismatched unit, %s vs %s\n", ++ e1->name, e1->unit, e2->unit); ++ return -1; ++ } ++ ++ if (!is_same(e1->perpkg, e2->perpkg)) { ++ pr_debug2("testing event e1 %s: mismatched perpkg, %s vs %s\n", ++ e1->name, e1->perpkg, e2->perpkg); ++ return -1; ++ } ++ ++ if (!is_same(e1->metric_expr, e2->metric_expr)) { ++ pr_debug2("testing event e1 %s: mismatched metric_expr, %s vs %s\n", ++ e1->name, e1->metric_expr, e2->metric_expr); ++ return -1; ++ } ++ ++ if (!is_same(e1->metric_name, e2->metric_name)) { ++ pr_debug2("testing event e1 %s: mismatched metric_name, %s vs %s\n", ++ e1->name, e1->metric_name, e2->metric_name); ++ return -1; ++ } ++ ++ if (!is_same(e1->deprecated, e2->deprecated)) { ++ pr_debug2("testing event e1 %s: mismatched deprecated, %s vs %s\n", ++ e1->name, e1->deprecated, e2->deprecated); ++ return -1; ++ } ++ ++ if (!is_same(e1->pmu, e2->pmu)) { ++ pr_debug2("testing event e1 %s: mismatched pmu string, %s vs %s\n", ++ e1->name, e1->pmu, e2->pmu); ++ return -1; ++ } ++ ++ if (!is_same(e1->compat, e2->compat)) { ++ pr_debug2("testing event e1 %s: mismatched compat string, %s vs %s\n", ++ e1->name, e1->compat, e2->compat); ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* Verify generated events from pmu-events.c is as expected */ + static int test_pmu_event_table(void) + { +@@ -193,60 +258,8 @@ static int test_pmu_event_table(void) + found = true; + map_events++; + +- if (!is_same(table->desc, te->desc)) { +- pr_debug2("testing event table %s: mismatched desc, %s vs %s\n", +- table->name, table->desc, te->desc); +- return -1; +- } +- +- if (!is_same(table->topic, te->topic)) { +- pr_debug2("testing event table %s: mismatched topic, %s vs %s\n", +- table->name, table->topic, +- te->topic); +- return -1; +- } +- +- if (!is_same(table->long_desc, te->long_desc)) { +- pr_debug2("testing event table %s: mismatched long_desc, %s vs %s\n", +- table->name, table->long_desc, +- te->long_desc); +- return -1; +- } +- +- if (!is_same(table->unit, te->unit)) { +- pr_debug2("testing event table %s: mismatched unit, %s vs %s\n", +- table->name, table->unit, +- te->unit); +- return -1; +- } +- +- if (!is_same(table->perpkg, te->perpkg)) { +- pr_debug2("testing event table %s: mismatched perpkg, %s vs %s\n", +- table->name, table->perpkg, +- te->perpkg); +- return -1; +- } +- +- if (!is_same(table->metric_expr, te->metric_expr)) { +- pr_debug2("testing event table %s: mismatched metric_expr, %s vs %s\n", +- table->name, table->metric_expr, +- te->metric_expr); ++ if (compare_pmu_events(table, te)) + return -1; +- } +- +- if (!is_same(table->metric_name, te->metric_name)) { +- pr_debug2("testing event table %s: mismatched metric_name, %s vs %s\n", +- table->name, table->metric_name, +- te->metric_name); +- return -1; +- } +- +- if (!is_same(table->deprecated, te->deprecated)) { +- pr_debug2("testing event table %s: mismatched deprecated, %s vs %s\n", +- table->name, table->deprecated, +- te->deprecated); +- return -1; +- } + + pr_debug("testing event table %s: pass\n", table->name); + } +-- +2.27.0 + diff --git a/patches/0289-perf-jevents-Relocate-test-events-to-cpu-folder.patch b/patches/0289-perf-jevents-Relocate-test-events-to-cpu-folder.patch new file mode 100644 index 0000000..4ca5f73 --- /dev/null +++ b/patches/0289-perf-jevents-Relocate-test-events-to-cpu-folder.patch @@ -0,0 +1,75 @@ +From 9bd4b86b3ab1f370ed108a261e5b29fda3b8b7de Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:17 +0800 +Subject: [PATCH 172/201] perf jevents: Relocate test events to cpu folder + +mainline inclusion +from mainline-v5.15-rc1 +commit 35267cea901456d16fb3841ab44347937bf0b087 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=35267cea901456d16fb3841ab44347937bf0b087 + +---------------------------------------------------------------------- + +In future to add support for sys events, relocate the core and uncore +events to a cpu folder. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../pmu-events/arch/test/{test_cpu => test_soc/cpu}/branch.json | 0 + .../pmu-events/arch/test/{test_cpu => test_soc/cpu}/cache.json | 0 + .../pmu-events/arch/test/{test_cpu => test_soc/cpu}/other.json | 0 + .../pmu-events/arch/test/{test_cpu => test_soc/cpu}/uncore.json | 0 + tools/perf/pmu-events/jevents.c | 2 +- + 5 files changed, 1 insertion(+), 1 deletion(-) + rename tools/perf/pmu-events/arch/test/{test_cpu => test_soc/cpu}/branch.json (100%) + rename tools/perf/pmu-events/arch/test/{test_cpu => test_soc/cpu}/cache.json (100%) + rename tools/perf/pmu-events/arch/test/{test_cpu => test_soc/cpu}/other.json (100%) + rename tools/perf/pmu-events/arch/test/{test_cpu => test_soc/cpu}/uncore.json (100%) + +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/branch.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/branch.json +similarity index 100% +rename from tools/perf/pmu-events/arch/test/test_cpu/branch.json +rename to tools/perf/pmu-events/arch/test/test_soc/cpu/branch.json +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/cache.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/cache.json +similarity index 100% +rename from tools/perf/pmu-events/arch/test/test_cpu/cache.json +rename to tools/perf/pmu-events/arch/test/test_soc/cpu/cache.json +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/other.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/other.json +similarity index 100% +rename from tools/perf/pmu-events/arch/test/test_cpu/other.json +rename to tools/perf/pmu-events/arch/test/test_soc/cpu/other.json +diff --git a/tools/perf/pmu-events/arch/test/test_cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json +similarity index 100% +rename from tools/perf/pmu-events/arch/test/test_cpu/uncore.json +rename to tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 776a0c660050..6768ac3832e0 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -810,7 +810,7 @@ static void print_mapping_test_table(FILE *outfp) + fprintf(outfp, "\t.cpuid = \"testcpu\",\n"); + fprintf(outfp, "\t.version = \"v1\",\n"); + fprintf(outfp, "\t.type = \"core\",\n"); +- fprintf(outfp, "\t.table = pme_test_cpu,\n"); ++ fprintf(outfp, "\t.table = pme_test_soc_cpu,\n"); + fprintf(outfp, "},\n"); + } + +-- +2.27.0 + diff --git a/patches/0290-perf-test-Declare-pmu-events-test-events-separately.patch b/patches/0290-perf-test-Declare-pmu-events-test-events-separately.patch new file mode 100644 index 0000000..22f8de3 --- /dev/null +++ b/patches/0290-perf-test-Declare-pmu-events-test-events-separately.patch @@ -0,0 +1,389 @@ +From b76c5cef9b2af923a0c4b0e62d493f4be1ee6176 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:18 +0800 +Subject: [PATCH 173/201] perf test: Declare pmu-events test events separately + +mainline inclusion +from mainline-v5.15-rc1 +commit c81e823ff8667f19d2b6ee0ab0e919e3043abd36 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c81e823ff8667f19d2b6ee0ab0e919e3043abd36 + +---------------------------------------------------------------------- + +Currently all test events are put into arrays of test events. +Create pointer arrays of test events instead, so the test events may be +referenced later for tighter alias verification. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 244 ++++++++++++++++++---------------- + 1 file changed, 126 insertions(+), 118 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 47b5fec7edbf..555f01164632 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -30,108 +30,114 @@ struct perf_pmu_test_event { + const char *alias_long_desc; + }; + +-static struct perf_pmu_test_event test_cpu_events[] = { +- { +- .event = { +- .name = "bp_l1_btb_correct", +- .event = "event=0x8a", +- .desc = "L1 BTB Correction", +- .topic = "branch", +- }, +- .alias_str = "event=0x8a", +- .alias_long_desc = "L1 BTB Correction", +- }, +- { +- .event = { +- .name = "bp_l2_btb_correct", +- .event = "event=0x8b", +- .desc = "L2 BTB Correction", +- .topic = "branch", +- }, +- .alias_str = "event=0x8b", +- .alias_long_desc = "L2 BTB Correction", ++static const struct perf_pmu_test_event bp_l1_btb_correct = { ++ .event = { ++ .name = "bp_l1_btb_correct", ++ .event = "event=0x8a", ++ .desc = "L1 BTB Correction", ++ .topic = "branch", + }, +- { +- .event = { +- .name = "segment_reg_loads.any", +- .event = "umask=0x80,period=200000,event=0x6", +- .desc = "Number of segment register loads", +- .topic = "other", +- }, +- .alias_str = "umask=0x80,(null)=0x30d40,event=0x6", +- .alias_long_desc = "Number of segment register loads", ++ .alias_str = "event=0x8a", ++ .alias_long_desc = "L1 BTB Correction", ++}; ++ ++static const struct perf_pmu_test_event bp_l2_btb_correct = { ++ .event = { ++ .name = "bp_l2_btb_correct", ++ .event = "event=0x8b", ++ .desc = "L2 BTB Correction", ++ .topic = "branch", + }, +- { +- .event = { +- .name = "dispatch_blocked.any", +- .event = "umask=0x20,period=200000,event=0x9", +- .desc = "Memory cluster signals to block micro-op dispatch for any reason", +- .topic = "other", +- }, +- .alias_str = "umask=0x20,(null)=0x30d40,event=0x9", +- .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason", ++ .alias_str = "event=0x8b", ++ .alias_long_desc = "L2 BTB Correction", ++}; ++ ++static const struct perf_pmu_test_event segment_reg_loads_any = { ++ .event = { ++ .name = "segment_reg_loads.any", ++ .event = "umask=0x80,period=200000,event=0x6", ++ .desc = "Number of segment register loads", ++ .topic = "other", + }, +- { +- .event = { +- .name = "eist_trans", +- .event = "umask=0x0,period=200000,event=0x3a", +- .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", +- .topic = "other", +- }, +- .alias_str = "umask=0,(null)=0x30d40,event=0x3a", +- .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", ++ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6", ++ .alias_long_desc = "Number of segment register loads", ++}; ++ ++static const struct perf_pmu_test_event dispatch_blocked_any = { ++ .event = { ++ .name = "dispatch_blocked.any", ++ .event = "umask=0x20,period=200000,event=0x9", ++ .desc = "Memory cluster signals to block micro-op dispatch for any reason", ++ .topic = "other", + }, +- { +- .event = { +- .name = "l3_cache_rd", +- .event = "event=0x40", +- .desc = "L3 cache access, read", +- .long_desc = "Attributable Level 3 cache access, read", +- .topic = "cache", +- }, +- .alias_str = "event=0x40", +- .alias_long_desc = "Attributable Level 3 cache access, read", ++ .alias_str = "umask=0x20,(null)=0x30d40,event=0x9", ++ .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason", ++}; ++ ++static const struct perf_pmu_test_event eist_trans = { ++ .event = { ++ .name = "eist_trans", ++ .event = "umask=0x0,period=200000,event=0x3a", ++ .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", ++ .topic = "other", + }, +- { /* sentinel */ +- .event = { +- .name = NULL, +- }, ++ .alias_str = "umask=0,(null)=0x30d40,event=0x3a", ++ .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", ++}; ++ ++static const struct perf_pmu_test_event l3_cache_rd = { ++ .event = { ++ .name = "l3_cache_rd", ++ .event = "event=0x40", ++ .desc = "L3 cache access, read", ++ .long_desc = "Attributable Level 3 cache access, read", ++ .topic = "cache", + }, ++ .alias_str = "event=0x40", ++ .alias_long_desc = "Attributable Level 3 cache access, read", + }; + +-static struct perf_pmu_test_event test_uncore_events[] = { +- { +- .event = { +- .name = "uncore_hisi_ddrc.flux_wcmd", +- .event = "event=0x2", +- .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ", +- .topic = "uncore", +- .long_desc = "DDRC write commands", +- .pmu = "hisi_sccl,ddrc", +- }, +- .alias_str = "event=0x2", +- .alias_long_desc = "DDRC write commands", ++static const struct perf_pmu_test_event *core_events[] = { ++ &bp_l1_btb_correct, ++ &bp_l2_btb_correct, ++ &segment_reg_loads_any, ++ &dispatch_blocked_any, ++ &eist_trans, ++ &l3_cache_rd, ++ NULL ++}; ++ ++static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = { ++ .event = { ++ .name = "uncore_hisi_ddrc.flux_wcmd", ++ .event = "event=0x2", ++ .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ", ++ .topic = "uncore", ++ .long_desc = "DDRC write commands", ++ .pmu = "hisi_sccl,ddrc", + }, +- { +- .event = { +- .name = "unc_cbo_xsnp_response.miss_eviction", +- .event = "umask=0x81,event=0x22", +- .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core", +- .topic = "uncore", +- .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", +- .pmu = "uncore_cbox", +- }, +- .alias_str = "umask=0x81,event=0x22", +- .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .alias_str = "event=0x2", ++ .alias_long_desc = "DDRC write commands", ++}; ++ ++static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { ++ .event = { ++ .name = "unc_cbo_xsnp_response.miss_eviction", ++ .event = "umask=0x81,event=0x22", ++ .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .topic = "uncore", ++ .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .pmu = "uncore_cbox", + }, +- { /* sentinel */ +- .event = { +- .name = NULL, +- }, +- } ++ .alias_str = "umask=0x81,event=0x22", ++ .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", + }; + +-const int total_test_events_size = ARRAY_SIZE(test_uncore_events); ++static const struct perf_pmu_test_event *uncore_events[] = { ++ &uncore_hisi_ddrc_flux_wcmd, ++ &unc_cbo_xsnp_response_miss_eviction, ++ NULL ++}; + + static bool is_same(const char *reference, const char *test) + { +@@ -226,7 +232,7 @@ static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + return 0; + } + +-/* Verify generated events from pmu-events.c is as expected */ ++/* Verify generated events from pmu-events.c are as expected */ + static int test_pmu_event_table(void) + { + struct pmu_events_map *map = __test_pmu_get_events_map(); +@@ -234,31 +240,31 @@ static int test_pmu_event_table(void) + int map_events = 0, expected_events; + + /* ignore 2x sentinels */ +- expected_events = ARRAY_SIZE(test_cpu_events) + +- ARRAY_SIZE(test_uncore_events) - 2; ++ expected_events = ARRAY_SIZE(core_events) + ++ ARRAY_SIZE(uncore_events) - 2; + + if (!map) + return -1; + + for (table = map->table; table->name; table++) { +- struct perf_pmu_test_event *test; +- struct pmu_event *te; ++ struct perf_pmu_test_event const **test_event_table; + bool found = false; + + if (table->pmu) +- test = &test_uncore_events[0]; ++ test_event_table = &uncore_events[0]; + else +- test = &test_cpu_events[0]; ++ test_event_table = &core_events[0]; + +- te = &test->event; ++ for (; *test_event_table; test_event_table++) { ++ struct perf_pmu_test_event const *test_event = *test_event_table; ++ struct pmu_event const *event = &test_event->event; + +- for (; te->name; test++, te = &test->event) { +- if (strcmp(table->name, te->name)) ++ if (strcmp(table->name, event->name)) + continue; + found = true; + map_events++; + +- if (compare_pmu_events(table, te)) ++ if (compare_pmu_events(table, event)) + return -1; + + pr_debug("testing event table %s: pass\n", table->name); +@@ -294,8 +300,7 @@ static struct perf_pmu_alias *find_alias(const char *test_event, struct list_hea + /* Verify aliases are as expected */ + static int __test__pmu_event_aliases(char *pmu_name, int *count) + { +- struct perf_pmu_test_event *test; +- struct pmu_event *te; ++ struct perf_pmu_test_event const **test_event_table; + struct perf_pmu *pmu; + LIST_HEAD(aliases); + int res = 0; +@@ -307,10 +312,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + return -1; + + if (is_pmu_core(pmu_name)) { +- test = &test_cpu_events[0]; ++ test_event_table = &core_events[0]; + use_uncore_table = false; + } else { +- test = &test_uncore_events[0]; ++ test_event_table = &uncore_events[0]; + use_uncore_table = true; + } + +@@ -322,50 +327,53 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + + pmu_add_cpu_aliases_map(&aliases, pmu, map); + +- for (te = &test->event; te->name; test++, te = &test->event) { +- struct perf_pmu_alias *alias = find_alias(te->name, &aliases); ++ for (; *test_event_table; test_event_table++) { ++ struct perf_pmu_test_event const *test_event = *test_event_table; ++ struct pmu_event const *event = &test_event->event; ++ ++ struct perf_pmu_alias *alias = find_alias(event->name, &aliases); + + if (!alias) { + bool uncore_match = pmu_uncore_alias_match(pmu_name, +- te->pmu); ++ event->pmu); + + if (use_uncore_table && !uncore_match) { + pr_debug3("testing aliases PMU %s: skip matching alias %s\n", +- pmu_name, te->name); ++ pmu_name, event->name); + continue; + } + + pr_debug2("testing aliases PMU %s: no alias, alias_table->name=%s\n", +- pmu_name, te->name); ++ pmu_name, event->name); + res = -1; + break; + } + +- if (!is_same(alias->desc, te->desc)) { ++ if (!is_same(alias->desc, event->desc)) { + pr_debug2("testing aliases PMU %s: mismatched desc, %s vs %s\n", +- pmu_name, alias->desc, te->desc); ++ pmu_name, alias->desc, event->desc); + res = -1; + break; + } + +- if (!is_same(alias->long_desc, test->alias_long_desc)) { ++ if (!is_same(alias->long_desc, test_event->alias_long_desc)) { + pr_debug2("testing aliases PMU %s: mismatched long_desc, %s vs %s\n", + pmu_name, alias->long_desc, +- test->alias_long_desc); ++ test_event->alias_long_desc); + res = -1; + break; + } + +- if (!is_same(alias->str, test->alias_str)) { ++ if (!is_same(alias->str, test_event->alias_str)) { + pr_debug2("testing aliases PMU %s: mismatched str, %s vs %s\n", +- pmu_name, alias->str, test->alias_str); ++ pmu_name, alias->str, test_event->alias_str); + res = -1; + break; + } + +- if (!is_same(alias->topic, te->topic)) { ++ if (!is_same(alias->topic, event->topic)) { + pr_debug2("testing aliases PMU %s: mismatched topic, %s vs %s\n", +- pmu_name, alias->topic, te->topic); ++ pmu_name, alias->topic, event->topic); + res = -1; + break; + } +-- +2.27.0 + diff --git a/patches/0291-perf-test-Factor-out-pmu-events-alias-comparison.patch b/patches/0291-perf-test-Factor-out-pmu-events-alias-comparison.patch new file mode 100644 index 0000000..136082b --- /dev/null +++ b/patches/0291-perf-test-Factor-out-pmu-events-alias-comparison.patch @@ -0,0 +1,137 @@ +From 626c5b5e6670cfa5b8d8e30d69d363e23c453891 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:19 +0800 +Subject: [PATCH 174/201] perf test: Factor out pmu-events alias comparison + +mainline inclusion +from mainline-v5.15-rc1 +commit e386acd79017952ba032aad60e8307befc5aa378 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e386acd79017952ba032aad60e8307befc5aa378 + +---------------------------------------------------------------------- + +Factor out alias test which will be used in multiple places. + +Also test missing fields. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-5-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 80 ++++++++++++++++++++++++----------- + 1 file changed, 55 insertions(+), 25 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 555f01164632..7401074ebc48 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -232,6 +232,60 @@ static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + return 0; + } + ++static int compare_alias_to_test_event(struct perf_pmu_alias *alias, ++ struct perf_pmu_test_event const *test_event, ++ char const *pmu_name) ++{ ++ struct pmu_event const *event = &test_event->event; ++ ++ /* An alias was found, ensure everything is in order */ ++ if (!is_same(alias->name, event->name)) { ++ pr_debug("testing aliases PMU %s: mismatched name, %s vs %s\n", ++ pmu_name, alias->name, event->name); ++ return -1; ++ } ++ ++ if (!is_same(alias->desc, event->desc)) { ++ pr_debug("testing aliases PMU %s: mismatched desc, %s vs %s\n", ++ pmu_name, alias->desc, event->desc); ++ return -1; ++ } ++ ++ if (!is_same(alias->long_desc, test_event->alias_long_desc)) { ++ pr_debug("testing aliases PMU %s: mismatched long_desc, %s vs %s\n", ++ pmu_name, alias->long_desc, ++ test_event->alias_long_desc); ++ return -1; ++ } ++ ++ if (!is_same(alias->topic, event->topic)) { ++ pr_debug("testing aliases PMU %s: mismatched topic, %s vs %s\n", ++ pmu_name, alias->topic, event->topic); ++ return -1; ++ } ++ ++ if (!is_same(alias->str, test_event->alias_str)) { ++ pr_debug("testing aliases PMU %s: mismatched str, %s vs %s\n", ++ pmu_name, alias->str, test_event->alias_str); ++ return -1; ++ } ++ ++ if (!is_same(alias->long_desc, test_event->alias_long_desc)) { ++ pr_debug("testing aliases PMU %s: mismatched long desc, %s vs %s\n", ++ pmu_name, alias->str, test_event->alias_long_desc); ++ return -1; ++ } ++ ++ ++ if (!is_same(alias->pmu_name, test_event->event.pmu)) { ++ pr_debug("testing aliases PMU %s: mismatched pmu_name, %s vs %s\n", ++ pmu_name, alias->pmu_name, test_event->event.pmu); ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* Verify generated events from pmu-events.c are as expected */ + static int test_pmu_event_table(void) + { +@@ -349,31 +403,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + break; + } + +- if (!is_same(alias->desc, event->desc)) { +- pr_debug2("testing aliases PMU %s: mismatched desc, %s vs %s\n", +- pmu_name, alias->desc, event->desc); +- res = -1; +- break; +- } +- +- if (!is_same(alias->long_desc, test_event->alias_long_desc)) { +- pr_debug2("testing aliases PMU %s: mismatched long_desc, %s vs %s\n", +- pmu_name, alias->long_desc, +- test_event->alias_long_desc); +- res = -1; +- break; +- } +- +- if (!is_same(alias->str, test_event->alias_str)) { +- pr_debug2("testing aliases PMU %s: mismatched str, %s vs %s\n", +- pmu_name, alias->str, test_event->alias_str); +- res = -1; +- break; +- } +- +- if (!is_same(alias->topic, event->topic)) { +- pr_debug2("testing aliases PMU %s: mismatched topic, %s vs %s\n", +- pmu_name, alias->topic, event->topic); ++ if (compare_alias_to_test_event(alias, test_event, pmu_name)) { + res = -1; + break; + } +-- +2.27.0 + diff --git a/patches/0292-perf-test-Test-pmu-events-core-aliases-separately.patch b/patches/0292-perf-test-Test-pmu-events-core-aliases-separately.patch new file mode 100644 index 0000000..ab15639 --- /dev/null +++ b/patches/0292-perf-test-Test-pmu-events-core-aliases-separately.patch @@ -0,0 +1,151 @@ +From 755c91bcdbb0326b5fb213786a0e4042ffd84304 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:20 +0800 +Subject: [PATCH 175/201] perf test: Test pmu-events core aliases separately + +mainline inclusion +from mainline-v5.15-rc1 +commit 3bc4526b30f14b70280ec2a7a02fbfdab2ebdb0a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3bc4526b30f14b70280ec2a7a02fbfdab2ebdb0a + +---------------------------------------------------------------------- + +The current method to test uncore event aliasing is limited, as it +relies on the uncore PMU being present in the host system to test. + +As such, breakages of uncore PMU aliases goes unnoticed. To make this +more robust, a new method of testing uncore PMUs with fake PMUs will be +used in future. This will be separate to testing core PMU aliases. + +So make the current test function core PMU only. Uncore PMU alias +support will be re-added later. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-6-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 45 +++++++++++++---------------------- + 1 file changed, 16 insertions(+), 29 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 7401074ebc48..088eea628c84 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -352,26 +352,19 @@ static struct perf_pmu_alias *find_alias(const char *test_event, struct list_hea + } + + /* Verify aliases are as expected */ +-static int __test__pmu_event_aliases(char *pmu_name, int *count) ++static int __test_core_pmu_event_aliases(char *pmu_name, int *count) + { + struct perf_pmu_test_event const **test_event_table; + struct perf_pmu *pmu; + LIST_HEAD(aliases); + int res = 0; +- bool use_uncore_table; + struct pmu_events_map *map = __test_pmu_get_events_map(); + struct perf_pmu_alias *a, *tmp; + + if (!map) + return -1; + +- if (is_pmu_core(pmu_name)) { +- test_event_table = &core_events[0]; +- use_uncore_table = false; +- } else { +- test_event_table = &uncore_events[0]; +- use_uncore_table = true; +- } ++ test_event_table = &core_events[0]; + + pmu = zalloc(sizeof(*pmu)); + if (!pmu) +@@ -384,20 +377,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + for (; *test_event_table; test_event_table++) { + struct perf_pmu_test_event const *test_event = *test_event_table; + struct pmu_event const *event = &test_event->event; +- + struct perf_pmu_alias *alias = find_alias(event->name, &aliases); + + if (!alias) { +- bool uncore_match = pmu_uncore_alias_match(pmu_name, +- event->pmu); +- +- if (use_uncore_table && !uncore_match) { +- pr_debug3("testing aliases PMU %s: skip matching alias %s\n", +- pmu_name, event->name); +- continue; +- } +- +- pr_debug2("testing aliases PMU %s: no alias, alias_table->name=%s\n", ++ pr_debug("testing aliases core PMU %s: no alias, alias_table->name=%s\n", + pmu_name, event->name); + res = -1; + break; +@@ -409,7 +392,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + } + + (*count)++; +- pr_debug2("testing aliases PMU %s: matched event %s\n", ++ pr_debug2("testing aliases core PMU %s: matched event %s\n", + pmu_name, alias->name); + } + +@@ -421,7 +404,6 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) + return res; + } + +- + /* Test that aliases generated are as expected */ + static int test_aliases(void) + { +@@ -430,21 +412,26 @@ static int test_aliases(void) + while ((pmu = perf_pmu__scan(pmu)) != NULL) { + int count = 0; + ++ if (!is_pmu_core(pmu->name)) ++ continue; ++ + if (list_empty(&pmu->format)) { +- pr_debug2("skipping testing PMU %s\n", pmu->name); ++ pr_debug2("skipping testing core PMU %s\n", pmu->name); + continue; + } + +- if (__test__pmu_event_aliases(pmu->name, &count)) { +- pr_debug("testing PMU %s aliases: failed\n", pmu->name); ++ if (__test_core_pmu_event_aliases(pmu->name, &count)) { ++ pr_debug("testing core PMU %s aliases: failed\n", pmu->name); + return -1; + } + +- if (count == 0) +- pr_debug3("testing PMU %s aliases: no events to match\n", ++ if (count == 0) { ++ pr_debug("testing core PMU %s aliases: no events to match\n", + pmu->name); +- else +- pr_debug("testing PMU %s aliases: pass\n", pmu->name); ++ return -1; ++ } ++ ++ pr_debug("testing core PMU %s aliases: pass\n", pmu->name); + } + + return 0; +-- +2.27.0 + diff --git a/patches/0293-perf-pmu-Check-.is_uncore-field-in-pmu_add_cpu_alias.patch b/patches/0293-perf-pmu-Check-.is_uncore-field-in-pmu_add_cpu_alias.patch new file mode 100644 index 0000000..f6892fb --- /dev/null +++ b/patches/0293-perf-pmu-Check-.is_uncore-field-in-pmu_add_cpu_alias.patch @@ -0,0 +1,55 @@ +From 38726b240651795b9559daeab23242db4ba5c7d7 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:21 +0800 +Subject: [PATCH 176/201] perf pmu: Check .is_uncore field in + pmu_add_cpu_aliases_map() + +mainline inclusion +from mainline-v5.15-rc1 +commit 5806099a2e2ab36fa7a7705faaf3d7296b701e67 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5806099a2e2ab36fa7a7705faaf3d7296b701e67 + +---------------------------------------------------------------------- + +Calling pmu_is_uncore() for fake PMUs does not work, as it checks sysfs +for the PMU details (which won't exist). + +Check .is_uncore field instead, which makes sense anyway. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-7-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/pmu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 089b5af03f98..172819439cdd 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -885,8 +885,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, + break; + } + +- if (pmu_is_uncore(name) && +- pmu_uncore_alias_match(pname, name)) ++ if (pmu->is_uncore && pmu_uncore_alias_match(pname, name)) + goto new_alias; + + if (strcmp(pname, name)) +-- +2.27.0 + diff --git a/patches/0294-perf-test-Re-add-pmu-event-uncore-PMU-alias-test.patch b/patches/0294-perf-test-Re-add-pmu-event-uncore-PMU-alias-test.patch new file mode 100644 index 0000000..f3888e1 --- /dev/null +++ b/patches/0294-perf-test-Re-add-pmu-event-uncore-PMU-alias-test.patch @@ -0,0 +1,206 @@ +From 840372a1a55293896f2aec5029c523805baa0776 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:22 +0800 +Subject: [PATCH 177/201] perf test: Re-add pmu-event uncore PMU alias test + +mainline inclusion +from mainline-v5.15-rc1 +commit 5a65c0c8f6fd5e0708e52131940f2306a3be4e55 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5a65c0c8f6fd5e0708e52131940f2306a3be4e55 + +---------------------------------------------------------------------- + +Add support to match aliases for uncore PMUs. + +Since we cannot rely on the PMUs being present on the host system, use +fake PMUs. + +The following conditions in the test are ensures: + +- Expected count of aliases created + +- All aliases can be matched to an expected alias in + perf_pmu_test_pmu.aliases + +This will catch the condition fixed in commit c47a5599eda3 ("perf tools: +Fix pattern matching for same substring in different PMU type"), where +excess events were created for a PMU. It will also fix the scenario +inadvertently broken there, where no aliases were created for aliases +with multiple tokens. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-8-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 110 ++++++++++++++++++++++++++++++++++ + 1 file changed, 110 insertions(+) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 088eea628c84..4320e38b42d5 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -28,6 +28,14 @@ struct perf_pmu_test_event { + * be set in the alias. + */ + const char *alias_long_desc; ++ ++ /* PMU which we should match against */ ++ const char *matching_pmu; ++}; ++ ++struct perf_pmu_test_pmu { ++ struct perf_pmu pmu; ++ struct perf_pmu_test_event const *aliases[10]; + }; + + static const struct perf_pmu_test_event bp_l1_btb_correct = { +@@ -118,6 +126,7 @@ static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = { + }, + .alias_str = "event=0x2", + .alias_long_desc = "DDRC write commands", ++ .matching_pmu = "hisi_sccl1_ddrc2", + }; + + static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { +@@ -131,6 +140,7 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { + }, + .alias_str = "umask=0x81,event=0x22", + .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", ++ .matching_pmu = "uncore_cbox_0", + }; + + static const struct perf_pmu_test_event *uncore_events[] = { +@@ -404,10 +414,103 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count) + return res; + } + ++static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) ++{ ++ int alias_count = 0, to_match_count = 0, matched_count = 0; ++ struct perf_pmu_test_event const **table; ++ struct perf_pmu *pmu = &test_pmu->pmu; ++ const char *pmu_name = pmu->name; ++ struct perf_pmu_alias *a, *tmp, *alias; ++ struct pmu_events_map *map; ++ LIST_HEAD(aliases); ++ int res = 0; ++ ++ map = __test_pmu_get_events_map(); ++ if (!map) ++ return -1; ++ pmu_add_cpu_aliases_map(&aliases, pmu, map); ++ ++ /* Count how many aliases we generated */ ++ list_for_each_entry(alias, &aliases, list) ++ alias_count++; ++ ++ /* Count how many aliases we expect from the known table */ ++ for (table = &test_pmu->aliases[0]; *table; table++) ++ to_match_count++; ++ ++ if (alias_count != to_match_count) { ++ pr_debug("testing aliases uncore PMU %s: mismatch expected aliases (%d) vs found (%d)\n", ++ pmu_name, to_match_count, alias_count); ++ res = -1; ++ goto out; ++ } ++ ++ list_for_each_entry(alias, &aliases, list) { ++ bool matched = false; ++ ++ for (table = &test_pmu->aliases[0]; *table; table++) { ++ struct perf_pmu_test_event const *test_event = *table; ++ struct pmu_event const *event = &test_event->event; ++ ++ if (!strcmp(event->name, alias->name)) { ++ if (compare_alias_to_test_event(alias, ++ test_event, ++ pmu_name)) { ++ continue; ++ } ++ matched = true; ++ matched_count++; ++ } ++ } ++ ++ if (matched == false) { ++ pr_debug("testing aliases uncore PMU %s: could not match alias %s\n", ++ pmu_name, alias->name); ++ res = -1; ++ goto out; ++ } ++ } ++ ++ if (alias_count != matched_count) { ++ pr_debug("testing aliases uncore PMU %s: mismatch found aliases (%d) vs matched (%d)\n", ++ pmu_name, matched_count, alias_count); ++ res = -1; ++ } ++ ++out: ++ list_for_each_entry_safe(a, tmp, &aliases, list) { ++ list_del(&a->list); ++ perf_pmu_free_alias(a); ++ } ++ return res; ++} ++ ++static struct perf_pmu_test_pmu test_pmus[] = { ++ { ++ .pmu = { ++ .name = (char *)"hisi_sccl1_ddrc2", ++ .is_uncore = 1, ++ }, ++ .aliases = { ++ &uncore_hisi_ddrc_flux_wcmd, ++ }, ++ }, ++ { ++ .pmu = { ++ .name = (char *)"uncore_cbox_0", ++ .is_uncore = 1, ++ }, ++ .aliases = { ++ &unc_cbo_xsnp_response_miss_eviction, ++ }, ++ }, ++}; ++ + /* Test that aliases generated are as expected */ + static int test_aliases(void) + { + struct perf_pmu *pmu = NULL; ++ unsigned long i; + + while ((pmu = perf_pmu__scan(pmu)) != NULL) { + int count = 0; +@@ -434,6 +537,13 @@ static int test_aliases(void) + pr_debug("testing core PMU %s aliases: pass\n", pmu->name); + } + ++ for (i = 0; i < ARRAY_SIZE(test_pmus); i++) { ++ int res = __test_uncore_pmu_event_aliases(&test_pmus[i]); ++ ++ if (res) ++ return res; ++ } ++ + return 0; + } + +-- +2.27.0 + diff --git a/patches/0295-perf-test-Add-more-pmu-events-uncore-aliases.patch b/patches/0295-perf-test-Add-more-pmu-events-uncore-aliases.patch new file mode 100644 index 0000000..c94e225 --- /dev/null +++ b/patches/0295-perf-test-Add-more-pmu-events-uncore-aliases.patch @@ -0,0 +1,165 @@ +From 46d06a22229e17c3b11a9284000ed3b5b4973f50 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:23 +0800 +Subject: [PATCH 178/201] perf test: Add more pmu-events uncore aliases + +mainline inclusion +from mainline-v5.15-rc1 +commit 6a86657fbc245119190f3f6a477f2331e882af0c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6a86657fbc245119190f3f6a477f2331e882af0c + +---------------------------------------------------------------------- + +Add more events to cover the scenarios fixed and also inadvertently +broken by commit c47a5599eda324ba ("perf tools: Fix pattern matching for +same substring in different PMU type") + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-9-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/test/test_soc/cpu/uncore.json | 23 +++++- + tools/perf/tests/pmu-events.c | 72 +++++++++++++++++++ + 2 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json +index d0a890cc814d..788766f45dbc 100644 +--- a/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json ++++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json +@@ -17,5 +17,26 @@ + "CounterMask": "0", + "Invert": "0", + "EdgeDetect": "0" +- } ++ }, ++ { ++ "EventCode": "0x7", ++ "EventName": "uncore_hisi_l3c.rd_hit_cpipe", ++ "BriefDescription": "Total read hits", ++ "PublicDescription": "Total read hits", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x12", ++ "EventName": "uncore_imc_free_running.cache_miss", ++ "BriefDescription": "Total cache misses", ++ "PublicDescription": "Total cache misses", ++ "Unit": "imc_free_running" ++ }, ++ { ++ "EventCode": "0x34", ++ "EventName": "uncore_imc.cache_hits", ++ "BriefDescription": "Total cache hits", ++ "PublicDescription": "Total cache hits", ++ "Unit": "imc" ++ }, + ] +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 4320e38b42d5..b747354abbb4 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -143,9 +143,54 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { + .matching_pmu = "uncore_cbox_0", + }; + ++static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = { ++ .event = { ++ .name = "uncore_hisi_l3c.rd_hit_cpipe", ++ .event = "event=0x2", ++ .desc = "Total read hits. Unit: hisi_sccl,l3c ", ++ .topic = "uncore", ++ .long_desc = "Total read hits", ++ .pmu = "hisi_sccl,l3c", ++ }, ++ .alias_str = "event=0x7", ++ .alias_long_desc = "Total read hits", ++ .matching_pmu = "hisi_sccl3_l3c7", ++}; ++ ++static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = { ++ .event = { ++ .name = "uncore_imc_free_running.cache_miss", ++ .event = "event=0x12", ++ .desc = "Total cache misses. Unit: uncore_imc_free_running ", ++ .topic = "uncore", ++ .long_desc = "Total cache misses", ++ .pmu = "uncore_imc_free_running", ++ }, ++ .alias_str = "event=0x12", ++ .alias_long_desc = "Total cache misses", ++ .matching_pmu = "uncore_imc_free_running_0", ++}; ++ ++static const struct perf_pmu_test_event uncore_imc_cache_hits = { ++ .event = { ++ .name = "uncore_imc.cache_hits", ++ .event = "event=0x34", ++ .desc = "Total cache hits. Unit: uncore_imc ", ++ .topic = "uncore", ++ .long_desc = "Total cache hits", ++ .pmu = "uncore_imc", ++ }, ++ .alias_str = "event=0x34", ++ .alias_long_desc = "Total cache hits", ++ .matching_pmu = "uncore_imc_0", ++}; ++ + static const struct perf_pmu_test_event *uncore_events[] = { + &uncore_hisi_ddrc_flux_wcmd, + &unc_cbo_xsnp_response_miss_eviction, ++ &uncore_hisi_l3c_rd_hit_cpipe, ++ &uncore_imc_free_running_cache_miss, ++ &uncore_imc_cache_hits, + NULL + }; + +@@ -504,6 +549,33 @@ static struct perf_pmu_test_pmu test_pmus[] = { + &unc_cbo_xsnp_response_miss_eviction, + }, + }, ++ { ++ .pmu = { ++ .name = (char *)"hisi_sccl3_l3c7", ++ .is_uncore = 1, ++ }, ++ .aliases = { ++ &uncore_hisi_l3c_rd_hit_cpipe, ++ }, ++ }, ++ { ++ .pmu = { ++ .name = (char *)"uncore_imc_free_running_0", ++ .is_uncore = 1, ++ }, ++ .aliases = { ++ &uncore_imc_free_running_cache_miss, ++ }, ++ }, ++ { ++ .pmu = { ++ .name = (char *)"uncore_imc_0", ++ .is_uncore = 1, ++ }, ++ .aliases = { ++ &uncore_imc_cache_hits, ++ }, ++ }, + }; + + /* Test that aliases generated are as expected */ +-- +2.27.0 + diff --git a/patches/0296-perf-pmu-Make-pmu_add_sys_aliases-public.patch b/patches/0296-perf-pmu-Make-pmu_add_sys_aliases-public.patch new file mode 100644 index 0000000..e924660 --- /dev/null +++ b/patches/0296-perf-pmu-Make-pmu_add_sys_aliases-public.patch @@ -0,0 +1,67 @@ +From 068cabdac7c1604ec341e915e0920d8d6545d670 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:24 +0800 +Subject: [PATCH 179/201] perf pmu: Make pmu_add_sys_aliases() public + +mainline inclusion +from mainline-v5.15-rc1 +commit e199f47f159d72f12b91d2b33cee78f95ff8ff59 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e199f47f159d72f12b91d2b33cee78f95ff8ff59 + +---------------------------------------------------------------------- + +Function pmu_add_sys_aliases() will be required for the PMU events test +for system events aliases, so make it public. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-10-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/pmu.h +--- + tools/perf/util/pmu.c | 2 +- + tools/perf/util/pmu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index 172819439cdd..acdf4e70b99d 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -968,7 +968,7 @@ static int pmu_add_sys_aliases_iter_fn(struct pmu_event *pe, void *data) + return 0; + } + +-static void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu) ++void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu) + { + struct pmu_sys_event_iter_data idata = { + .head = head, +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index a9942e5b076d..75aeb3a43cfb 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -66,6 +66,7 @@ struct perf_pmu_alias { + }; + + struct perf_pmu *perf_pmu__find(const char *name); ++void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu); + int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, + struct list_head *head_terms, + struct parse_events_error *error); +-- +2.27.0 + diff --git a/patches/0297-perf-jevents-Print-SoC-name-per-system-event-table.patch b/patches/0297-perf-jevents-Print-SoC-name-per-system-event-table.patch new file mode 100644 index 0000000..fb36181 --- /dev/null +++ b/patches/0297-perf-jevents-Print-SoC-name-per-system-event-table.patch @@ -0,0 +1,65 @@ +From 532f5ed5aae8917b9d538ecb91972df1b79c0226 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:25 +0800 +Subject: [PATCH 180/201] perf jevents: Print SoC name per system event table + +mainline inclusion +from mainline-v5.15-rc1 +commit 5abd3988b0382d31a35600732a46fa7f90740658 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5abd3988b0382d31a35600732a46fa7f90740658 + +---------------------------------------------------------------------- + +Print the SoC name per system event table, which will allow the test SoC be +identified by the pmu-events test. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-11-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 3 ++- + tools/perf/pmu-events/pmu-events.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index 6768ac3832e0..cafab324a395 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -832,7 +832,8 @@ static int process_system_event_tables(FILE *outfp) + print_system_event_mapping_table_prefix(outfp); + + list_for_each_entry(sys_event_table, &sys_event_tables, list) { +- fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t},", ++ fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t\t.name = \"%s\",\n\t},", ++ sys_event_table->soc_id, + sys_event_table->soc_id); + } + +diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h +index 70b9c37ed957..f30fe6236291 100644 +--- a/tools/perf/pmu-events/pmu-events.h ++++ b/tools/perf/pmu-events/pmu-events.h +@@ -45,6 +45,7 @@ struct pmu_events_map { + }; + + struct pmu_sys_events { ++ const char *name; + struct pmu_event *table; + }; + +-- +2.27.0 + diff --git a/patches/0298-perf-test-Add-pmu-events-sys-event-support.patch b/patches/0298-perf-test-Add-pmu-events-sys-event-support.patch new file mode 100644 index 0000000..46d062e --- /dev/null +++ b/patches/0298-perf-test-Add-pmu-events-sys-event-support.patch @@ -0,0 +1,185 @@ +From ed1b1864948aed415ed182517a1255a773e5505c Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 29 Jul 2021 21:56:26 +0800 +Subject: [PATCH 181/201] perf test: Add pmu-events sys event support + +mainline inclusion +from mainline-v5.15-rc1 +commit 8ee465a181d0100533c6039bbbcea5517a049aec +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8ee465a181d0100533c6039bbbcea5517a049aec + +---------------------------------------------------------------------- + +Add support for system events, along with core and uncore events. + +Support for a sample PMU is also added. + +Signed-off-by: John Garry +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@huawei.com +Link: https //lore.kernel.org/r/1627566986-30605-12-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../arch/test/test_soc/sys/uncore.json | 9 +++ + tools/perf/tests/pmu-events.c | 77 ++++++++++++++++++- + 2 files changed, 83 insertions(+), 3 deletions(-) + create mode 100644 tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json + +diff --git a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json +new file mode 100644 +index 000000000000..0f681a6e10ea +--- /dev/null ++++ b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json +@@ -0,0 +1,9 @@ ++[ ++ { ++ "BriefDescription": "ddr write-cycles event", ++ "EventCode": "0x2b", ++ "EventName": "sys_ddr_pmu.write_cycles", ++ "Unit": "sys_ddr_pmu", ++ "Compat": "v8" ++ }, ++] +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index b747354abbb4..fcd9df8f545d 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -194,6 +194,25 @@ static const struct perf_pmu_test_event *uncore_events[] = { + NULL + }; + ++static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = { ++ .event = { ++ .name = "sys_ddr_pmu.write_cycles", ++ .event = "event=0x2b", ++ .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ", ++ .topic = "uncore", ++ .pmu = "uncore_sys_ddr_pmu", ++ .compat = "v8", ++ }, ++ .alias_str = "event=0x2b", ++ .alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ", ++ .matching_pmu = "uncore_sys_ddr_pmu", ++}; ++ ++static const struct perf_pmu_test_event *sys_events[] = { ++ &sys_ddr_pmu_write_cycles, ++ NULL ++}; ++ + static bool is_same(const char *reference, const char *test) + { + if (!reference && !test) +@@ -222,6 +241,18 @@ static struct pmu_events_map *__test_pmu_get_events_map(void) + return NULL; + } + ++static struct pmu_event *__test_pmu_get_sys_events_table(void) ++{ ++ struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; ++ ++ for ( ; tables->name; tables++) { ++ if (!strcmp("pme_test_soc_sys", tables->name)) ++ return tables->table; ++ } ++ ++ return NULL; ++} ++ + static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + { + if (!is_same(e1->desc, e2->desc)) { +@@ -344,15 +375,17 @@ static int compare_alias_to_test_event(struct perf_pmu_alias *alias, + /* Verify generated events from pmu-events.c are as expected */ + static int test_pmu_event_table(void) + { ++ struct pmu_event *sys_event_tables = __test_pmu_get_sys_events_table(); + struct pmu_events_map *map = __test_pmu_get_events_map(); + struct pmu_event *table; + int map_events = 0, expected_events; + +- /* ignore 2x sentinels */ ++ /* ignore 3x sentinels */ + expected_events = ARRAY_SIZE(core_events) + +- ARRAY_SIZE(uncore_events) - 2; ++ ARRAY_SIZE(uncore_events) + ++ ARRAY_SIZE(sys_events) - 3; + +- if (!map) ++ if (!map || !sys_event_tables) + return -1; + + for (table = map->table; table->name; table++) { +@@ -386,6 +419,33 @@ static int test_pmu_event_table(void) + } + } + ++ for (table = sys_event_tables; table->name; table++) { ++ struct perf_pmu_test_event const **test_event_table; ++ bool found = false; ++ ++ test_event_table = &sys_events[0]; ++ ++ for (; *test_event_table; test_event_table++) { ++ struct perf_pmu_test_event const *test_event = *test_event_table; ++ struct pmu_event const *event = &test_event->event; ++ ++ if (strcmp(table->name, event->name)) ++ continue; ++ found = true; ++ map_events++; ++ ++ if (compare_pmu_events(table, event)) ++ return -1; ++ ++ pr_debug("testing sys event table %s: pass\n", table->name); ++ } ++ if (!found) { ++ pr_debug("testing event table: could not find event %s\n", ++ table->name); ++ return -1; ++ } ++ } ++ + if (map_events != expected_events) { + pr_err("testing event table: found %d, but expected %d\n", + map_events, expected_events); +@@ -474,6 +534,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) + if (!map) + return -1; + pmu_add_cpu_aliases_map(&aliases, pmu, map); ++ pmu_add_sys_aliases(&aliases, pmu); + + /* Count how many aliases we generated */ + list_for_each_entry(alias, &aliases, list) +@@ -576,6 +637,16 @@ static struct perf_pmu_test_pmu test_pmus[] = { + &uncore_imc_cache_hits, + }, + }, ++ { ++ .pmu = { ++ .name = (char *)"uncore_sys_ddr_pmu0", ++ .is_uncore = 1, ++ .id = (char *)"v8", ++ }, ++ .aliases = { ++ &sys_ddr_pmu_write_cycles, ++ }, ++ }, + }; + + /* Test that aliases generated are as expected */ +-- +2.27.0 + diff --git a/patches/0299-perf-parse-events-Set-numeric-term-config.patch b/patches/0299-perf-parse-events-Set-numeric-term-config.patch new file mode 100644 index 0000000..7ad1fdb --- /dev/null +++ b/patches/0299-perf-parse-events-Set-numeric-term-config.patch @@ -0,0 +1,135 @@ +From b8441923b082859f5681d98d3681555eb17562a1 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 16 Sep 2021 20:34:21 +0800 +Subject: [PATCH 182/201] perf parse-events: Set numeric term config + +mainline inclusion +from mainline-v5.16-rc1 +commit 4f9d4f8aa7328068a2f25cfb3d1d04c1b6fa54ac +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f9d4f8aa7328068a2f25cfb3d1d04c1b6fa54ac + +---------------------------------------------------------------------- + +For numeric terms, the config field may be NULL as it is not set from +the l+y parsing. + +Fix by setting the term config from the term type name. + +Also fix up the pmu-events test to set the alias strings to set the +period term properly, and fix up parse-events test to check the term +config string. + +Signed-off-by: John Garry +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Cc: liuqi115@huawei.com +Link: https://lore.kernel.org/r/1631795665-240946-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-events.c | 8 ++++---- + tools/perf/tests/pmu-events.c | 6 +++--- + tools/perf/util/parse-events.c | 2 +- + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c +index 4ca5e569a05f..77af44643c90 100644 +--- a/tools/perf/tests/parse-events.c ++++ b/tools/perf/tests/parse-events.c +@@ -602,7 +602,7 @@ static int test__checkterms_simple(struct list_head *terms) + TEST_ASSERT_VAL("wrong type val", + term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + TEST_ASSERT_VAL("wrong val", term->val.num == 10); +- TEST_ASSERT_VAL("wrong config", !term->config); ++ TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config")); + + /* config1 */ + term = list_entry(term->list.next, struct parse_events_term, list); +@@ -611,7 +611,7 @@ static int test__checkterms_simple(struct list_head *terms) + TEST_ASSERT_VAL("wrong type val", + term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + TEST_ASSERT_VAL("wrong val", term->val.num == 1); +- TEST_ASSERT_VAL("wrong config", !term->config); ++ TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config1")); + + /* config2=3 */ + term = list_entry(term->list.next, struct parse_events_term, list); +@@ -620,7 +620,7 @@ static int test__checkterms_simple(struct list_head *terms) + TEST_ASSERT_VAL("wrong type val", + term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + TEST_ASSERT_VAL("wrong val", term->val.num == 3); +- TEST_ASSERT_VAL("wrong config", !term->config); ++ TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config2")); + + /* umask=1*/ + term = list_entry(term->list.next, struct parse_events_term, list); +@@ -658,7 +658,7 @@ static int test__checkterms_simple(struct list_head *terms) + TEST_ASSERT_VAL("wrong type val", + term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); + TEST_ASSERT_VAL("wrong val", term->val.num == 0xead); +- TEST_ASSERT_VAL("wrong config", !term->config); ++ TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "config")); + return 0; + } + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index fcd9df8f545d..80e71bf8a3fe 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -67,7 +67,7 @@ static const struct perf_pmu_test_event segment_reg_loads_any = { + .desc = "Number of segment register loads", + .topic = "other", + }, +- .alias_str = "umask=0x80,(null)=0x30d40,event=0x6", ++ .alias_str = "umask=0x80,period=0x30d40,event=0x6", + .alias_long_desc = "Number of segment register loads", + }; + +@@ -78,7 +78,7 @@ static const struct perf_pmu_test_event dispatch_blocked_any = { + .desc = "Memory cluster signals to block micro-op dispatch for any reason", + .topic = "other", + }, +- .alias_str = "umask=0x20,(null)=0x30d40,event=0x9", ++ .alias_str = "umask=0x20,period=0x30d40,event=0x9", + .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason", + }; + +@@ -89,7 +89,7 @@ static const struct perf_pmu_test_event eist_trans = { + .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", + .topic = "other", + }, +- .alias_str = "umask=0,(null)=0x30d40,event=0x3a", ++ .alias_str = "umask=0,period=0x30d40,event=0x3a", + .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", + }; + +diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c +index 2d20b54866ad..18238a6ca9d2 100644 +--- a/tools/perf/util/parse-events.c ++++ b/tools/perf/util/parse-events.c +@@ -2674,7 +2674,7 @@ int parse_events_term__num(struct parse_events_term **term, + struct parse_events_term temp = { + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = type_term, +- .config = config, ++ .config = config ? : strdup(config_term_names[type_term]), + .no_value = no_value, + .err_term = loc_term ? loc_term->first_column : 0, + .err_val = loc_val ? loc_val->first_column : 0, +-- +2.27.0 + diff --git a/patches/0300-perf-jevents-Support-ConfigCode.patch b/patches/0300-perf-jevents-Support-ConfigCode.patch new file mode 100644 index 0000000..8839b88 --- /dev/null +++ b/patches/0300-perf-jevents-Support-ConfigCode.patch @@ -0,0 +1,97 @@ +From e0c30e694311b19f0f7078298021077019719aef Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 16 Sep 2021 20:34:22 +0800 +Subject: [PATCH 183/201] perf jevents: Support ConfigCode + +mainline inclusion +from mainline-v5.16-rc1 +commit d60bad10c4ae42ef96b5b7dfd5924c54f3f257a6 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d60bad10c4ae42ef96b5b7dfd5924c54f3f257a6 + +---------------------------------------------------------------------- + +Some PMUs use "config=XXX" for eventcodes, like: + +more /sys/bus/event_source/devices/hisi_sccl1_ddrc3/events/act_cmd +config=0x5 + +However jevents would give an alias with .event field "event=0x5" for +this event. This is handled without issue by the parse events code, but +the pmu alias code gets a bit confused, as it warns about assigning +"event=0x5" over "config=0x5" in perf_pmu_assign_str() when merging +aliases: ./perf stat -v -e act_cmd ... alias act_cmd differs in field +'value' ... + +To make things a bit more straightforward, allow jevents to support +"config=XXX" as well, by supporting a "ConfigCode" field. + +Signed-off-by: John Garry +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Cc: liuqi115@huawei.com +Link: https://lore.kernel.org/r/1631795665-240946-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/pmu-events/jevents.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index cafab324a395..b330c244f076 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -571,10 +571,12 @@ static int json_events(const char *fn, + struct json_event je = {}; + char *arch_std = NULL; + unsigned long long eventcode = 0; ++ unsigned long long configcode = 0; + struct msrmap *msr = NULL; + jsmntok_t *msrval = NULL; + jsmntok_t *precise = NULL; + jsmntok_t *obj = tok++; ++ bool configcode_present = false; + + EXPECT(obj->type == JSMN_OBJECT, obj, "expected object"); + for (j = 0; j < obj->size; j += 2) { +@@ -597,6 +599,12 @@ static int json_events(const char *fn, + addfield(map, &code, "", "", val); + eventcode |= strtoul(code, NULL, 0); + free(code); ++ } else if (json_streq(map, field, "ConfigCode")) { ++ char *code = NULL; ++ addfield(map, &code, "", "", val); ++ configcode |= strtoul(code, NULL, 0); ++ free(code); ++ configcode_present = true; + } else if (json_streq(map, field, "ExtSel")) { + char *code = NULL; + addfield(map, &code, "", "", val); +@@ -678,7 +686,10 @@ static int json_events(const char *fn, + addfield(map, &extra_desc, " ", + "(Precise event)", NULL); + } +- snprintf(buf, sizeof buf, "event=%#llx", eventcode); ++ if (configcode_present) ++ snprintf(buf, sizeof buf, "config=%#llx", configcode); ++ else ++ snprintf(buf, sizeof buf, "event=%#llx", eventcode); + addfield(map, &event, ",", buf, NULL); + if (je.desc && extra_desc) + addfield(map, &je.desc, " ", extra_desc, NULL); +-- +2.27.0 + diff --git a/patches/0301-perf-test-Verify-more-event-members-in-pmu-events-te.patch b/patches/0301-perf-test-Verify-more-event-members-in-pmu-events-te.patch new file mode 100644 index 0000000..efa865e --- /dev/null +++ b/patches/0301-perf-test-Verify-more-event-members-in-pmu-events-te.patch @@ -0,0 +1,144 @@ +From 82f903d05ea2c430be9f39a85f3857a7a37e56db Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 16 Sep 2021 20:34:23 +0800 +Subject: [PATCH 184/201] perf test: Verify more event members in pmu-events + test + +mainline inclusion +from mainline-v5.16-rc1 +commit 56be05103a408b7f56c5e75717b2b23a5adf1ddb +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=56be05103a408b7f56c5e75717b2b23a5adf1ddb + +---------------------------------------------------------------------- + +Function compare_pmu_events() does not compare all struct pmu-events +members, so add tests for missing members "name", "event", "aggr_mod", +"event", "metric_constraint", and "metric_group", and re-order the tests +to match current struct pmu-events member ordering. + +Also fix uncore_hisi_l3c_rd_hit_cpipe.event member, now that we're +actually testing it. + +Signed-off-by: John Garry +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Cc: liuqi115@huawei.com +Link: https://lore.kernel.org/r/1631795665-240946-4-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 50 ++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 10 deletions(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index 80e71bf8a3fe..c9a89c8f4ab1 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -146,7 +146,7 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { + static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = { + .event = { + .name = "uncore_hisi_l3c.rd_hit_cpipe", +- .event = "event=0x2", ++ .event = "event=0x7", + .desc = "Total read hits. Unit: hisi_sccl,l3c ", + .topic = "uncore", + .long_desc = "Total read hits", +@@ -255,6 +255,24 @@ static struct pmu_event *__test_pmu_get_sys_events_table(void) + + static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + { ++ if (!is_same(e1->name, e2->name)) { ++ pr_debug2("testing event e1 %s: mismatched name string, %s vs %s\n", ++ e1->name, e1->name, e2->name); ++ return -1; ++ } ++ ++ if (!is_same(e1->compat, e2->compat)) { ++ pr_debug2("testing event e1 %s: mismatched compat string, %s vs %s\n", ++ e1->name, e1->compat, e2->compat); ++ return -1; ++ } ++ ++ if (!is_same(e1->event, e2->event)) { ++ pr_debug2("testing event e1 %s: mismatched event, %s vs %s\n", ++ e1->name, e1->event, e2->event); ++ return -1; ++ } ++ + if (!is_same(e1->desc, e2->desc)) { + pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n", + e1->name, e1->desc, e2->desc); +@@ -273,6 +291,12 @@ static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + return -1; + } + ++ if (!is_same(e1->pmu, e2->pmu)) { ++ pr_debug2("testing event e1 %s: mismatched pmu string, %s vs %s\n", ++ e1->name, e1->pmu, e2->pmu); ++ return -1; ++ } ++ + if (!is_same(e1->unit, e2->unit)) { + pr_debug2("testing event e1 %s: mismatched unit, %s vs %s\n", + e1->name, e1->unit, e2->unit); +@@ -285,6 +309,12 @@ static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + return -1; + } + ++ if (!is_same(e1->aggr_mode, e2->aggr_mode)) { ++ pr_debug2("testing event e1 %s: mismatched aggr_mode, %s vs %s\n", ++ e1->name, e1->aggr_mode, e2->aggr_mode); ++ return -1; ++ } ++ + if (!is_same(e1->metric_expr, e2->metric_expr)) { + pr_debug2("testing event e1 %s: mismatched metric_expr, %s vs %s\n", + e1->name, e1->metric_expr, e2->metric_expr); +@@ -297,21 +327,21 @@ static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2) + return -1; + } + +- if (!is_same(e1->deprecated, e2->deprecated)) { +- pr_debug2("testing event e1 %s: mismatched deprecated, %s vs %s\n", +- e1->name, e1->deprecated, e2->deprecated); ++ if (!is_same(e1->metric_group, e2->metric_group)) { ++ pr_debug2("testing event e1 %s: mismatched metric_group, %s vs %s\n", ++ e1->name, e1->metric_group, e2->metric_group); + return -1; + } + +- if (!is_same(e1->pmu, e2->pmu)) { +- pr_debug2("testing event e1 %s: mismatched pmu string, %s vs %s\n", +- e1->name, e1->pmu, e2->pmu); ++ if (!is_same(e1->deprecated, e2->deprecated)) { ++ pr_debug2("testing event e1 %s: mismatched deprecated, %s vs %s\n", ++ e1->name, e1->deprecated, e2->deprecated); + return -1; + } + +- if (!is_same(e1->compat, e2->compat)) { +- pr_debug2("testing event e1 %s: mismatched compat string, %s vs %s\n", +- e1->name, e1->compat, e2->compat); ++ if (!is_same(e1->metric_constraint, e2->metric_constraint)) { ++ pr_debug2("testing event e1 %s: mismatched metric_constant, %s vs %s\n", ++ e1->name, e1->metric_constraint, e2->metric_constraint); + return -1; + } + +-- +2.27.0 + diff --git a/patches/0302-perf-vendor-events-arm64-Revise-hip08-uncore-events.patch b/patches/0302-perf-vendor-events-arm64-Revise-hip08-uncore-events.patch new file mode 100644 index 0000000..b4dc423 --- /dev/null +++ b/patches/0302-perf-vendor-events-arm64-Revise-hip08-uncore-events.patch @@ -0,0 +1,435 @@ +From 0f4c25291a6aad9a8e71c63f3c59830b5cbe6a89 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 16 Sep 2021 20:34:25 +0800 +Subject: [PATCH 185/201] perf vendor events arm64: Revise hip08 uncore events + +mainline inclusion +from mainline-v5.16-rc1 +commit c801612875909cbce823dfc276c58c7155f95b01 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c801612875909cbce823dfc276c58c7155f95b01 + +---------------------------------------------------------------------- + +To improve alias matching, remove the PMU name prefix from the +EventName. This will mean that the pmu code will merge aliases, such +that we no longer get a huge list of per-PMU events - see +perf_pmu_merge_alias(). + +Also make the following associated changes: + +- Use "ConfigCode" rather than "EventCode", so the pmu code is not so + disagreeable about inconsistent event codes + +- Add undocumented HHA event codes to allow alias merging (for those + events) + +Signed-off-by: John Garry +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Leo Yan +Cc: Mark Rutland +Cc: Mathieu Poirier +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxarm@huawei.com +Cc: liuqi115@huawei.com +Link: https://lore.kernel.org/r/1631795665-240946-6-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +--- + .../arm64/hisilicon/hip08/uncore-ddrc.json | 32 ++--- + .../arm64/hisilicon/hip08/uncore-hha.json | 122 +++++++++++++++--- + .../arm64/hisilicon/hip08/uncore-l3c.json | 52 ++++---- + 3 files changed, 143 insertions(+), 63 deletions(-) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +index 7da86942dae2..c937c3de1409 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-ddrc.json +@@ -1,56 +1,56 @@ + [ + { +- "EventCode": "0x00", +- "EventName": "uncore_hisi_ddrc.flux_wr", ++ "ConfigCode": "0x00", ++ "EventName": "flux_wr", + "BriefDescription": "DDRC total write operations", + "PublicDescription": "DDRC total write operations", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x01", +- "EventName": "uncore_hisi_ddrc.flux_rd", ++ "ConfigCode": "0x01", ++ "EventName": "flux_rd", + "BriefDescription": "DDRC total read operations", + "PublicDescription": "DDRC total read operations", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x02", +- "EventName": "uncore_hisi_ddrc.flux_wcmd", ++ "ConfigCode": "0x02", ++ "EventName": "flux_wcmd", + "BriefDescription": "DDRC write commands", + "PublicDescription": "DDRC write commands", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x03", +- "EventName": "uncore_hisi_ddrc.flux_rcmd", ++ "ConfigCode": "0x03", ++ "EventName": "flux_rcmd", + "BriefDescription": "DDRC read commands", + "PublicDescription": "DDRC read commands", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x04", +- "EventName": "uncore_hisi_ddrc.pre_cmd", ++ "ConfigCode": "0x04", ++ "EventName": "pre_cmd", + "BriefDescription": "DDRC precharge commands", + "PublicDescription": "DDRC precharge commands", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x05", +- "EventName": "uncore_hisi_ddrc.act_cmd", ++ "ConfigCode": "0x05", ++ "EventName": "act_cmd", + "BriefDescription": "DDRC active commands", + "PublicDescription": "DDRC active commands", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x06", +- "EventName": "uncore_hisi_ddrc.rnk_chg", ++ "ConfigCode": "0x06", ++ "EventName": "rnk_chg", + "BriefDescription": "DDRC rank commands", + "PublicDescription": "DDRC rank commands", + "Unit": "hisi_sccl,ddrc", + }, + { +- "EventCode": "0x07", +- "EventName": "uncore_hisi_ddrc.rw_chg", ++ "ConfigCode": "0x07", ++ "EventName": "rw_chg", + "BriefDescription": "DDRC read and write changes", + "PublicDescription": "DDRC read and write changes", + "Unit": "hisi_sccl,ddrc", +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +index 3be418a248ea..364914a0e99d 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-hha.json +@@ -1,72 +1,152 @@ + [ + { +- "EventCode": "0x00", +- "EventName": "uncore_hisi_hha.rx_ops_num", ++ "ConfigCode": "0x00", ++ "EventName": "rx_ops_num", + "BriefDescription": "The number of all operations received by the HHA", + "PublicDescription": "The number of all operations received by the HHA", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x01", +- "EventName": "uncore_hisi_hha.rx_outer", ++ "ConfigCode": "0x01", ++ "EventName": "rx_outer", + "BriefDescription": "The number of all operations received by the HHA from another socket", + "PublicDescription": "The number of all operations received by the HHA from another socket", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x02", +- "EventName": "uncore_hisi_hha.rx_sccl", ++ "ConfigCode": "0x02", ++ "EventName": "rx_sccl", + "BriefDescription": "The number of all operations received by the HHA from another SCCL in this socket", + "PublicDescription": "The number of all operations received by the HHA from another SCCL in this socket", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x03", +- "EventName": "uncore_hisi_hha.rx_ccix", ++ "ConfigCode": "0x03", ++ "EventName": "rx_ccix", + "BriefDescription": "Count of the number of operations that HHA has received from CCIX", + "PublicDescription": "Count of the number of operations that HHA has received from CCIX", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x1c", +- "EventName": "uncore_hisi_hha.rd_ddr_64b", ++ "ConfigCode": "0x4", ++ "EventName": "rx_wbi", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x5", ++ "EventName": "rx_wbip", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x11", ++ "EventName": "rx_wtistash", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x1c", ++ "EventName": "rd_ddr_64b", + "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 64 bytes", + "PublicDescription": "The number of read operations sent by HHA to DDRC which size is 64bytes", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x1d", +- "EventName": "uncore_hisi_hha.wr_ddr_64b", ++ "ConfigCode": "0x1d", ++ "EventName": "wr_ddr_64b", + "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", + "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x1e", +- "EventName": "uncore_hisi_hha.rd_ddr_128b", ++ "ConfigCode": "0x1e", ++ "EventName": "rd_ddr_128b", + "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes", + "PublicDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x1f", +- "EventName": "uncore_hisi_hha.wr_ddr_128b", ++ "ConfigCode": "0x1f", ++ "EventName": "wr_ddr_128b", + "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", + "PublicDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x20", +- "EventName": "uncore_hisi_hha.spill_num", ++ "ConfigCode": "0x20", ++ "EventName": "spill_num", + "BriefDescription": "Count of the number of spill operations that the HHA has sent", + "PublicDescription": "Count of the number of spill operations that the HHA has sent", + "Unit": "hisi_sccl,hha", + }, + { +- "EventCode": "0x21", +- "EventName": "uncore_hisi_hha.spill_success", ++ "ConfigCode": "0x21", ++ "EventName": "spill_success", + "BriefDescription": "Count of the number of successful spill operations that the HHA has sent", + "PublicDescription": "Count of the number of successful spill operations that the HHA has sent", +- "Unit": "hisi_sccl,hha", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x23", ++ "EventName": "bi_num", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x32", ++ "EventName": "mediated_num", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x33", ++ "EventName": "tx_snp_num", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x34", ++ "EventName": "tx_snp_outer", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x35", ++ "EventName": "tx_snp_ccix", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x38", ++ "EventName": "rx_snprspdata", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x3c", ++ "EventName": "rx_snprsp_outer", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x40", ++ "EventName": "sdir-lookup", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x41", ++ "EventName": "edir-lookup", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x42", ++ "EventName": "sdir-hit", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x43", ++ "EventName": "edir-hit", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "ConfigCode": "0x4c", ++ "EventName": "sdir-home-migrate", ++ "Unit": "hisi_sccl,hha" + }, ++ { ++ "ConfigCode": "0x4d", ++ "EventName": "edir-home-migrate", ++ "Unit": "hisi_sccl,hha" ++ } + ] +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +index f463d0acfaef..b448caddf1ae 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/uncore-l3c.json +@@ -1,91 +1,91 @@ + [ + { +- "EventCode": "0x00", +- "EventName": "uncore_hisi_l3c.rd_cpipe", ++ "ConfigCode": "0x00", ++ "EventName": "rd_cpipe", + "BriefDescription": "Total read accesses", + "PublicDescription": "Total read accesses", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x01", +- "EventName": "uncore_hisi_l3c.wr_cpipe", ++ "ConfigCode": "0x01", ++ "EventName": "wr_cpipe", + "BriefDescription": "Total write accesses", + "PublicDescription": "Total write accesses", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x02", +- "EventName": "uncore_hisi_l3c.rd_hit_cpipe", ++ "ConfigCode": "0x02", ++ "EventName": "rd_hit_cpipe", + "BriefDescription": "Total read hits", + "PublicDescription": "Total read hits", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x03", +- "EventName": "uncore_hisi_l3c.wr_hit_cpipe", ++ "ConfigCode": "0x03", ++ "EventName": "wr_hit_cpipe", + "BriefDescription": "Total write hits", + "PublicDescription": "Total write hits", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x04", +- "EventName": "uncore_hisi_l3c.victim_num", ++ "ConfigCode": "0x04", ++ "EventName": "victim_num", + "BriefDescription": "l3c precharge commands", + "PublicDescription": "l3c precharge commands", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x20", +- "EventName": "uncore_hisi_l3c.rd_spipe", ++ "ConfigCode": "0x20", ++ "EventName": "rd_spipe", + "BriefDescription": "Count of the number of read lines that come from this cluster of CPU core in spipe", + "PublicDescription": "Count of the number of read lines that come from this cluster of CPU core in spipe", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x21", +- "EventName": "uncore_hisi_l3c.wr_spipe", ++ "ConfigCode": "0x21", ++ "EventName": "wr_spipe", + "BriefDescription": "Count of the number of write lines that come from this cluster of CPU core in spipe", + "PublicDescription": "Count of the number of write lines that come from this cluster of CPU core in spipe", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x22", +- "EventName": "uncore_hisi_l3c.rd_hit_spipe", ++ "ConfigCode": "0x22", ++ "EventName": "rd_hit_spipe", + "BriefDescription": "Count of the number of read lines that hits in spipe of this L3C", + "PublicDescription": "Count of the number of read lines that hits in spipe of this L3C", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x23", +- "EventName": "uncore_hisi_l3c.wr_hit_spipe", ++ "ConfigCode": "0x23", ++ "EventName": "wr_hit_spipe", + "BriefDescription": "Count of the number of write lines that hits in spipe of this L3C", + "PublicDescription": "Count of the number of write lines that hits in spipe of this L3C", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x29", +- "EventName": "uncore_hisi_l3c.back_invalid", ++ "ConfigCode": "0x29", ++ "EventName": "back_invalid", + "BriefDescription": "Count of the number of L3C back invalid operations", + "PublicDescription": "Count of the number of L3C back invalid operations", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x40", +- "EventName": "uncore_hisi_l3c.retry_cpu", ++ "ConfigCode": "0x40", ++ "EventName": "retry_cpu", + "BriefDescription": "Count of the number of retry that L3C suppresses the CPU operations", + "PublicDescription": "Count of the number of retry that L3C suppresses the CPU operations", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x41", +- "EventName": "uncore_hisi_l3c.retry_ring", ++ "ConfigCode": "0x41", ++ "EventName": "retry_ring", + "BriefDescription": "Count of the number of retry that L3C suppresses the ring operations", + "PublicDescription": "Count of the number of retry that L3C suppresses the ring operations", + "Unit": "hisi_sccl,l3c", + }, + { +- "EventCode": "0x42", +- "EventName": "uncore_hisi_l3c.prefetch_drop", ++ "ConfigCode": "0x42", ++ "EventName": "prefetch_drop", + "BriefDescription": "Count of the number of prefetch drops from this L3C", + "PublicDescription": "Count of the number of prefetch drops from this L3C", + "Unit": "hisi_sccl,l3c", +-- +2.27.0 + diff --git a/patches/0303-perf-test-Add-pmu-events-test-for-aliases-of-hip09-d.patch b/patches/0303-perf-test-Add-pmu-events-test-for-aliases-of-hip09-d.patch new file mode 100644 index 0000000..d066250 --- /dev/null +++ b/patches/0303-perf-test-Add-pmu-events-test-for-aliases-of-hip09-d.patch @@ -0,0 +1,89 @@ +From d2e08a5dc3f137d0f4925ed6561d2d82365db0c7 Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Wed, 30 Nov 2022 19:01:35 +0800 +Subject: [PATCH 186/201] perf test: Add pmu-events test for aliases of hip09 + ddrc pmu + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add a test for aliases of hip09 ddrc pmu to ensure that +the pmu-events tables are as expects. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + .../arch/test/test_soc/sys/uncore.json | 8 ++++++ + tools/perf/tests/pmu-events.c | 26 +++++++++++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json +index 0f681a6e10ea..bfe4ea8b46fc 100644 +--- a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json ++++ b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json +@@ -6,4 +6,12 @@ + "Unit": "sys_ddr_pmu", + "Compat": "v8" + }, ++ { ++ "EventCode": "0x84", ++ "EventName": "sys_hisi_ddrc.flux_rd", ++ "BriefDescription": "DDRC read commands", ++ "PublicDescription": "DDRC read commands", ++ "Unit": "sys_hisi_ddrc", ++ "Compat": "hip09" ++ } + ] +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index c9a89c8f4ab1..eac481cd8fbb 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -208,8 +208,24 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = { + .matching_pmu = "uncore_sys_ddr_pmu", + }; + ++static const struct perf_pmu_test_event sys_hisi_ddrc_flux_rd = { ++ .event = { ++ .name = "sys_hisi_ddrc.flux_rd", ++ .event = "event=0x84", ++ .desc = "DDRC read commands. Unit: uncore_sys_hisi_ddrc ", ++ .topic = "uncore", ++ .long_desc = "DDRC read commands", ++ .pmu = "uncore_sys_hisi_ddrc", ++ .compat = "hip09", ++ }, ++ .alias_str = "event=0x84", ++ .alias_long_desc = "DDRC read commands", ++ .matching_pmu = "uncore_sys_hisi_ddrc_0", ++}; ++ + static const struct perf_pmu_test_event *sys_events[] = { + &sys_ddr_pmu_write_cycles, ++ &sys_hisi_ddrc_flux_rd, + NULL + }; + +@@ -677,6 +693,16 @@ static struct perf_pmu_test_pmu test_pmus[] = { + &sys_ddr_pmu_write_cycles, + }, + }, ++ { ++ .pmu = { ++ .name = (char *)"uncore_sys_hisi_ddrc_0", ++ .is_uncore = 1, ++ .id = (char *)"hip09", ++ }, ++ .aliases = { ++ &sys_hisi_ddrc_flux_rd, ++ }, ++ }, + }; + + /* Test that aliases generated are as expected */ +-- +2.27.0 + diff --git a/patches/0304-perf-jevents-Add-support-for-HiSilicon-L3C-PMU-alias.patch b/patches/0304-perf-jevents-Add-support-for-HiSilicon-L3C-PMU-alias.patch new file mode 100644 index 0000000..707e6a7 --- /dev/null +++ b/patches/0304-perf-jevents-Add-support-for-HiSilicon-L3C-PMU-alias.patch @@ -0,0 +1,157 @@ +From e620ed3caa3c3d5a8cc1b6ff2a9aa49234e34c84 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:36 +0800 +Subject: [PATCH 187/201] perf jevents: Add support for HiSilicon L3C PMU + aliasing + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add support for HiSilicon L3C PMU aliasing on Hip09 platform. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip09/sys/uncore-l3c.json | 125 ++++++++++++++++++ + 1 file changed, 125 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-l3c.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-l3c.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-l3c.json +new file mode 100644 +index 000000000000..46167a2eec51 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-l3c.json +@@ -0,0 +1,125 @@ ++[ ++ { ++ "EventCode": "0x00", ++ "EventName": "rd_cpipe", ++ "BriefDescription": "Total read accesses", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x02", ++ "EventName": "rd_hit_cpipe", ++ "BriefDescription": "Total read hits", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x20", ++ "EventName": "rd_spipe", ++ "BriefDescription": "Count of the number of read lines that come from this cluster of CPU core in spipe", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x22", ++ "EventName": "rd_hit_spipe", ++ "BriefDescription": "Count of the number of read lines that hits in spipe of this L3C", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x29", ++ "EventName": "back_invalid", ++ "BriefDescription": "Count of the number of L3C back invalid operations", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x40", ++ "EventName": "retry_cpu", ++ "BriefDescription": "Count of the number of retry that L3C suppresses the CPU operations", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x41", ++ "EventName": "retry_ring", ++ "BriefDescription": "Count of the number of retry that L3C suppresses the ring operations", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x48", ++ "EventName": "l3c_hit", ++ "BriefDescription": "Count of the total number of L3C hit", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x80", ++ "EventName": "read_sum", ++ "Filter": "tt_core=0xff", ++ "BriefDescription": "total time taken by CPU to read L3C", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0xb8", ++ "EventName": "l3c_ref", ++ "BriefDescription": "Count of the total number of CPU accessed L3C", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0xb9", ++ "EventName": "dat_access", ++ "BriefDescription": "Count of the total number of CPU accessed L3C", ++ "Filter": "tt_core=0xff", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0xc0", ++ "EventName": "read_alloc", ++ "Filter": "tt_core=0xff", ++ "BriefDescription": "Count of the requests issued by CPU received by L3C", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0xce", ++ "EventName": "retry_alloc", ++ "Filter": "tt_core=0xff", ++ "BriefDescription": "Count of the L3C retry CPU", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventCode": "0x7f", ++ "EventName": "l3c_cycles", ++ "BriefDescription": "Count of L3C cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "EventName": "cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "MetricExpr": "l3c_hit / l3c_ref", ++ "BriefDescription": "hit rate of L3C", ++ "Compat": "0x00000030", ++ "MetricGroup": "L3Cache", ++ "MetricName": "l3c_hit_rate", ++ "Unit": "hisi_sccl,l3c" ++ }, ++ { ++ "MetricExpr": "read_sum / (l3c_ref - retry_alloc)", ++ "BriefDescription": "Average latency of CPU reading L3", ++ "Compat": "0x00000030", ++ "MetricGroup": "L3Cache", ++ "MetricName": "l3c_latency", ++ "Unit": "hisi_sccl,l3c" ++ } ++] +\ No newline at end of file +-- +2.27.0 + diff --git a/patches/0305-perf-jevents-Add-support-for-HiSilicon-DDRC-PMU-alia.patch b/patches/0305-perf-jevents-Add-support-for-HiSilicon-DDRC-PMU-alia.patch new file mode 100644 index 0000000..80f201a --- /dev/null +++ b/patches/0305-perf-jevents-Add-support-for-HiSilicon-DDRC-PMU-alia.patch @@ -0,0 +1,149 @@ +From a1a624c9d6f721979646e38d7a841e82ad6f286a Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:37 +0800 +Subject: [PATCH 188/201] perf jevents: Add support for HiSilicon DDRC PMU + aliasing + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add support for HiSilicon DDRC PMU aliasing on Hip09 platform. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + .../hisilicon/hip09/sys/uncore-ddrc.json | 117 ++++++++++++++++++ + 1 file changed, 117 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-ddrc.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-ddrc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-ddrc.json +new file mode 100644 +index 000000000000..4a68a2fdb854 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-ddrc.json +@@ -0,0 +1,117 @@ ++[ ++ { ++ "EventCode": "0x00", ++ "EventName": "ddrc_cycles", ++ "BriefDescription": "Count of DDRC cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventName": "cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x01", ++ "EventName": "act_cnt", ++ "BriefDescription": "count of DDRC active commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x07", ++ "EventName": "priority_cmd", ++ "BriefDescription": "count of DMC commands with the highest priority", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x0b", ++ "EventName": "pre_act", ++ "BriefDescription": "count of DDRC pre-active commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x41", ++ "EventName": "read_cmd", ++ "BriefDescription": "count of DDRC read commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x44", ++ "EventName": "write_cmd", ++ "BriefDescription": "count of DDRC write commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x80", ++ "EventName": "read_cmd_occupancy", ++ "BriefDescription": "count of cycles occupied by the read command in the queue", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x81", ++ "EventName": "write_cmd_occupancy", ++ "BriefDescription": "count of cycles occupied by the write command in the queue", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x83", ++ "EventName": "flux_wr", ++ "BriefDescription": "DDRC write commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "EventCode": "0x84", ++ "EventName": "flux_rd", ++ "BriefDescription": "DDRC read commands", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "MetricExpr": "flux_wr * 32 / duration_time", ++ "BriefDescription": "Average bandwidth of DDRC memory write(Byte/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "DDRC", ++ "MetricName": "ddrc_bw_write", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "MetricExpr": "flux_rd * 32 / duration_time", ++ "BriefDescription": "Average bandwidth of DDRC memory read(Byte/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "DDRC", ++ "MetricName": "ddrc_bw_read", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "MetricExpr": "(flux_wr + flux_rd) * 32 / duration_time", ++ "BriefDescription": "Average bandwidth of DDRC (including memory read and write)(Byte/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "DDRC", ++ "MetricName": "ddrc_bw", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "MetricExpr": "read_cmd_occupancy / read_cmd", ++ "BriefDescription": "Average delay of DDRC read command scheduling", ++ "Compat": "0x00000030", ++ "MetricGroup": "DDRC", ++ "MetricName": "ddrc_read_lat", ++ "Unit": "hisi_sccl,ddrc" ++ }, ++ { ++ "MetricExpr": "write_cmd_occupancy / write_cmd", ++ "BriefDescription": "Average delay of DDRC write command scheduling", ++ "Compat": "0x00000030", ++ "MetricGroup": "DDRC", ++ "MetricName": "ddrc_write_lat", ++ "Unit": "hisi_sccl,ddrc" ++ } ++] +\ No newline at end of file +-- +2.27.0 + diff --git a/patches/0306-perf-jevents-Add-support-for-HiSilicon-HHA-PMU-alias.patch b/patches/0306-perf-jevents-Add-support-for-HiSilicon-HHA-PMU-alias.patch new file mode 100644 index 0000000..d3b4af9 --- /dev/null +++ b/patches/0306-perf-jevents-Add-support-for-HiSilicon-HHA-PMU-alias.patch @@ -0,0 +1,134 @@ +From 8061299b4e8c67438cacec2896d52d7440987798 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:38 +0800 +Subject: [PATCH 189/201] perf jevents: Add support for HiSilicon HHA PMU + aliasing + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add support for HiSilicon HHA PMU aliasing on Hip09 platform. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip09/sys/uncore-hha.json | 102 ++++++++++++++++++ + 1 file changed, 102 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-hha.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-hha.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-hha.json +new file mode 100644 +index 000000000000..e49dceeaa263 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-hha.json +@@ -0,0 +1,102 @@ ++[ ++ { ++ "EventCode": "0x00", ++ "EventName": "rx_ops_num", ++ "BriefDescription": "The number of all operations received by the HHA", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x01", ++ "EventName": "rx_outer", ++ "BriefDescription": "The number of all operations received by the HHA from another socket", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x02", ++ "EventName": "rx_sccl", ++ "BriefDescription": "The number of all operations received by the HHA from another SCCL in this socket", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x1c", ++ "EventName": "rd_ddr_64b", ++ "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 64 bytes", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x1d", ++ "EventName": "wr_ddr_64b", ++ "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x1e", ++ "EventName": "rd_ddr_128b", ++ "BriefDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x1f", ++ "EventName": "wr_ddr_128b", ++ "BriefDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x2e", ++ "EventName": "hha_retry", ++ "BriefDescription": "Count of the HHA retry", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventCode": "0x55", ++ "EventName": "hha_cycles", ++ "BriefDescription": "Count of the HHA cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "EventName": "cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "MetricExpr": "(rd_ddr_64b * 64 + rd_ddr_128b *128) / duration_time", ++ "BriefDescription": "Average bandwidth of reading DDRC(Byte/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "HHA", ++ "MetricName": "hha_read_ddrc_bw", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "MetricExpr": "(wr_ddr_64b * 64 + wr_ddr_128b *128) / duration_time", ++ "BriefDescription": "Average bandwidth of writing DDRC(Byte/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "HHA", ++ "MetricName": "hha_write_ddrc_bw", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "MetricExpr": "rx_outer / rx_ops_num", ++ "BriefDescription": "Rate of cross-chip operations received by HHA", ++ "Compat": "0x00000030", ++ "MetricGroup": "HHA", ++ "MetricName": "cross_chip_ops_rate", ++ "Unit": "hisi_sccl,hha" ++ }, ++ { ++ "MetricExpr": "rx_sccl / rx_ops_num", ++ "BriefDescription": "Rate of cross-die operations received by HHA", ++ "Compat": "0x00000030", ++ "MetricGroup": "HHA", ++ "MetricName": "cross_die_ops_rate", ++ "Unit": "hisi_sccl,hha" ++ } ++] +\ No newline at end of file +-- +2.27.0 + diff --git a/patches/0307-perf-jevents-Add-support-for-HiSilicon-SLLC-PMU-alia.patch b/patches/0307-perf-jevents-Add-support-for-HiSilicon-SLLC-PMU-alia.patch new file mode 100644 index 0000000..83879fc --- /dev/null +++ b/patches/0307-perf-jevents-Add-support-for-HiSilicon-SLLC-PMU-alia.patch @@ -0,0 +1,182 @@ +From 9f42a499f9c817c79dda47774a121a1b3dcd47e3 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:39 +0800 +Subject: [PATCH 190/201] perf jevents: Add support for HiSilicon SLLC PMU + aliasing + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add support for HiSilicon SLLC PMU aliasing on Hip09 platform. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/pmu-events/jevents.c +--- + .../hisilicon/hip09/sys/uncore-sllc.json | 134 ++++++++++++++++++ + tools/perf/pmu-events/jevents.c | 1 + + 2 files changed, 135 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-sllc.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-sllc.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-sllc.json +new file mode 100644 +index 000000000000..3f62cb0c791d +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-sllc.json +@@ -0,0 +1,134 @@ ++[ ++ { ++ "EventCode": "0x09", ++ "EventName": "sllc_cycles", ++ "BriefDescription": "Count of SLLC cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventName": "cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x20", ++ "EventName": "rx_req_sum", ++ "BriefDescription": "total cycles SLLC taken to receive requests", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x21", ++ "EventName": "rx_data_sum", ++ "BriefDescription": "total cycles SLLC taken to receive data", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x24", ++ "EventName": "tx_req_sum", ++ "BriefDescription": "total cycles SLLC taken to transmit requests", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x25", ++ "EventName": "tx_data_sum", ++ "BriefDescription": "total cycles SLLC taken to transmit data", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x30", ++ "EventName": "rx_req", ++ "BriefDescription": "Count of the requests received by SLLC", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x31", ++ "EventName": "rx_data", ++ "BriefDescription": "Count of the data received by SLLC", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x34", ++ "EventName": "tx_req", ++ "BriefDescription": "Count of the requests transmitted by SLLC", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "EventCode": "0x35", ++ "EventName": "tx_data", ++ "BriefDescription": "Count of the data transmitted by SLLC", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "rx_req_sum / rx_req", ++ "BriefDescription": "Average latency of SLLC receive requests(cycles)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_rx_req_lat", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "rx_data_sum / rx_data", ++ "BriefDescription": "Average latency of SLLC receive data(cycles)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_rx_data_lat", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "tx_req_sum / tx_req", ++ "BriefDescription": "Average latency of SLLC transmit requests(cycles)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_tx_req_lat", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "tx_data_sum / tx_data", ++ "BriefDescription": "Average latency of SLLC transmit data(cycles)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_tx_data_lat", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "rx_req * 332 / duration_time", ++ "BriefDescription": "Average bandwidth of SLLC receive requests(bits/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_rx_req_bw", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "rx_data * 332 / duration_time", ++ "BriefDescription": "Average bandwidth of SLLC receive data(bits/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_rx_data_bw", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "tx_req * 332 / duration_time", ++ "BriefDescription": "Average bandwidth of SLLC transmit requests(bits/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_tx_req_bw", ++ "Unit": "hisi_sccl,sllc" ++ }, ++ { ++ "MetricExpr": "tx_data * 332 / duration_time", ++ "BriefDescription": "Average bandwidth of SLLC transmit data(bits/s)", ++ "Compat": "0x00000030", ++ "MetricGroup": "SLLC", ++ "MetricName": "sllc_tx_data_bw", ++ "Unit": "hisi_sccl,sllc" ++ } ++] +\ No newline at end of file +diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c +index b330c244f076..26275543840e 100644 +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -283,6 +283,7 @@ static struct map { + { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, + { "hisi_sccl,hha", "hisi_sccl,hha" }, + { "hisi_sccl,l3c", "hisi_sccl,l3c" }, ++ { "hisi_sccl,sllc", "hisi_sccl,sllc" }, + {} + }; + +-- +2.27.0 + diff --git a/patches/0308-perf-jevents-Add-support-for-HiSilicon-PA-PMU-aliasi.patch b/patches/0308-perf-jevents-Add-support-for-HiSilicon-PA-PMU-aliasi.patch new file mode 100644 index 0000000..d1c088d --- /dev/null +++ b/patches/0308-perf-jevents-Add-support-for-HiSilicon-PA-PMU-aliasi.patch @@ -0,0 +1,118 @@ +From f3e508aa850b99ecc2432bf2a34a28f12f4ebc28 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Wed, 30 Nov 2022 19:01:40 +0800 +Subject: [PATCH 191/201] perf jevents: Add support for HiSilicon PA PMU + aliasing + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 + +-------------------------------------------------------------------------- + +Add support for HiSilicon PA PMU aliasing on Hip09 platform. + +Signed-off-by: Qi Liu +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + .../arm64/hisilicon/hip09/sys/uncore-pa.json | 86 +++++++++++++++++++ + 1 file changed, 86 insertions(+) + create mode 100644 tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-pa.json + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-pa.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-pa.json +new file mode 100644 +index 000000000000..6ddc9b4ffa16 +--- /dev/null ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip09/sys/uncore-pa.json +@@ -0,0 +1,86 @@ ++[ ++ { ++ "EventCode": "0x78", ++ "EventName": "pa_cycles", ++ "BriefDescription": "Count of PA cycles", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventName": "cycle", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x40", ++ "EventName": "rx_req", ++ "BriefDescription": "Count of the requests received by PA link0", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x41", ++ "EventName": "rx_req_link1", ++ "BriefDescription": "Count of the requests received by PA link1", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x42", ++ "EventName": "rx_req_link2", ++ "BriefDescription": "Count of the requests received by PA link2", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x43", ++ "EventName": "rx_req_link3", ++ "BriefDescription": "Count of the requests received by PA link3", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x5c", ++ "EventName": "tx_req", ++ "BriefDescription": "Count of the requests transmitted by PA link0", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x5d", ++ "EventName": "tx_req_link1", ++ "BriefDescription": "Count of the requests transmitted by PA link1", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x5e", ++ "EventName": "tx_req_link2", ++ "BriefDescription": "Count of the requests transmitted by PA link2", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "EventCode": "0x5f", ++ "EventName": "tx_req_link3", ++ "BriefDescription": "Count of the requests transmitted by PA link3", ++ "Compat": "0x00000030", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "MetricExpr": "(rx_req + rx_req_link1 + rx_req_link2 + rx_req_link3) / duration_time", ++ "BriefDescription": "Average bandwidth of PA receive requests", ++ "Compat": "0x00000030", ++ "MetricGroup": "PA", ++ "MetricName": "pa_rx_req_bw", ++ "Unit": "hisi_sicl,pa" ++ }, ++ { ++ "MetricExpr": "(tx_req + tx_req_link1 + tx_req_link2 + tx_req_link3) / duration_time", ++ "BriefDescription": "Average bandwidth of PA transmitted requests", ++ "Compat": "0x00000030", ++ "MetricGroup": "PA", ++ "MetricName": "pa_tx_req_bw", ++ "Unit": "hisi_sicl,pa" ++ } ++] +\ No newline at end of file +-- +2.27.0 + diff --git a/patches/0309-perf-expr-Test-parsing-of-floating-point-numbers.patch b/patches/0309-perf-expr-Test-parsing-of-floating-point-numbers.patch new file mode 100644 index 0000000..49409c2 --- /dev/null +++ b/patches/0309-perf-expr-Test-parsing-of-floating-point-numbers.patch @@ -0,0 +1,55 @@ +From b79ccba00ace3e843109aad2133e35c187827795 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Tue, 12 May 2020 23:27:51 -0700 +Subject: [PATCH 192/201] perf expr: Test parsing of floating point numbers + +mainline inclusion +from mainline-v5.8-rc1 +commit 63f11355a6ee7febc7b3fdad8a7009c0e16748df +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=63f11355a6ee7febc7b3fdad8a7009c0e16748df + +---------------------------------------------------------------------- + +Add test for fix in: +commit 5741da3dee4c ("perf expr: Parse numbers as doubles") + +Signed-off-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Jin Yao +Cc: Jiri Olsa +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Link: http://lore.kernel.org/lkml/20200513062752.3681-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 992b7546b9da..9f7d8ee21d89 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -36,6 +36,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + ret |= test(&ctx, "min(1,2) + 1", 2); + ret |= test(&ctx, "max(1,2) + 1", 3); + ret |= test(&ctx, "1+1 if 3*4 else 0", 2); ++ ret |= test(&ctx, "1.1 + 2.1", 3.2); + + if (ret) + return ret; +-- +2.27.0 + diff --git a/patches/0310-perf-expr-Allow-numbers-to-be-followed-by-a-dot.patch b/patches/0310-perf-expr-Allow-numbers-to-be-followed-by-a-dot.patch new file mode 100644 index 0000000..ba9045d --- /dev/null +++ b/patches/0310-perf-expr-Allow-numbers-to-be-followed-by-a-dot.patch @@ -0,0 +1,69 @@ +From eecee160cb9f45894e29222adeb5e027dd2faa5f Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Tue, 19 May 2020 23:36:52 -0700 +Subject: [PATCH 193/201] perf expr: Allow numbers to be followed by a dot + +mainline inclusion +from mainline-v5.8-rc1 +commit a45badc7392b4613708748f6a2cc0c6f63a1c8d6 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a45badc7392b4613708748f6a2cc0c6f63a1c8d6 + +---------------------------------------------------------------------- + +Metrics like UNC_M_POWER_SELF_REFRESH encode 100 as "100." and +consequently the 100 is treated as a symbol. Alter the regular +expression to allow the dot to be before or after the number. + +Note, this passed the pmu-events test as that tests the validity of a +number using strtod rather than lex code. strtod allows the dot after. + +Add a test for this behavior. + +Fixes: 26226a97724d (perf expr: Move expr lexer to flex) +Signed-off-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: John Garry +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Paul Clarke +Cc: Peter Zijlstra +Cc: Stephane Eranian +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/expr.c | 1 + + tools/perf/util/expr.l | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c +index 9f7d8ee21d89..576bd4af5720 100644 +--- a/tools/perf/tests/expr.c ++++ b/tools/perf/tests/expr.c +@@ -37,6 +37,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) + ret |= test(&ctx, "max(1,2) + 1", 3); + ret |= test(&ctx, "1+1 if 3*4 else 0", 2); + ret |= test(&ctx, "1.1 + 2.1", 3.2); ++ ret |= test(&ctx, ".1 + 2.", 2.1); + + if (ret) + return ret; +diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l +index ceab11bea6f9..f397bf8b1a48 100644 +--- a/tools/perf/util/expr.l ++++ b/tools/perf/util/expr.l +@@ -81,7 +81,7 @@ static int str(yyscan_t scanner, int token, int runtime) + } + %} + +-number [0-9]*\.?[0-9]+ ++number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+) + + sch [-,=] + spec \\{sch} +-- +2.27.0 + diff --git a/patches/0311-perf-test-Set-NULL-sentinel-in-pmu_events-table-in-P.patch b/patches/0311-perf-test-Set-NULL-sentinel-in-pmu_events-table-in-P.patch new file mode 100644 index 0000000..42d89f0 --- /dev/null +++ b/patches/0311-perf-test-Set-NULL-sentinel-in-pmu_events-table-in-P.patch @@ -0,0 +1,209 @@ +From b88d0132fc745cfa3026df8c404e75796ebd69f2 Mon Sep 17 00:00:00 2001 +From: Thomas Richter +Date: Tue, 25 Aug 2020 09:12:11 +0200 +Subject: [PATCH 194/201] perf test: Set NULL sentinel in pmu_events table in + "Parse and process metrics" test + +mainline inclusion +from mainline-v5.9-rc4 +commit 492d4d876c293e64266222ecec0573103dfc2625 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=492d4d876c293e64266222ecec0573103dfc2625 + +---------------------------------------------------------------------- + +Linux 5.9 introduced perf test case "Parse and process metrics" and +on s390 this test case always dumps core: + + [root@t35lp67 perf]# ./perf test -vvvv -F 67 + 67: Parse and process metrics : + --- start --- + metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC + parsing metric: inst_retired.any / cpu_clk_unhalted.thread + Segmentation fault (core dumped) + [root@t35lp67 perf]# + +I debugged this core dump and gdb shows this call chain: + + (gdb) where + #0 0x000003ffabc3192a in __strnlen_c_1 () from /lib64/libc.so.6 + #1 0x000003ffabc293de in strcasestr () from /lib64/libc.so.6 + #2 0x0000000001102ba2 in match_metric(list=0x1e6ea20 "inst_retired.any", + n=) + at util/metricgroup.c:368 + #3 find_metric (map=, map=, + metric=0x1e6ea20 "inst_retired.any") + at util/metricgroup.c:765 + #4 __resolve_metric (ids=0x0, map=, metric_list=0x0, + metric_no_group=, m=) + at util/metricgroup.c:844 + #5 resolve_metric (ids=0x0, map=0x0, metric_list=0x0, + metric_no_group=) + at util/metricgroup.c:881 + #6 metricgroup__add_metric (metric=, + metric_no_group=metric_no_group@entry=false, events=, + events@entry=0x3ffd84fb878, metric_list=0x0, + metric_list@entry=0x3ffd84fb868, map=0x0) + at util/metricgroup.c:943 + #7 0x00000000011034ae in metricgroup__add_metric_list (map=0x13f9828 , + metric_list=0x3ffd84fb868, events=0x3ffd84fb878, + metric_no_group=, list=) + at util/metricgroup.c:988 + #8 parse_groups (perf_evlist=perf_evlist@entry=0x1e70260, + str=str@entry=0x12f34b2 "IPC", metric_no_group=, + metric_no_merge=, + fake_pmu=fake_pmu@entry=0x1462f18 , + metric_events=0x3ffd84fba58, map=0x1) + at util/metricgroup.c:1040 + #9 0x0000000001103eb2 in metricgroup__parse_groups_test( + evlist=evlist@entry=0x1e70260, map=map@entry=0x13f9828 , + str=str@entry=0x12f34b2 "IPC", + metric_no_group=metric_no_group@entry=false, + metric_no_merge=metric_no_merge@entry=false, + metric_events=0x3ffd84fba58) + at util/metricgroup.c:1082 + #10 0x00000000010c84d8 in __compute_metric (ratio2=0x0, name2=0x0, + ratio1=, name1=0x12f34b2 "IPC", + vals=0x3ffd84fbad8, name=0x12f34b2 "IPC") + at tests/parse-metric.c:159 + #11 compute_metric (ratio=, vals=0x3ffd84fbad8, + name=0x12f34b2 "IPC") + at tests/parse-metric.c:189 + #12 test_ipc () at tests/parse-metric.c:208 +..... +..... omitted many more lines + +This test case was added with +commit 218ca91df477 ("perf tests: Add parse metric test for frontend metric"). + +When I compile with make DEBUG=y it works fine and I do not get a core dump. + +It turned out that the above listed function call chain worked on a struct +pmu_event array which requires a trailing element with zeroes which was +missing. The marco map_for_each_event() loops over that array tests for members +metric_expr/metric_name/metric_group being non-NULL. Adding this element fixes +the issue. + +Output after: + + [root@t35lp46 perf]# ./perf test 67 + 67: Parse and process metrics : Ok + [root@t35lp46 perf]# + +Committer notes: + +As Ian remarks, this is not s390 specific: + + + This also shows up with address sanitizer on all architectures + (perhaps change the patch title) and perhaps add a "Fixes: " + tag. + + ================================================================= + ==4718==ERROR: AddressSanitizer: global-buffer-overflow on address + 0x55c93b4d59e8 at pc 0x55c93a1541e2 bp 0x7ffd24327c60 sp + 0x7ffd24327c58 + READ of size 8 at 0x55c93b4d59e8 thread T0 + #0 0x55c93a1541e1 in find_metric tools/perf/util/metricgroup.c:764:2 + #1 0x55c93a153e6c in __resolve_metric tools/perf/util/metricgroup.c:844:9 + #2 0x55c93a152f18 in resolve_metric tools/perf/util/metricgroup.c:881:9 + #3 0x55c93a1528db in metricgroup__add_metric + tools/perf/util/metricgroup.c:943:9 + #4 0x55c93a151996 in metricgroup__add_metric_list + tools/perf/util/metricgroup.c:988:9 + #5 0x55c93a1511b9 in parse_groups tools/perf/util/metricgroup.c:1040:8 + #6 0x55c93a1513e1 in metricgroup__parse_groups_test + tools/perf/util/metricgroup.c:1082:9 + #7 0x55c93a0108ae in __compute_metric tools/perf/tests/parse-metric.c:159:8 + #8 0x55c93a010744 in compute_metric tools/perf/tests/parse-metric.c:189:9 + #9 0x55c93a00f5ee in test_ipc tools/perf/tests/parse-metric.c:208:2 + #10 0x55c93a00f1e8 in test__parse_metric + tools/perf/tests/parse-metric.c:345:2 + #11 0x55c939fd7202 in run_test tools/perf/tests/builtin-test.c:410:9 + #12 0x55c939fd6736 in test_and_print tools/perf/tests/builtin-test.c:440:9 + #13 0x55c939fd58c3 in __cmd_test tools/perf/tests/builtin-test.c:661:4 + #14 0x55c939fd4e02 in cmd_test tools/perf/tests/builtin-test.c:807:9 + #15 0x55c939e4763d in run_builtin tools/perf/perf.c:313:11 + #16 0x55c939e46475 in handle_internal_command tools/perf/perf.c:365:8 + #17 0x55c939e4737e in run_argv tools/perf/perf.c:409:2 + #18 0x55c939e45f7e in main tools/perf/perf.c:539:3 + + 0x55c93b4d59e8 is located 0 bytes to the right of global variable + 'pme_test' defined in 'tools/perf/tests/parse-metric.c:17:25' + (0x55c93b4d54a0) of size 1352 + SUMMARY: AddressSanitizer: global-buffer-overflow + tools/perf/util/metricgroup.c:764:2 in find_metric + Shadow bytes around the buggy address: + 0x0ab9a7692ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0ab9a7692af0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0ab9a7692b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0ab9a7692b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0ab9a7692b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + =>0x0ab9a7692b30: 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9 f9 + 0x0ab9a7692b40: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 + 0x0ab9a7692b50: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 + 0x0ab9a7692b60: f9 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00 + 0x0ab9a7692b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0ab9a7692b80: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 + Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + Shadow gap: cc + + +I'm also adding the missing "Fixes" tag and setting just .name to NULL, +as doing it that way is more compact (the compiler will zero out +everything else) and the table iterators look for .name being NULL as +the sentinel marking the end of the table. + +Fixes: 0a507af9c681ac2a ("perf tests: Add parse metric test for ipc metric") +Signed-off-by: Thomas Richter +Reviewed-by: Sumanth Korikkar +Acked-by: Ian Rogers +Cc: Heiko Carstens +Cc: Jiri Olsa +Cc: Namhyung Kim +Cc: Sven Schnelle +Cc: Vasily Gorbik +Link: http://lore.kernel.org/lkml/20200825071211.16959-1-tmricht@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/parse-metric.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 936953991347..483271895815 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -68,6 +68,9 @@ static struct pmu_event pme_test[] = { + { + .metric_expr = "1/m3", + .metric_name = "M3", ++}, ++{ ++ .name = NULL, + } + }; + +-- +2.27.0 + diff --git a/patches/0312-perf-test-Fix-msan-uninitialized-use.patch b/patches/0312-perf-test-Fix-msan-uninitialized-use.patch new file mode 100644 index 0000000..7142c74 --- /dev/null +++ b/patches/0312-perf-test-Fix-msan-uninitialized-use.patch @@ -0,0 +1,77 @@ +From d70a55abc4d87a2e54dbb1dd7e53fae51107f647 Mon Sep 17 00:00:00 2001 +From: Ian Rogers +Date: Wed, 23 Sep 2020 14:06:55 -0700 +Subject: [PATCH 195/201] perf test: Fix msan uninitialized use. + +mainline inclusion +from mainline-v5.10-rc1 +commit a55b7bb1c14662490689e094964ecc5387bb2b55 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a55b7bb1c14662490689e094964ecc5387bb2b55 + +---------------------------------------------------------------------- + +Ensure 'st' is initialized before an error branch is taken. +Fixes test "67: Parse and process metrics" with LLVM msan: + + ==6757==WARNING: MemorySanitizer: use-of-uninitialized-value + #0 0x5570edae947d in rblist__exit tools/perf/util/rblist.c:114:2 + #1 0x5570edb1c6e8 in runtime_stat__exit tools/perf/util/stat-shadow.c:141:2 + #2 0x5570ed92cfae in __compute_metric tools/perf/tests/parse-metric.c:187:2 + #3 0x5570ed92cb74 in compute_metric tools/perf/tests/parse-metric.c:196:9 + #4 0x5570ed92c6d8 in test_recursion_fail tools/perf/tests/parse-metric.c:318:2 + #5 0x5570ed92b8c8 in test__parse_metric tools/perf/tests/parse-metric.c:356:2 + #6 0x5570ed8de8c1 in run_test tools/perf/tests/builtin-test.c:410:9 + #7 0x5570ed8ddadf in test_and_print tools/perf/tests/builtin-test.c:440:9 + #8 0x5570ed8dca04 in __cmd_test tools/perf/tests/builtin-test.c:661:4 + #9 0x5570ed8dbc07 in cmd_test tools/perf/tests/builtin-test.c:807:9 + #10 0x5570ed7326cc in run_builtin tools/perf/perf.c:313:11 + #11 0x5570ed731639 in handle_internal_command tools/perf/perf.c:365:8 + #12 0x5570ed7323cd in run_argv tools/perf/perf.c:409:2 + #13 0x5570ed731076 in main tools/perf/perf.c:539:3 + +Fixes: commit f5a56570a3f2 ("perf test: Fix memory leaks in parse-metric test") +Signed-off-by: Ian Rogers +Reviewed-by: Nick Desaulniers +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: clang-built-linux@googlegroups.com +Link: http://lore.kernel.org/lkml/20200923210655.4143682-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/tests/parse-metric.c +--- + tools/perf/tests/parse-metric.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c +index 483271895815..7d63eaa592e2 100644 +--- a/tools/perf/tests/parse-metric.c ++++ b/tools/perf/tests/parse-metric.c +@@ -157,6 +157,7 @@ static int __compute_metric(const char *name, struct value *vals, + } + + perf_evlist__set_maps(evlist, cpus, NULL); ++ runtime_stat__init(&st); + + /* Parse the metric into metric_events list. */ + err = metricgroup__parse_groups_test(evlist, &map, name, +@@ -170,7 +171,6 @@ static int __compute_metric(const char *name, struct value *vals, + goto out; + + /* Load the runtime stats with given numbers for events. */ +- runtime_stat__init(&st); + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ +-- +2.27.0 + diff --git a/patches/0313-perf-test-Fix-metric-parsing-test.patch b/patches/0313-perf-test-Fix-metric-parsing-test.patch new file mode 100644 index 0000000..d2367c0 --- /dev/null +++ b/patches/0313-perf-test-Fix-metric-parsing-test.patch @@ -0,0 +1,84 @@ +From e0558b25b65b152b33604886040f6dab143e4258 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 19 Nov 2020 20:54:11 +0530 +Subject: [PATCH 196/201] perf test: Fix metric parsing test + +mainline inclusion +from mainline-v5.11-rc1 +commit b2ce5dbc15819ea4bef47dbd368239cb1e965158 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b2ce5dbc15819ea4bef47dbd368239cb1e965158 + +---------------------------------------------------------------------- + +Commit e1c92a7fbbc5 ("perf tests: Add another metric parsing test") add +another test for metric parsing. The test goes through all metrics +compiled for arch within pmu events and try to parse them. + +Right now this test is failing in powerpc machine. + +Result in power9 platform: + + [command]# ./perf test 10 + 10: PMU events : + 10.1: PMU event table sanity : Ok + 10.2: PMU event map aliases : Ok + 10.3: Parsing of PMU event table metrics : Skip (some metrics failed) + 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! + +Issue is we are passing different runtime parameter value in +"expr__find_other" and "expr__parse" function which is called from +function `metric_parse_fake`. And because of this parsing of hv-24x7 +metrics is failing. + + [command]# ./perf test 10 -vv + ..... + hv_24x7/pm_mcs01_128b_rd_disp_port01,chip=1/ not found + expr__parse failed + test child finished with -1 + ---- end ---- + PMU events subtest 4: FAILED! + +This patch fix this issue and change runtime parameter value to '0' in +expr__parse function. + +Result in power9 platform after this patch: + + [command]# ./perf test 10 + 10: PMU events : + 10.1: PMU event table sanity : Ok + 10.2: PMU event map aliases : Ok + 10.3: Parsing of PMU event table metrics : Skip (some metrics failed) + 10.4: Parsing of PMU event table metrics with fake PMUs : Ok + +Fixes: e1c92a7fbbc5 ("perf tests: Add another metric parsing test") +Signed-off-by: Kajol Jain +Acked-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Madhavan Srinivasan +Cc: Ravi Bangoria +Link: http://lore.kernel.org/lkml/20201119152411.46041-1-kjain@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/tests/pmu-events.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c +index eac481cd8fbb..46d9288bd020 100644 +--- a/tools/perf/tests/pmu-events.c ++++ b/tools/perf/tests/pmu-events.c +@@ -999,7 +999,7 @@ static int metric_parse_fake(const char *str) + } + } + +- if (expr__parse(&result, &ctx, str, 1)) ++ if (expr__parse(&result, &ctx, str, 0)) + pr_err("expr__parse failed\n"); + else + ret = 0; +-- +2.27.0 + diff --git a/patches/0314-perf-vendor-events-arm64-Fix-incorrect-Hisi-hip08-L3.patch b/patches/0314-perf-vendor-events-arm64-Fix-incorrect-Hisi-hip08-L3.patch new file mode 100644 index 0000000..15e760b --- /dev/null +++ b/patches/0314-perf-vendor-events-arm64-Fix-incorrect-Hisi-hip08-L3.patch @@ -0,0 +1,91 @@ +From 7c1df98efe5f653283a98a5bf87a63ad37307e9c Mon Sep 17 00:00:00 2001 +From: Shang XiaoJing +Date: Fri, 21 Oct 2022 18:50:33 +0800 +Subject: [PATCH 197/201] perf vendor events arm64: Fix incorrect Hisi hip08 L3 + metrics + +mainline inclusion +from mainline-v6.1-rc3 +commit e9229d5b6254a75291536f582652c599957344d2 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e9229d5b6254a75291536f582652c599957344d2 + +---------------------------------------------------------------------- + +Commit 0cc177cfc95d565e ("perf vendor events arm64: Add Hisi hip08 L3 +metrics") add L3 metrics of hip08, but some metrics (IF_BP_MISP_BR_RET, +IF_BP_MISP_BR_RET, IF_BP_MISP_BR_BL) have incorrect event number due to +the mistakes in document, which caused incorrect result. Fix the +incorrect metrics. + +Before: + + 65,811,214,308 armv8_pmuv3_0/event=0x1014/ # 18.87 push_branch + # -40.19 other_branch + 3,564,316,780 BR_MIS_PRED # 0.51 indirect_branch + # 21.81 pop_branch + +After: + + 6,537,146,245 BR_MIS_PRED # 0.48 indirect_branch + # 0.47 pop_branch + # 0.00 push_branch + # 0.05 other_branch + +Fixes: 0cc177cfc95d565e ("perf vendor events arm64: Add Hisi hip08 L3 metrics") +Reviewed-by: John Garry +Signed-off-by: Shang XiaoJing +Acked-by: James Clark +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: John Garry +Cc: Kajol Jain +Cc: Leo Yan +Cc: linux-arm-kernel@lists.infradead.org +Cc: Mark Rutland +Cc: Mike Leach +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Will Deacon +Link: https://lore.kernel.org/r/20221021105035.10000-2-shangxiaojing@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + .../perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +index dda8e59149d2..be23d3c89a79 100644 +--- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json ++++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +@@ -112,21 +112,21 @@ + "MetricName": "indirect_branch" + }, + { +- "MetricExpr": "(armv8_pmuv3_0@event\\=0x1014@ + armv8_pmuv3_0@event\\=0x1018@) / BR_MIS_PRED", ++ "MetricExpr": "(armv8_pmuv3_0@event\\=0x1013@ + armv8_pmuv3_0@event\\=0x1016@) / BR_MIS_PRED", + "PublicDescription": "Push branch L3 topdown metric", + "BriefDescription": "Push branch L3 topdown metric", + "MetricGroup": "TopDownL3", + "MetricName": "push_branch" + }, + { +- "MetricExpr": "armv8_pmuv3_0@event\\=0x100c@ / BR_MIS_PRED", ++ "MetricExpr": "armv8_pmuv3_0@event\\=0x100d@ / BR_MIS_PRED", + "PublicDescription": "Pop branch L3 topdown metric", + "BriefDescription": "Pop branch L3 topdown metric", + "MetricGroup": "TopDownL3", + "MetricName": "pop_branch" + }, + { +- "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\\=0x1010@ - armv8_pmuv3_0@event\\=0x1014@ - armv8_pmuv3_0@event\\=0x1018@ - armv8_pmuv3_0@event\\=0x100c@) / BR_MIS_PRED", ++ "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\\=0x1010@ - armv8_pmuv3_0@event\\=0x1013@ - armv8_pmuv3_0@event\\=0x1016@ - armv8_pmuv3_0@event\\=0x100d@) / BR_MIS_PRED", + "PublicDescription": "Other branch L3 topdown metric", + "BriefDescription": "Other branch L3 topdown metric", + "MetricGroup": "TopDownL3", +-- +2.27.0 + diff --git a/patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch b/patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch new file mode 100644 index 0000000..611eacc --- /dev/null +++ b/patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch @@ -0,0 +1,75 @@ +From 7a3cf279e516bef36cd731957adb70761653873a Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 10 Jun 2021 22:33:00 +0800 +Subject: [PATCH 198/201] perf metricgroup: Return error code from + metricgroup__add_metric_sys_event_iter() + +mainline inclusion +from mainline-v5.13-rc7 +commit fe7a98b9d9b36e5c8a22d76b67d29721f153f66e +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fe7a98b9d9b36e5c8a22d76b67d29721f153f66e + +---------------------------------------------------------------------- + +The error code is not set at all in the sys event iter function. + +This may lead to an uninitialized value of "ret" in +metricgroup__add_metric() when no CPU metric is added. + +Fix by properly setting the error code. + +It is not necessary to init "ret" to 0 in metricgroup__add_metric(), as +if we have no CPU or sys event metric matching, then "has_match" should +be 0 and "ret" is set to -EINVAL. + +However gcc cannot detect that it may not have been set after the +map_for_each_metric() loop for CPU metrics, which is strange. + +Fixes: be335ec28efa8 ("perf metricgroup: Support adding metrics for system PMUs") +Signed-off-by: John Garry +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/1623335580-187317-3-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 2eaaa96d009a..523123ec1bd2 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -1072,16 +1072,18 @@ static int metricgroup__add_metric_sys_event_iter(struct pmu_event *pe, + + ret = add_metric(d->metric_list, pe, d->metric_no_group, d->m, NULL, d->ids); + if (ret) +- return ret; ++ goto out; + + ret = resolve_metric(d->metric_no_group, + d->metric_list, NULL, d->ids); + if (ret) +- return ret; ++ goto out; + + *(d->has_match) = true; + +- return *d->ret; ++out: ++ *(d->ret) = ret; ++ return ret; + } + + static int metricgroup__add_metric(const char *metric, bool metric_no_group, +-- +2.27.0 + diff --git a/patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch b/patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch new file mode 100644 index 0000000..0c17c16 --- /dev/null +++ b/patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch @@ -0,0 +1,86 @@ +From f1fc7419be0aca70f081ffac6569ac60c861b1c9 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Tue, 19 Jan 2021 18:04:15 +0800 +Subject: [PATCH 199/201] perf metricgroup: Fix system PMU metrics + +mainline inclusion +from mainline-v5.11-rc5 +commit 3d6e79ee9e8f8c6604312382c2be1d1bd1cffc9e +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3d6e79ee9e8f8c6604312382c2be1d1bd1cffc9e + +---------------------------------------------------------------------- + +Joakim reports that getting "perf stat" for multiple system PMU metrics +segfaults: + + $ perf stat -a -I 1000 -M imx8mm_ddr_write.all,imx8mm_ddr_write.all + Segmentation fault + $ + +While the same works without issue for a single metric. + +The logic in metricgroup__add_metric_sys_event_iter() is broken, in that +add_metric() @m argument should be NULL for each new metric. Fix by not +passing a holder for that, and rather make local in +metricgroup__add_metric_sys_event_iter(). + +Fixes: be335ec28efa ("perf metricgroup: Support adding metrics for system PMUs") +Reported-by: Joakim Zhang +Signed-off-by: John Garry +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@openeuler.org +Link: https://lore.kernel.org/r/1611050655-44020-1-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan +--- + tools/perf/util/metricgroup.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 523123ec1bd2..bc0aa1b7938b 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -772,7 +772,6 @@ int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused) + struct metricgroup_add_iter_data { + struct list_head *metric_list; + const char *metric; +- struct metric **m; + struct expr_ids *ids; + int *ret; + bool *has_match; +@@ -1065,12 +1064,13 @@ static int metricgroup__add_metric_sys_event_iter(struct pmu_event *pe, + void *data) + { + struct metricgroup_add_iter_data *d = data; ++ struct metric *m = NULL; + int ret; + + if (!match_pe_metric(pe, d->metric)) + return 0; + +- ret = add_metric(d->metric_list, pe, d->metric_no_group, d->m, NULL, d->ids); ++ ret = add_metric(d->metric_list, pe, d->metric_no_group, &m, NULL, d->ids); + if (ret) + goto out; + +@@ -1123,7 +1123,6 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, + .metric_list = &list, + .metric = metric, + .metric_no_group = metric_no_group, +- .m = &m, + .ids = &ids, + .has_match = &has_match, + .ret = &ret, +-- +2.27.0 + diff --git a/patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch b/patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch new file mode 100644 index 0000000..2153667 --- /dev/null +++ b/patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch @@ -0,0 +1,134 @@ +From 3667180fda826780793e3a05e3883e078d2f0ba5 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 21 Jan 2021 00:18:38 +0800 +Subject: [PATCH 200/201] perf metricgroup: Fix for metrics containing + duration_time + +mainline inclusion +from mainline-v5.11-rc5 +commit 9c880c24cb0db49d6e62e6d882df1470b0be8038 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9c880c24cb0db49d6e62e6d882df1470b0be8038 + +---------------------------------------------------------------------- + +Metrics containing duration_time cause a segfault: + + $ perf stat -v -M L1D_Cache_Fill_BW sleep 1 + Using CPUID GenuineIntel-6-3D-4 + metric expr 64 * l1d.replacement / 1000000000 / duration_time for L1D_Cache_Fill_BW + found event duration_time + found event l1d.replacement + adding {l1d.replacement}:W,duration_time + l1d.replacement -> cpu/umask=0x1,(null)=0x1e8483,event=0x51/ + Segmentation fault + $ + +In commit c2337d67199a1ea1 ("perf metricgroup: Fix metrics using aliases +covering multiple PMUs"), the logic in find_evsel_group() when iter'ing +events was changed to not only select events in same group, but also for +aliased PMUs. + +Checking whether events were for aliased PMUs was done by comparing the +event PMU name. This was not safe for duration_time event, which has no +associated PMU (and no PMU name), so fix by checking if the event PMU name +is set also. + +Committer testing: + +Reproduced the bug, then, on a: + + $ grep -m1 ^'model name' /proc/cpuinfo + model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz + $ + +We now get: + + $ perf stat -M L1D_Cache_Fill_BW sleep 1 + + Performance counter stats for 'sleep 1': + + 4,141 l1d.replacement:u + 1,001,285,107 ns duration_time:u + + 1.001285107 seconds time elapsed + + 0.000000000 seconds user + 0.001119000 seconds sys + + $ + +Detais from -v: + + Using CPUID GenuineIntel-6-8E-A + metric expr 64 * l1d.replacement / 1000000000 / duration_time for L1D_Cache_Fill_BW + found event duration_time + found event l1d.replacement + adding {l1d.replacement}:W,duration_time + l1d.replacement -> cpu/(null)=0x1e8483,umask=0x1,event=0x51/ + Control descriptor is not initialized + Warning: + kernel.perf_event_paranoid=2, trying to fall back to excluding kernel and hypervisor samples + Warning: + kernel.perf_event_paranoid=2, trying to fall back to excluding kernel and hypervisor samples + l1d.replacement:u: 4592 612201 612201 + duration_time:u: 1001478621 1001478621 1001478621 + +Fixes: c2337d67199a1ea1 ("perf metricgroup: Fix metrics using aliases covering multiple PMUs") +Reported-by: Joakim Zhang +Signed-off-by: John Garry +Tested-by: Arnaldo Carvalho de Melo +Tested-by: Jiri Olsa +Acked-by: Ian Rogers +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: linuxarm@openeuler.org +Link: https://lore.kernel.org/r/1611159518-226883-1-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index bc0aa1b7938b..32c5919c9413 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -167,6 +167,14 @@ static bool contains_event(struct perf_evsel **metric_events, int num_events, + return false; + } + ++static bool evsel_same_pmu(struct perf_evsel *ev1, struct perf_evsel *ev2) ++{ ++ if (!ev1->pmu_name || !ev2->pmu_name) ++ return false; ++ ++ return !strcmp(ev1->pmu_name, ev2->pmu_name); ++} ++ + /** + * Find a group of events in perf_evlist that correspond to those from a parsed + * metric expression. Note, as find_evsel_group is called in the same order as +@@ -285,8 +293,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + */ + if (!has_constraint && + ev->leader != metric_events[i]->leader && +- !strcmp(ev->leader->pmu_name, +- metric_events[i]->leader->pmu_name)) ++ evsel_same_pmu(ev->leader, metric_events[i]->leader)) + break; + if (!strcmp(metric_events[i]->name, ev->name)) { + set_bit(ev->idx, evlist_used); +-- +2.27.0 + diff --git a/patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch b/patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch new file mode 100644 index 0000000..0140ba2 --- /dev/null +++ b/patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch @@ -0,0 +1,98 @@ +From 736d13f5a840e28e2db51c749e9ef67a7099a277 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Thu, 10 Jun 2021 22:32:59 +0800 +Subject: [PATCH 201/201] perf metricgroup: Fix find_evsel_group() event + selector + +mainline inclusion +from mainline-v5.13-rc7 +commit fc96ec4d5d4155c61cbafd49fb2dd403c899a9f4 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fc96ec4d5d4155c61cbafd49fb2dd403c899a9f4 + +---------------------------------------------------------------------- + +The following command segfaults on my x86 broadwell: + + $ ./perf stat -M frontend_bound,retiring,backend_bound,bad_speculation sleep 1 + WARNING: grouped events cpus do not match, disabling group: + anon group { raw 0x10e } + anon group { raw 0x10e } + perf: util/evsel.c:1596: get_group_fd: Assertion `!(!leader->core.fd)' failed. + Aborted (core dumped) + +The issue shows itself as a use-after-free in evlist__check_cpu_maps(), +whereby the leader of an event selector (evsel) has been deleted (yet we +still attempt to verify for an evsel). + +Fundamentally the problem comes from metricgroup__setup_events() -> +find_evsel_group(), and has developed from the previous fix attempt in +commit 9c880c24cb0d ("perf metricgroup: Fix for metrics containing +duration_time"). + +The problem now is that the logic in checking if an evsel is in the same +group is subtly broken for the "cycles" event. For the "cycles" event, +the pmu_name is NULL; however the logic in find_evsel_group() may set an +event matched against "cycles" as used, when it should not be. + +This leads to a condition where an evsel is set, yet its leader is not. + +Fix the check for evsel pmu_name by not matching evsels when either has a +NULL pmu_name. + +There is still a pre-existing metric issue whereby the ordering of the +metrics may break the 'stat' function, as discussed at: +https://lore.kernel.org/lkml/49c6fccb-b716-1bf0-18a6-cace1cdb66b9@huawei.com/ + +Fixes: 9c880c24cb0d ("perf metricgroup: Fix for metrics containing duration_time") +Signed-off-by: John Garry +Tested-by: Arnaldo Carvalho de Melo # On a Thinkpad T450S +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: http://lore.kernel.org/lkml/1623335580-187317-2-git-send-email-john.garry@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: hongrongxuan + + Conflicts: + tools/perf/util/metricgroup.c +--- + tools/perf/util/metricgroup.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c +index 32c5919c9413..c6679f9cad9c 100644 +--- a/tools/perf/util/metricgroup.c ++++ b/tools/perf/util/metricgroup.c +@@ -167,10 +167,11 @@ static bool contains_event(struct perf_evsel **metric_events, int num_events, + return false; + } + +-static bool evsel_same_pmu(struct perf_evsel *ev1, struct perf_evsel *ev2) ++static bool evsel_same_pmu_or_none(struct perf_evsel *ev1, ++ struct perf_evsel *ev2) + { + if (!ev1->pmu_name || !ev2->pmu_name) +- return false; ++ return true; + + return !strcmp(ev1->pmu_name, ev2->pmu_name); + } +@@ -293,7 +294,7 @@ static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + */ + if (!has_constraint && + ev->leader != metric_events[i]->leader && +- evsel_same_pmu(ev->leader, metric_events[i]->leader)) ++ evsel_same_pmu_or_none(ev->leader, metric_events[i]->leader)) + break; + if (!strcmp(metric_events[i]->name, ev->name)) { + set_bit(ev->idx, evlist_used); +-- +2.27.0 + diff --git a/series.conf b/series.conf index 44b2f18..894f274 100644 --- a/series.conf +++ b/series.conf @@ -118,3 +118,204 @@ patches/0114-perf-auxtrace-arm64-Add-support-for-HiSilicon-PCIe-T.patch patches/0115-perf-auxtrace-arm64-Add-support-for-parsing-HiSilico.patch patches/0116-Fix-the-header-file-location-error-and-adjust-the-fu.patch patches/0117-scsi-virtio_scsi-limit-number-of-hw-queues-by-nr_cpu.patch +patches/0118-perf-stat-Introduce-perf_evlist__print_counters.patch +patches/0119-perf-stat-Move-STAT_RECORD-out-of-perf_evlist__print.patch +patches/0120-perf-stat-Add-struct-perf_stat_config-argument-to-pe.patch +patches/0121-perf-stat-Pass-struct-perf_stat_config-argument-to-l.patch +patches/0122-perf-stat-Pass-a-struct-perf_stat_config-argument-to.patch +patches/0123-perf-stat-Move-metric_events-to-struct-perf_stat_con.patch +patches/0124-perf-list-Display-metric-expressions-for-details-opt.patch +patches/0125-perf-tools-Fix-legacy-events-symbol-separator-parsin.patch +patches/0126-perf-stat-Revert-checks-for-duration_time.patch +patches/0127-perf-stat-Implement-duration_time-as-a-proper-event.patch +patches/0128-perf-evsel-Support-printing-evsel-name-for-duration_.patch +patches/0129-perf-list-Output-tool-events.patch +patches/0130-libbpf-add-resizable-non-thread-safe-internal-hashma.patch +patches/0131-perf-stat-Fix-metrics-with-no-merge.patch +patches/0132-perf-jevents-Remove-unused-variable.patch +patches/0133-perf-jevents-Use-nonlocal-include-statements-in-pmu-.patch +patches/0134-perf-list-Avoid-extra-for-raw-metrics.patch +patches/0135-perf-tools-metric-Don-t-include-duration_time-in-gro.patch +patches/0136-perf-metricgroup-Add-missing-list_del_init-when-flus.patch +patches/0137-perf-metricgroup-Remove-needless-includes-from-metri.patch +patches/0138-perf-pmu-Change-convert_scale-from-static-to-global.patch +patches/0139-perf-metricgroup-Scale-the-metric-result.patch +patches/0140-perf-metricgroup-Support-multiple-events-for-metricg.patch +patches/0141-perf-pmu-Support-more-complex-PMU-event-aliasing.patch +patches/0142-perf-jevents-Add-support-for-Hisi-hip08-DDRC-PMU-ali.patch +patches/0143-perf-jevents-Add-support-for-Hisi-hip08-HHA-PMU-alia.patch +patches/0144-perf-jevents-Add-support-for-Hisi-hip08-L3C-PMU-alia.patch +patches/0145-perf-vendor-events-arm64-Fix-Hisi-hip08-DDRC-PMU-eve.patch +patches/0146-perf-vendor-events-arm64-Add-some-missing-events-for.patch +patches/0147-perf-vendor-events-arm64-Add-some-missing-events-for.patch +patches/0148-perf-vendor-events-arm64-Add-some-missing-events-for.patch +patches/0149-perf-stat-Fix-free-memory-access-memory-leaks-in-met.patch +patches/0150-perf-tools-Move-ALLOC_LIST-into-a-function.patch +patches/0151-perf-list-Hide-deprecated-events-by-default.patch +patches/0152-perf-metricgroup-Fix-printing-event-names-of-metric-.patch +patches/0153-tools-bitmap-Implement-bitmap_equal-operation-at-bit.patch +patches/0154-perf-metricgroup-Fix-printing-event-names-of-metric-.patch +patches/0155-perf-parse-events-Fix-an-old-style-declaration.patch +patches/0156-libbpf-fix-missing-__WORDSIZE-definition.patch +patches/0157-libbpf-hashmap-Remove-unused-include.patch +patches/0158-libbpf-Define-__WORDSIZE-if-not-available.patch +patches/0159-libbpf-Fix-libbpf-hashmap-on-I-LP32-architectures.patch +patches/0160-libbpf-hashmap-Fix-undefined-behavior-in-hash_bits.patch +patches/0161-perf-tools-Grab-a-copy-of-libbpf-s-hashmap.patch +patches/0162-perf-tools-Sync-hashmap.h-with-libbpf-s.patch +patches/0163-perf-tools-Update-copy-of-libbpf-s-hashmap.c.patch +patches/0164-perf-jevents-Support-metric-constraint.patch +patches/0165-perf-metricgroup-Factor-out-metricgroup__add_metric_.patch +patches/0166-perf-util-Factor-out-sysctl__nmi_watchdog_enabled.patch +patches/0167-perf-metricgroup-Support-metric-constraint.patch +patches/0168-perf-vendor-events-intel-Add-NO_NMI_WATCHDOG-metric-.patch +patches/0169-perf-expr-Add-expr.c-object.patch +patches/0170-perf-expr-Move-expr-lexer-to-flex.patch +patches/0171-perf-expr-Increase-EXPR_MAX_OTHER-to-support-metrics.patch +patches/0172-perf-expr-Straighten-expr__parse-expr__find_other-in.patch +patches/0173-perf-expr-Make-expr__parse-return-1-on-error.patch +patches/0174-perf-expr-Fix-memory-leaks-in-metric-bison.patch +patches/0175-perf-expr-Fix-copy-paste-mistake.patch +patches/0176-perf-expr-Add-expr_-prefix-for-parse_ctx-and-parse_i.patch +patches/0177-perf-expr-Add-expr_scanner_ctx-object.patch +patches/0178-perf-metrictroup-Split-the-metricgroup__add_metric-f.patch +patches/0179-perf-metricgroups-Enhance-JSON-metric-infrastructure.patch +patches/0180-perf-tests-expr-Added-test-for-runtime-param-in-metr.patch +patches/0181-perf-jevents-Add-some-test-events.patch +patches/0182-perf-jevents-Support-test-events-folder.patch +patches/0183-perf-pmu-Refactor-pmu_add_cpu_aliases.patch +patches/0184-perf-test-Add-pmu-events-test.patch +patches/0185-perf-pmu-Add-is_pmu_core.patch +patches/0186-perf-pmu-Make-pmu_uncore_alias_match-public.patch +patches/0187-perf-test-Test-pmu-events-aliases.patch +patches/0188-perf-expr-Allow-for-unlimited-escaped-characters-in-.patch +patches/0189-perf-expr-Allow-to-be-an-other-token.patch +patches/0190-perf-expr-Increase-max-other.patch +patches/0191-perf-expr-Parse-numbers-as-doubles.patch +patches/0192-perf-test-Improve-pmu-event-metric-testing.patch +patches/0193-perf-test-Provide-a-subtest-callback-to-ask-for-the-.patch +patches/0194-perf-expr-Migrate-expr-ids-table-to-a-hashmap.patch +patches/0195-perf-metricgroup-Make-evlist_used-variable-a-bitmap-.patch +patches/0196-perf-metricgroup-Always-place-duration_time-last.patch +patches/0197-perf-metricgroup-Use-early-return-in-add_metric.patch +patches/0198-perf-metricgroup-Delay-events-string-creation.patch +patches/0199-perf-metricgroup-Order-event-groups-by-size.patch +patches/0200-perf-metricgroup-Remove-duped-metric-group-events.patch +patches/0201-perf-metricgroup-Add-options-to-not-group-or-merge.patch +patches/0202-perf-metricgroup-Remove-unnecessary-from-events.patch +patches/0203-perf-parser-Add-support-to-specify-rXXX-event-with-p.patch +patches/0204-perf-tools-Allow-r0x-HEX-event-syntax.patch +patches/0205-perf-stat-Do-not-pass-avg-to-generic_metric.patch +patches/0206-perf-parse-Add-struct-parse_events_state-pointer-to-.patch +patches/0207-perf-tools-Fix-term-parsing-for-raw-syntax.patch +patches/0208-perf-tools-Add-fake-pmu-support.patch +patches/0209-perf-tests-Factor-check_parse_id-function.patch +patches/0210-perf-parse-Provide-a-way-to-pass-a-fake_pmu-to-parse.patch +patches/0211-perf-pmu-Add-a-perf_pmu__fake-object-to-use-with-__p.patch +patches/0212-perf-tests-Add-another-metric-parsing-test.patch +patches/0213-perf-parse-Factor-out-parse_groups-function.patch +patches/0214-perf-tools-Add-fake_pmu-to-parse_group-function.patch +patches/0215-perf-tools-Add-map-to-parse_groups-function.patch +patches/0216-perf-tools-Add-metricgroup__parse_groups_test-functi.patch +patches/0217-perf-tools-Factor-out-prepare_metric-function.patch +patches/0218-perf-tools-Release-metric_events-rblist.patch +patches/0219-perf-tools-Add-test_generic_metric-function.patch +patches/0220-perf-pmu-List-kernel-supplied-event-aliases-for-arm6.patch +patches/0221-perf-pmu-Improve-CPU-core-PMU-HW-event-list-ordering.patch +patches/0222-perf-metric-Rename-expr__add_id-to-expr__add_val.patch +patches/0223-perf-metric-Add-struct-expr_id_data-to-keep-expr-val.patch +patches/0224-perf-metric-Fix-memory-leak-in-expr__add_id-function.patch +patches/0225-perf-metric-Add-expr__add_id-function.patch +patches/0226-perf-metric-Change-expr__get_id-to-return-struct-exp.patch +patches/0227-perf-metric-Add-expr__del_id-function.patch +patches/0228-perf-metric-Add-macros-for-iterating-map-events.patch +patches/0229-perf-metric-Add-add_metric-function.patch +patches/0230-perf-metric-Rename-__metricgroup__add_metric-to-__ad.patch +patches/0231-perf-metric-Collect-referenced-metrics-in-struct-met.patch +patches/0232-perf-metric-Collect-referenced-metrics-in-struct-met.patch +patches/0233-perf-metric-Add-referenced-metrics-to-hash-data.patch +patches/0234-perf-metric-Compute-referenced-metrics.patch +patches/0235-perf-metric-Add-events-for-the-current-list.patch +patches/0236-perf-tests-Add-parse-metric-test-for-ipc-metric.patch +patches/0237-perf-tests-Add-parse-metric-test-for-frontend-metric.patch +patches/0238-perf-metric-Add-cache_miss_cycles-to-metric-parse-te.patch +patches/0239-perf-metric-Add-DCache_L2-to-metric-parse-test.patch +patches/0240-perf-metric-Add-recursion-check-when-processing-nest.patch +patches/0241-perf-metric-Make-compute_single-function-more-precis.patch +patches/0242-perf-metric-Add-metric-group-test.patch +patches/0243-perf-metric-Rename-struct-egroup-to-metric.patch +patches/0244-perf-metric-Rename-group_list-to-metric_list.patch +patches/0245-perf-jevents-Make-json_events-static-and-ditch-jeven.patch +patches/0246-perf-jevents-Add-new-structure-to-pass-json-fields.patch +patches/0247-perf-jevents-Add-support-for-parsing-perchip-percore.patch +patches/0248-perf-metricgroup-Pass-pmu_event-structure-as-a-param.patch +patches/0249-perf-list-Do-not-print-Metric-Groups-unnecessarily.patch +patches/0250-perf-metricgroup-Fix-typo-in-comment.patch +patches/0251-perf-test-Free-aliases-for-PMU-event-map-aliases-tes.patch +patches/0252-perf-metric-Fix-some-memory-leaks.patch +patches/0253-perf-metric-Fix-some-memory-leaks-part-2.patch +patches/0254-perf-evlist-Fix-cpu-thread-map-leak.patch +patches/0255-perf-parse-event-Fix-memory-leak-in-evsel-unit.patch +patches/0256-perf-test-Fix-memory-leaks-in-parse-metric-test.patch +patches/0257-perf-metric-Release-expr_parse_ctx-after-testing.patch +patches/0258-perf-metric-Free-metric-when-it-failed-to-resolve.patch +patches/0259-perf-metric-Do-not-free-metric-when-failed-to-resolv.patch +patches/0260-perf-test-Free-formats-for-perf-pmu-parse-test.patch +patches/0261-perf-metricgroup-Fix-uncore-metric-expressions.patch +patches/0262-perf-metricgroup-Make-find_metric-public-with-name-c.patch +patches/0263-perf-test-Handle-metric-reuse-in-pmu-events-parsing-.patch +patches/0264-perf-pmu-Add-pmu_events_map__find-function-to-find-t.patch +patches/0265-perf-vendor-events-arm64-Add-Hisi-hip08-L1-metrics.patch +patches/0266-perf-vendor-events-arm64-Add-Hisi-hip08-L2-metrics.patch +patches/0267-perf-vendor-events-arm64-Add-Hisi-hip08-L3-metrics.patch +patches/0268-perf-jevents-Fix-event-code-for-events-referencing-s.patch +patches/0269-perf-jevents-Fix-getting-maximum-number-of-fds.patch +patches/0270-perf-jevents-Fix-event-syntax-error-caused-by-ExtSel.patch +patches/0271-perf-jevents-Tidy-error-handling.patch +patches/0272-perf-jevents-Add-support-for-an-extra-directory-leve.patch +patches/0273-perf-jevents-Add-support-for-system-events-tables.patch +patches/0274-perf-pmu-Add-pmu_id.patch +patches/0275-perf-pmu-Add-pmu_add_sys_aliases.patch +patches/0276-perf-evlist-Change-evlist__splice_list_tail-ordering.patch +patches/0277-perf-metricgroup-Fix-metrics-using-aliases-covering-.patch +patches/0278-perf-metricgroup-Split-up-metricgroup__print.patch +patches/0279-perf-metricgroup-Support-printing-metric-groups-for-.patch +patches/0280-perf-metricgroup-Support-adding-metrics-for-system-P.patch +patches/0281-perf-jevents-Add-test-for-arch-std-events.patch +patches/0282-perf-tools-Fix-pattern-matching-for-same-substring-i.patch +patches/0283-perf-pmu-Fix-alias-matching.patch +patches/0284-perf-pmu-Add-alias-match-method-to-fit-pmu_name-of-H.patch +patches/0285-perf-pmu-Simplify-arguments-of-__perf_pmu__new_alias.patch +patches/0286-perf-pmu-Save-pmu-name.patch +patches/0287-perf-jevents-Make-build-dependency-on-test-JSONs.patch +patches/0288-perf-test-Factor-out-pmu-events-event-comparison.patch +patches/0289-perf-jevents-Relocate-test-events-to-cpu-folder.patch +patches/0290-perf-test-Declare-pmu-events-test-events-separately.patch +patches/0291-perf-test-Factor-out-pmu-events-alias-comparison.patch +patches/0292-perf-test-Test-pmu-events-core-aliases-separately.patch +patches/0293-perf-pmu-Check-.is_uncore-field-in-pmu_add_cpu_alias.patch +patches/0294-perf-test-Re-add-pmu-event-uncore-PMU-alias-test.patch +patches/0295-perf-test-Add-more-pmu-events-uncore-aliases.patch +patches/0296-perf-pmu-Make-pmu_add_sys_aliases-public.patch +patches/0297-perf-jevents-Print-SoC-name-per-system-event-table.patch +patches/0298-perf-test-Add-pmu-events-sys-event-support.patch +patches/0299-perf-parse-events-Set-numeric-term-config.patch +patches/0300-perf-jevents-Support-ConfigCode.patch +patches/0301-perf-test-Verify-more-event-members-in-pmu-events-te.patch +patches/0302-perf-vendor-events-arm64-Revise-hip08-uncore-events.patch +patches/0303-perf-test-Add-pmu-events-test-for-aliases-of-hip09-d.patch +patches/0304-perf-jevents-Add-support-for-HiSilicon-L3C-PMU-alias.patch +patches/0305-perf-jevents-Add-support-for-HiSilicon-DDRC-PMU-alia.patch +patches/0306-perf-jevents-Add-support-for-HiSilicon-HHA-PMU-alias.patch +patches/0307-perf-jevents-Add-support-for-HiSilicon-SLLC-PMU-alia.patch +patches/0308-perf-jevents-Add-support-for-HiSilicon-PA-PMU-aliasi.patch +patches/0309-perf-expr-Test-parsing-of-floating-point-numbers.patch +patches/0310-perf-expr-Allow-numbers-to-be-followed-by-a-dot.patch +patches/0311-perf-test-Set-NULL-sentinel-in-pmu_events-table-in-P.patch +patches/0312-perf-test-Fix-msan-uninitialized-use.patch +patches/0313-perf-test-Fix-metric-parsing-test.patch +patches/0314-perf-vendor-events-arm64-Fix-incorrect-Hisi-hip08-L3.patch +patches/0315-perf-metricgroup-Return-error-code-from-metricgroup_.patch +patches/0316-perf-metricgroup-Fix-system-PMU-metrics.patch +patches/0317-perf-metricgroup-Fix-for-metrics-containing-duration.patch +patches/0318-perf-metricgroup-Fix-find_evsel_group-event-selector.patch