From be52a4c17a36659ed09b3b7d893158d97339552a Mon Sep 17 00:00:00 2001 From: Yushan Wang Date: Fri, 5 Dec 2025 18:13:23 +0800 Subject: [PATCH 01/19] Revert "perf arm-spe: Add support for SPE Data Source packet on HiSilicon HIP12" mainline inclusion driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA ----------------------------------------------- This reverts commit 73d6b946a7a9ee2d65d5649718ba3329526329f0. Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/arch/arm64/include/asm/cputype.h | 2 - .../util/arm-spe-decoder/arm-spe-decoder.h | 17 ---- tools/perf/util/arm-spe.c | 98 ------------------- 3 files changed, 117 deletions(-) diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h index 62f01cd23180..f40a5d84c74f 100644 --- a/tools/arch/arm64/include/asm/cputype.h +++ b/tools/arch/arm64/include/asm/cputype.h @@ -127,7 +127,6 @@ #define FUJITSU_CPU_PART_A64FX 0x001 #define HISI_CPU_PART_TSV110 0xD01 -#define HISI_CPU_PART_HIP12 0xD06 #define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_FIRESTORM 0x023 @@ -200,7 +199,6 @@ #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) -#define MIDR_HISI_HIP12 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP12) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 83836eb43fdd..1443c28545a9 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -67,23 +67,6 @@ enum arm_spe_neoverse_data_source { ARM_SPE_NV_DRAM = 0xe, }; -enum arm_spe_hisi_hip_data_source { - ARM_SPE_HISI_HIP_PEER_CPU = 0, - ARM_SPE_HISI_HIP_PEER_CPU_HITM = 1, - ARM_SPE_HISI_HIP_L3 = 2, - ARM_SPE_HISI_HIP_L3_HITM = 3, - ARM_SPE_HISI_HIP_PEER_CLUSTER = 4, - ARM_SPE_HISI_HIP_PEER_CLUSTER_HITM = 5, - ARM_SPE_HISI_HIP_REMOTE_SOCKET = 6, - ARM_SPE_HISI_HIP_REMOTE_SOCKET_HITM = 7, - ARM_SPE_HISI_HIP_LOCAL_MEM = 8, - ARM_SPE_HISI_HIP_REMOTE_MEM = 9, - ARM_SPE_HISI_HIP_NC_DEV = 13, - ARM_SPE_HISI_HIP_L2 = 16, - ARM_SPE_HISI_HIP_L2_HITM = 17, - ARM_SPE_HISI_HIP_L1 = 18, -}; - struct arm_spe_record { enum arm_spe_sample_type type; int err; diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 12007f9bdad8..9848310cee5f 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -418,11 +418,6 @@ static const struct midr_range neoverse_spe[] = { {}, }; -static const struct midr_range hisi_hip_ds_encoding_cpus[] = { - MIDR_ALL_VERSIONS(MIDR_HISI_HIP12), - {}, -}; - static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *record, union perf_mem_data_src *data_src) { @@ -522,101 +517,10 @@ static void arm_spe__synth_data_source_generic(const struct arm_spe_record *reco data_src->mem_lvl |= PERF_MEM_LVL_REM_CCE1; } -static void arm_spe__synth_data_source_hisi_hip(const struct arm_spe_record *record, - union perf_mem_data_src *data_src) -{ - /* Use common synthesis method to handle store operations */ - if (record->op & ARM_SPE_OP_ST) { - arm_spe__synth_data_source_generic(record, data_src); - return; - } - - switch (record->source) { - case ARM_SPE_HISI_HIP_PEER_CPU: - data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_PEER_CPU_HITM: - data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_L3: - data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; - data_src->mem_snoop = PERF_MEM_SNOOP_HIT; - break; - case ARM_SPE_HISI_HIP_L3_HITM: - data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - break; - case ARM_SPE_HISI_HIP_PEER_CLUSTER: - data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_PEER_CLUSTER_HITM: - data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_REMOTE_SOCKET: - data_src->mem_lvl = PERF_MEM_LVL_REM_CCE2; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; - data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_REMOTE_SOCKET_HITM: - data_src->mem_lvl = PERF_MEM_LVL_REM_CCE2; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; - data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; - break; - case ARM_SPE_HISI_HIP_LOCAL_MEM: - data_src->mem_lvl = PERF_MEM_LVL_LOC_RAM | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; - break; - case ARM_SPE_HISI_HIP_REMOTE_MEM: - data_src->mem_lvl = PERF_MEM_LVL_REM_RAM1 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; - data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; - break; - case ARM_SPE_HISI_HIP_NC_DEV: - data_src->mem_lvl = PERF_MEM_LVL_IO | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_IO; - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; - break; - case ARM_SPE_HISI_HIP_L2: - data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; - break; - case ARM_SPE_HISI_HIP_L2_HITM: - data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - break; - case ARM_SPE_HISI_HIP_L1: - data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; - data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1; - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; - break; - default: - break; - } -} - static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr) { union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; bool is_neoverse = is_midr_in_range_list(midr, neoverse_spe); - bool is_hisilicon = is_midr_in_range_list(midr, hisi_hip_ds_encoding_cpus); /* Only synthesize data source for LDST operations */ if (!is_ldst_op(record->op)) @@ -631,8 +535,6 @@ static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 m if (is_neoverse) arm_spe__synth_data_source_neoverse(record, &data_src); - else if (is_hisilicon) - arm_spe__synth_data_source_hisi_hip(record, &data_src); else arm_spe__synth_data_source_generic(record, &data_src); -- Gitee From ed2bd1f07a0f2131b802daeb1c826ad8e6a50aad Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:16 +0100 Subject: [PATCH 02/19] perf arm-spe: Rename arm_spe__synth_data_source_generic() mainline inclusion from mainline-v6.13-rc1 commit fb98fa3bf86893e53fac7bc951f503caf4a6eb23 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fb98fa3bf86893e53fac7bc951f503caf4a6eb23 ----------------------------------------------- The arm_spe__synth_data_source_generic() function is invoked when the tool detects that CPUs do not support data source packets and falls back to synthesizing only the memory level. Rename it to arm_spe__synth_memory_level() for better reflecting its purpose. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-2-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 9848310cee5f..6c67ba60d236 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -494,8 +494,8 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec } } -static void arm_spe__synth_data_source_generic(const struct arm_spe_record *record, - union perf_mem_data_src *data_src) +static void arm_spe__synth_memory_level(const struct arm_spe_record *record, + union perf_mem_data_src *data_src) { if (record->type & (ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS)) { data_src->mem_lvl = PERF_MEM_LVL_L3; @@ -536,7 +536,7 @@ static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 m if (is_neoverse) arm_spe__synth_data_source_neoverse(record, &data_src); else - arm_spe__synth_data_source_generic(record, &data_src); + arm_spe__synth_memory_level(record, &data_src); if (record->type & (ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS)) { data_src.mem_dtlb = PERF_MEM_TLB_WK; -- Gitee From 71e5a036c0db3a3037c1d32a0b035ee051c9f064 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:17 +0100 Subject: [PATCH 03/19] perf arm-spe: Rename the common data source encoding mainline inclusion from mainline-v6.13-rc1 commit 50b8f1d5bf4ad7f09ef8012ccf5f94f741df827b category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=50b8f1d5bf4ad7f09ef8012ccf5f94f741df827b ----------------------------------------------- The Neoverse CPUs follow the common data source encoding, and other CPU variants can share the same format. Rename the CPU list and data source definitions as common data source names. This change prepares for appending more CPU variants. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-3-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- .../util/arm-spe-decoder/arm-spe-decoder.h | 18 ++++++------ tools/perf/util/arm-spe.c | 28 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 1443c28545a9..358c611eeddb 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -56,15 +56,15 @@ enum arm_spe_op_type { ARM_SPE_OP_BR_INDIRECT = 1 << 17, }; -enum arm_spe_neoverse_data_source { - ARM_SPE_NV_L1D = 0x0, - ARM_SPE_NV_L2 = 0x8, - ARM_SPE_NV_PEER_CORE = 0x9, - ARM_SPE_NV_LOCAL_CLUSTER = 0xa, - ARM_SPE_NV_SYS_CACHE = 0xb, - ARM_SPE_NV_PEER_CLUSTER = 0xc, - ARM_SPE_NV_REMOTE = 0xd, - ARM_SPE_NV_DRAM = 0xe, +enum arm_spe_common_data_source { + ARM_SPE_COMMON_DS_L1D = 0x0, + ARM_SPE_COMMON_DS_L2 = 0x8, + ARM_SPE_COMMON_DS_PEER_CORE = 0x9, + ARM_SPE_COMMON_DS_LOCAL_CLUSTER = 0xa, + ARM_SPE_COMMON_DS_SYS_CACHE = 0xb, + ARM_SPE_COMMON_DS_PEER_CLUSTER = 0xc, + ARM_SPE_COMMON_DS_REMOTE = 0xd, + ARM_SPE_COMMON_DS_DRAM = 0xe, }; struct arm_spe_record { diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 6c67ba60d236..30ec8f52b398 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -411,15 +411,15 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, return arm_spe_deliver_synth_event(spe, speq, event, &sample); } -static const struct midr_range neoverse_spe[] = { +static const struct midr_range common_ds_encoding_cpus[] = { MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), {}, }; -static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *record, - union perf_mem_data_src *data_src) +static void arm_spe__synth_data_source_common(const struct arm_spe_record *record, + union perf_mem_data_src *data_src) { /* * Even though four levels of cache hierarchy are possible, no known @@ -441,17 +441,17 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec } switch (record->source) { - case ARM_SPE_NV_L1D: + case ARM_SPE_COMMON_DS_L1D: data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1; data_src->mem_snoop = PERF_MEM_SNOOP_NONE; break; - case ARM_SPE_NV_L2: + case ARM_SPE_COMMON_DS_L2: data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; data_src->mem_snoop = PERF_MEM_SNOOP_NONE; break; - case ARM_SPE_NV_PEER_CORE: + case ARM_SPE_COMMON_DS_PEER_CORE: data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; @@ -460,8 +460,8 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec * We don't know if this is L1, L2 but we do know it was a cache-2-cache * transfer, so set SNOOPX_PEER */ - case ARM_SPE_NV_LOCAL_CLUSTER: - case ARM_SPE_NV_PEER_CLUSTER: + case ARM_SPE_COMMON_DS_LOCAL_CLUSTER: + case ARM_SPE_COMMON_DS_PEER_CLUSTER: data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; @@ -469,7 +469,7 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec /* * System cache is assumed to be L3 */ - case ARM_SPE_NV_SYS_CACHE: + case ARM_SPE_COMMON_DS_SYS_CACHE: data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; data_src->mem_snoop = PERF_MEM_SNOOP_HIT; @@ -478,13 +478,13 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec * We don't know what level it hit in, except it came from the other * socket */ - case ARM_SPE_NV_REMOTE: + case ARM_SPE_COMMON_DS_REMOTE: data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1; data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; break; - case ARM_SPE_NV_DRAM: + case ARM_SPE_COMMON_DS_DRAM: data_src->mem_lvl = PERF_MEM_LVL_LOC_RAM | PERF_MEM_LVL_HIT; data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; data_src->mem_snoop = PERF_MEM_SNOOP_NONE; @@ -520,7 +520,7 @@ static void arm_spe__synth_memory_level(const struct arm_spe_record *record, static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr) { union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; - bool is_neoverse = is_midr_in_range_list(midr, neoverse_spe); + bool is_common = is_midr_in_range_list(midr, common_ds_encoding_cpus); /* Only synthesize data source for LDST operations */ if (!is_ldst_op(record->op)) @@ -533,8 +533,8 @@ static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 m else return 0; - if (is_neoverse) - arm_spe__synth_data_source_neoverse(record, &data_src); + if (is_common) + arm_spe__synth_data_source_common(record, &data_src); else arm_spe__synth_memory_level(record, &data_src); -- Gitee From 74c7fbd703f8045d1813cf8b16f79f10b35c6415 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:43:01 +0100 Subject: [PATCH 04/19] perf arm-spe: Support metadata version 2 mainline inclusion from mainline-v6.13-rc1 commit 7842a4b6ff698768ccdb13324c3902a069b5d5dd category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7842a4b6ff698768ccdb13324c3902a069b5d5dd ----------------------------------------------- This commit is to support metadata version 2 and at the meantime it is backward compatible for version 1's format. The metadata version 1 doesn't include the ARM_SPE_HEADER_VERSION field. As version 1 is fixed with two u64 fields, by checking the metadata size, it distinguishes the metadata is version 1 or version 2 (and any new versions if later will have). For version 2, it reads out CPU number and retrieves the metadata info for every CPU. Signed-off-by: Leo Yan Reviewed-by: James Clark Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241003184302.190806-5-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 99 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 30ec8f52b398..ec544b83464c 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -80,6 +80,10 @@ struct arm_spe { unsigned long num_events; u8 use_ctx_pkt_for_pid; + + u64 **metadata; + u64 metadata_ver; + u64 metadata_nr_cpu; }; struct arm_spe_queue { @@ -1022,6 +1026,73 @@ static int arm_spe_flush(struct perf_session *session __maybe_unused, return 0; } +static u64 *arm_spe__alloc_per_cpu_metadata(u64 *buf, int per_cpu_size) +{ + u64 *metadata; + + metadata = zalloc(per_cpu_size); + if (!metadata) + return NULL; + + memcpy(metadata, buf, per_cpu_size); + return metadata; +} + +static void arm_spe__free_metadata(u64 **metadata, int nr_cpu) +{ + int i; + + for (i = 0; i < nr_cpu; i++) + zfree(&metadata[i]); + free(metadata); +} + +static u64 **arm_spe__alloc_metadata(struct perf_record_auxtrace_info *info, + u64 *ver, int *nr_cpu) +{ + u64 *ptr = (u64 *)info->priv; + u64 metadata_size; + u64 **metadata = NULL; + int hdr_sz, per_cpu_sz, i; + + metadata_size = info->header.size - + sizeof(struct perf_record_auxtrace_info); + + /* Metadata version 1 */ + if (metadata_size == ARM_SPE_AUXTRACE_V1_PRIV_SIZE) { + *ver = 1; + *nr_cpu = 0; + /* No per CPU metadata */ + return NULL; + } + + *ver = ptr[ARM_SPE_HEADER_VERSION]; + hdr_sz = ptr[ARM_SPE_HEADER_SIZE]; + *nr_cpu = ptr[ARM_SPE_CPUS_NUM]; + + metadata = calloc(*nr_cpu, sizeof(*metadata)); + if (!metadata) + return NULL; + + /* Locate the start address of per CPU metadata */ + ptr += hdr_sz; + per_cpu_sz = (metadata_size - (hdr_sz * sizeof(u64))) / (*nr_cpu); + + for (i = 0; i < *nr_cpu; i++) { + metadata[i] = arm_spe__alloc_per_cpu_metadata(ptr, per_cpu_sz); + if (!metadata[i]) + goto err_per_cpu_metadata; + + ptr += per_cpu_sz / sizeof(u64); + } + + return metadata; + +err_per_cpu_metadata: + arm_spe__free_metadata(metadata, *nr_cpu); + return NULL; +} + static void arm_spe_free_queue(void *priv) { struct arm_spe_queue *speq = priv; @@ -1056,6 +1127,7 @@ static void arm_spe_free(struct perf_session *session) auxtrace_heap__free(&spe->heap); arm_spe_free_events(session); session->auxtrace = NULL; + arm_spe__free_metadata(spe->metadata, spe->metadata_nr_cpu); free(spe); } @@ -1302,15 +1374,26 @@ int arm_spe_process_auxtrace_info(union perf_event *event, const char *cpuid = perf_env__cpuid(session->evlist->env); u64 midr = strtol(cpuid, NULL, 16); struct arm_spe *spe; - int err; + u64 **metadata = NULL; + u64 metadata_ver; + int nr_cpu, err; if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) + min_sz) return -EINVAL; + metadata = arm_spe__alloc_metadata(auxtrace_info, &metadata_ver, + &nr_cpu); + if (!metadata && metadata_ver != 1) { + pr_err("Failed to parse Arm SPE metadata.\n"); + return -EINVAL; + } + spe = zalloc(sizeof(struct arm_spe)); - if (!spe) - return -ENOMEM; + if (!spe) { + err = -ENOMEM; + goto err_free_metadata; + } err = auxtrace_queues__init(&spe->queues); if (err) @@ -1319,8 +1402,14 @@ int arm_spe_process_auxtrace_info(union perf_event *event, spe->session = session; spe->machine = &session->machines.host; /* No kvm support */ spe->auxtrace_type = auxtrace_info->type; - spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE]; + if (metadata_ver == 1) + spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE]; + else + spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2]; spe->midr = midr; + spe->metadata = metadata; + spe->metadata_ver = metadata_ver; + spe->metadata_nr_cpu = nr_cpu; spe->timeless_decoding = arm_spe__is_timeless_decoding(spe); @@ -1381,5 +1470,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event, session->auxtrace = NULL; err_free: free(spe); +err_free_metadata: + arm_spe__free_metadata(metadata, nr_cpu); return err; } -- Gitee From 2caa3ae383311e64cc302b4406dc62e3113e19b9 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:43:02 +0100 Subject: [PATCH 05/19] perf arm-spe: Dump metadata with version 2 mainline inclusion from mainline-v6.13-rc1 commit e52abceb4b6c2723c7e49388e67a32ffb47bd90c category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e52abceb4b6c2723c7e49388e67a32ffb47bd90c ----------------------------------------------- This commit dumps metadata with version 2. It dumps metadata for header and per CPU data respectively in the arm_spe_print_info() function to support metadata version 2 format. After: 0 0 0x3c0 [0x1b0]: PERF_RECORD_AUXTRACE_INFO type: 4 Header version :2 Header size :4 PMU type v2 :13 CPU number :8 Magic :0x1010101010101010 CPU # :0 Num of params :3 MIDR :0x410fd801 PMU Type :-1 Min Interval :0 Magic :0x1010101010101010 CPU # :1 Num of params :3 MIDR :0x410fd801 PMU Type :-1 Min Interval :0 Magic :0x1010101010101010 CPU # :2 Num of params :3 MIDR :0x410fd870 PMU Type :13 Min Interval :1024 Magic :0x1010101010101010 CPU # :3 Num of params :3 MIDR :0x410fd870 PMU Type :13 Min Interval :1024 Magic :0x1010101010101010 CPU # :4 Num of params :3 MIDR :0x410fd870 PMU Type :13 Min Interval :1024 Magic :0x1010101010101010 CPU # :5 Num of params :3 MIDR :0x410fd870 PMU Type :13 Min Interval :1024 Magic :0x1010101010101010 CPU # :6 Num of params :3 MIDR :0x410fd850 PMU Type :-1 Min Interval :0 Magic :0x1010101010101010 CPU # :7 Num of params :3 MIDR :0x410fd850 PMU Type :-1 Min Interval :0 Signed-off-by: Leo Yan Reviewed-by: James Clark Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241003184302.190806-6-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 54 +++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index ec544b83464c..4f4cae13ba0b 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -1139,16 +1139,60 @@ static bool arm_spe_evsel_is_auxtrace(struct perf_session *session, return evsel->core.attr.type == spe->pmu_type; } -static const char * const arm_spe_info_fmts[] = { - [ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n", +static const char * const metadata_hdr_v1_fmts[] = { + [ARM_SPE_PMU_TYPE] = " PMU Type :%"PRId64"\n", + [ARM_SPE_PER_CPU_MMAPS] = " Per CPU mmaps :%"PRId64"\n", }; -static void arm_spe_print_info(__u64 *arr) +static const char * const metadata_hdr_fmts[] = { + [ARM_SPE_HEADER_VERSION] = " Header version :%"PRId64"\n", + [ARM_SPE_HEADER_SIZE] = " Header size :%"PRId64"\n", + [ARM_SPE_PMU_TYPE_V2] = " PMU type v2 :%"PRId64"\n", + [ARM_SPE_CPUS_NUM] = " CPU number :%"PRId64"\n", +}; + +static const char * const metadata_per_cpu_fmts[] = { + [ARM_SPE_MAGIC] = " Magic :0x%"PRIx64"\n", + [ARM_SPE_CPU] = " CPU # :%"PRId64"\n", + [ARM_SPE_CPU_NR_PARAMS] = " Num of params :%"PRId64"\n", + [ARM_SPE_CPU_MIDR] = " MIDR :0x%"PRIx64"\n", + [ARM_SPE_CPU_PMU_TYPE] = " PMU Type :%"PRId64"\n", + [ARM_SPE_CAP_MIN_IVAL] = " Min Interval :%"PRId64"\n", +}; + +static void arm_spe_print_info(struct arm_spe *spe, __u64 *arr) { + unsigned int i, cpu, hdr_size, cpu_num, cpu_size; + const char * const *hdr_fmts; + if (!dump_trace) return; - fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]); + if (spe->metadata_ver == 1) { + cpu_num = 0; + hdr_size = ARM_SPE_AUXTRACE_V1_PRIV_MAX; + hdr_fmts = metadata_hdr_v1_fmts; + } else { + cpu_num = arr[ARM_SPE_CPUS_NUM]; + hdr_size = arr[ARM_SPE_HEADER_SIZE]; + hdr_fmts = metadata_hdr_fmts; + } + + for (i = 0; i < hdr_size; i++) + fprintf(stdout, hdr_fmts[i], arr[i]); + + arr += hdr_size; + for (cpu = 0; cpu < cpu_num; cpu++) { + /* + * The parameters from ARM_SPE_MAGIC to ARM_SPE_CPU_NR_PARAMS + * are fixed. The sequential parameter size is decided by the + * field 'ARM_SPE_CPU_NR_PARAMS'. + */ + cpu_size = (ARM_SPE_CPU_NR_PARAMS + 1) + arr[ARM_SPE_CPU_NR_PARAMS]; + for (i = 0; i < cpu_size; i++) + fprintf(stdout, metadata_per_cpu_fmts[i], arr[i]); + arr += cpu_size; + } } struct arm_spe_synth { @@ -1442,7 +1486,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event, spe->auxtrace.evsel_is_auxtrace = arm_spe_evsel_is_auxtrace; session->auxtrace = &spe->auxtrace; - arm_spe_print_info(&auxtrace_info->priv[0]); + arm_spe_print_info(spe, &auxtrace_info->priv[0]); if (dump_trace) return 0; -- Gitee From 33d1ca4ddb62b6dafb22fea413a6f7d8640b41f2 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:18 +0100 Subject: [PATCH 06/19] perf arm-spe: Introduce arm_spe__is_homogeneous() mainline inclusion from mainline-v6.13-rc1 commit 56ae663e7636f2ce180201f0f18d7736c319a43f category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=56ae663e7636f2ce180201f0f18d7736c319a43f ----------------------------------------------- Introduce the arm_spe__is_homogeneous() function, it uses to check if Arm SPE is homogeneous cross all CPUs. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-4-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 4f4cae13ba0b..5ad1eafea96c 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -84,6 +84,7 @@ struct arm_spe { u64 **metadata; u64 metadata_ver; u64 metadata_nr_cpu; + bool is_homogeneous; }; struct arm_spe_queue { @@ -1409,6 +1410,30 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) return 0; } +static bool arm_spe__is_homogeneous(u64 **metadata, int nr_cpu) +{ + u64 midr; + int i; + + if (!nr_cpu) + return false; + + for (i = 0; i < nr_cpu; i++) { + if (!metadata[i]) + return false; + + if (i == 0) { + midr = metadata[i][ARM_SPE_CPU_MIDR]; + continue; + } + + if (midr != metadata[i][ARM_SPE_CPU_MIDR]) + return false; + } + + return true; +} + int arm_spe_process_auxtrace_info(union perf_event *event, struct perf_session *session) { @@ -1454,6 +1479,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event, spe->metadata = metadata; spe->metadata_ver = metadata_ver; spe->metadata_nr_cpu = nr_cpu; + spe->is_homogeneous = arm_spe__is_homogeneous(metadata, nr_cpu); spe->timeless_decoding = arm_spe__is_timeless_decoding(spe); -- Gitee From dcaf03e2f985430e324436a94e18f10f3490ed4c Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:19 +0100 Subject: [PATCH 07/19] perf arm-spe: Use metadata to decide the data source feature mainline inclusion from mainline-v6.13-rc1 commit ba5e7169e5483a61899497e23fa18f7ef33aa827 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ba5e7169e5483a61899497e23fa18f7ef33aa827 ----------------------------------------------- Use the info in the metadata to decide if the data source feature is supported. The CPU MIDR must be in the CPU list for the common data source encoding. For the metadata version 1, it doesn't include info for MIDR. In this case, due to absent info for making decision, print out warning to remind users to upgrade tool and returns false. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-5-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 67 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 5ad1eafea96c..1d64b7b09bf9 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -280,6 +280,20 @@ static int arm_spe_set_tid(struct arm_spe_queue *speq, pid_t tid) return 0; } +static u64 *arm_spe__get_metadata_by_cpu(struct arm_spe *spe, u64 cpu) +{ + u64 i; + + if (!spe->metadata) + return NULL; + + for (i = 0; i < spe->metadata_nr_cpu; i++) + if (spe->metadata[i][ARM_SPE_CPU] == cpu) + return spe->metadata[i]; + + return NULL; +} + static struct simd_flags arm_spe__synth_simd_flags(const struct arm_spe_record *record) { struct simd_flags simd_flags = {}; @@ -522,10 +536,57 @@ static void arm_spe__synth_memory_level(const struct arm_spe_record *record, data_src->mem_lvl |= PERF_MEM_LVL_REM_CCE1; } -static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr) +static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq) +{ + struct arm_spe *spe = speq->spe; + bool is_in_cpu_list; + u64 *metadata = NULL; + u64 midr = 0; + + /* + * Metadata version 1 doesn't contain any info for MIDR. + * Simply return false in this case. + */ + if (spe->metadata_ver == 1) { + pr_warning_once("The data file contains metadata version 1, " + "which is absent the info for data source. " + "Please upgrade the tool to record data.\n"); + return false; + } + + /* CPU ID is -1 for per-thread mode */ + if (speq->cpu < 0) { + /* + * On the heterogeneous system, due to CPU ID is -1, + * cannot confirm the data source packet is supported. + */ + if (!spe->is_homogeneous) + return false; + + /* In homogeneous system, simply use CPU0's metadata */ + if (spe->metadata) + metadata = spe->metadata[0]; + } else { + metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); + } + + if (!metadata) + return false; + + midr = metadata[ARM_SPE_CPU_MIDR]; + + is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus); + if (is_in_cpu_list) + return true; + else + return false; +} + +static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq, + const struct arm_spe_record *record) { union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; - bool is_common = is_midr_in_range_list(midr, common_ds_encoding_cpus); + bool is_common = arm_spe__is_common_ds_encoding(speq); /* Only synthesize data source for LDST operations */ if (!is_ldst_op(record->op)) @@ -562,7 +623,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq) u64 data_src; int err; - data_src = arm_spe__synth_data_source(record, spe->midr); + data_src = arm_spe__synth_data_source(speq, record); if (spe->sample_flc) { if (record->type & ARM_SPE_L1D_MISS) { -- Gitee From 04d3c41976272d0d254c8e712e17b1f172be1efe Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:20 +0100 Subject: [PATCH 08/19] perf arm-spe: Remove the unused 'midr' field mainline inclusion from mainline-v6.13-rc1 commit 6bcf54c89b3d8406433839f0e3b72c08b4a1caf3 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6bcf54c89b3d8406433839f0e3b72c08b4a1caf3 ----------------------------------------------- The 'midr' field is replaced by the MIDR values stored in metadata (per CPU wise). Remove the 'midr' field as it is no longer used. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-6-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 1d64b7b09bf9..5bbf5e07decc 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -48,7 +48,6 @@ struct arm_spe { struct perf_session *session; struct machine *machine; u32 pmu_type; - u64 midr; struct perf_tsc_conversion tc; @@ -1501,8 +1500,6 @@ int arm_spe_process_auxtrace_info(union perf_event *event, struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; size_t min_sz = sizeof(u64) * ARM_SPE_AUXTRACE_PRIV_MAX; struct perf_record_time_conv *tc = &session->time_conv; - const char *cpuid = perf_env__cpuid(session->evlist->env); - u64 midr = strtol(cpuid, NULL, 16); struct arm_spe *spe; u64 **metadata = NULL; u64 metadata_ver; @@ -1536,7 +1533,6 @@ int arm_spe_process_auxtrace_info(union perf_event *event, spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE]; else spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2]; - spe->midr = midr; spe->metadata = metadata; spe->metadata_ver = metadata_ver; spe->metadata_nr_cpu = nr_cpu; -- Gitee From 072c521d30a47c337423af748548af2f04fef143 Mon Sep 17 00:00:00 2001 From: Besar Wicaksono Date: Thu, 3 Oct 2024 19:53:21 +0100 Subject: [PATCH 09/19] perf arm-spe: Add Neoverse-V2 to common data source encoding list mainline inclusion from mainline-v6.13-rc1 commit 041c0e5715a65a1b653283b853b4ca973780607a category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=041c0e5715a65a1b653283b853b4ca973780607a ----------------------------------------------- Add Neoverse-V2 MIDR to the common data source encoding range list. Signed-off-by: Besar Wicaksono Reviewed-by: Leo Yan Reviewed-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-7-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 5bbf5e07decc..2c39bc800070 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -433,6 +433,7 @@ static const struct midr_range common_ds_encoding_cpus[] = { MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), {}, }; -- Gitee From 81242ec6bd1c5c8638f0e3a09ea3f113a0ca7b35 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:53:22 +0100 Subject: [PATCH 10/19] perf arm-spe: Add Cortex CPUs to common data source encoding list mainline inclusion from mainline-v6.13-rc1 commit ea2ead4224fd3899f6dadd4c1fc526f32ec2246c category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ea2ead4224fd3899f6dadd4c1fc526f32ec2246c ----------------------------------------------- Add Cortex-A720, Cortex-A725, Cortex-X1C, Cortex-X3 and Cortex-X925 into the common data source encoding list. For everyone of these CPUs, it technical reference manual defines the data source packet as the common encoding format. Signed-off-by: Leo Yan Reviewed-by: James Clark Link: https://lore.kernel.org/r/20241003185322.192357-8-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 2c39bc800070..a5fb1c84d490 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -430,6 +430,11 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, } static const struct midr_range common_ds_encoding_cpus[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), -- Gitee From f4b7623db2414fed3ce36df8086fe53377550958 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 17 Oct 2024 10:53:50 -0700 Subject: [PATCH 11/19] perf color: Add printf format checking and resolve issues mainline inclusion from mainline-v6.13-rc1 commit 58fc358a3e2d484697afbae86496fc5982f222f3 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=58fc358a3e2d484697afbae86496fc5982f222f3 ----------------------------------------------- Add printf format checking to vararg printf routines in color.h. Resolve build errors/bugs that are found through this checking. Signed-off-by: Ian Rogers Cc: Yicong Yang Cc: Weilin Wang Cc: Will Deacon Cc: James Clark Cc: Mike Leach Cc: Leo Yan Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Tim Chen Cc: John Garry Link: https://lore.kernel.org/r/20241017175356.783793-2-irogers@google.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index a5fb1c84d490..acd973e7885c 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -124,7 +124,7 @@ static void arm_spe_dump(struct arm_spe *spe __maybe_unused, else pkt_len = 1; printf("."); - color_fprintf(stdout, color, " %08x: ", pos); + color_fprintf(stdout, color, " %08zx: ", pos); for (i = 0; i < pkt_len; i++) color_fprintf(stdout, color, " %02x", buf[i]); for (; i < 16; i++) -- Gitee From 1b57f0eaf77a64bf311a86b861f8c71e24dd4c9a Mon Sep 17 00:00:00 2001 From: Graham Woodward Date: Fri, 25 Oct 2024 15:30:06 +0100 Subject: [PATCH 12/19] perf arm-spe: Set sample.addr to target address for instruction sample mainline inclusion from mainline-v6.13-rc1 commit 19966d792b9e6b055aeb2f0e573b4d4573d5e15b category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=19966d792b9e6b055aeb2f0e573b4d4573d5e15b ----------------------------------------------- For an instruction sample, assign the target address to the field 'to_ip'. If it is a non-branch record, to_ip will be 0, presenting a non-valid target address. Signed-off-by: Graham Woodward Reviewed-by: James Clark Tested-by: Leo Yan Cc: nd@arm.com Cc: mike.leach@linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20241025143009.25419-2-graham.woodward@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index acd973e7885c..8407813910ee 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -420,7 +420,7 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, sample.id = spe_events_id; sample.stream_id = spe_events_id; - sample.addr = record->virt_addr; + sample.addr = record->to_ip; sample.phys_addr = record->phys_addr; sample.data_src = data_src; sample.period = spe->instructions_sample_period; -- Gitee From cb91e9982efc0935405c463102ae5b7c75d7e31e Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 29 Oct 2024 14:37:33 +0000 Subject: [PATCH 13/19] perf arm-spe: Use old behavior when opening old SPE files mainline inclusion from mainline-v6.13-rc1 commit ba993e5ada1ddce7a71140dc85ef65bc2cd981bc category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ba993e5ada1ddce7a71140dc85ef65bc2cd981bc ----------------------------------------------- Since the linked commit, we stopped interpreting data source if the perf.data file doesn't have the new metadata version. This means that perf c2c will show no samples in this case. Keep the old behavior so old files can be opened, but also still show the new warning that updating might improve the decoding. Also re-write the warning to be more concise and specific to a user. Fixes: ba5e7169e548 ("perf arm-spe: Use metadata to decide the data source feature") Signed-off-by: James Clark Reviewed-by: Leo Yan Cc: Julio.Suarez@arm.com Cc: Kiel.Friedt@arm.com Cc: Ryan.Roberts@arm.com Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241029143734.291638-1-james.clark@linaro.org Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 50 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 8407813910ee..8613db585064 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -548,37 +548,35 @@ static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq) u64 *metadata = NULL; u64 midr = 0; - /* - * Metadata version 1 doesn't contain any info for MIDR. - * Simply return false in this case. - */ + /* Metadata version 1 assumes all CPUs are the same (old behavior) */ if (spe->metadata_ver == 1) { - pr_warning_once("The data file contains metadata version 1, " - "which is absent the info for data source. " - "Please upgrade the tool to record data.\n"); - return false; - } - - /* CPU ID is -1 for per-thread mode */ - if (speq->cpu < 0) { - /* - * On the heterogeneous system, due to CPU ID is -1, - * cannot confirm the data source packet is supported. - */ - if (!spe->is_homogeneous) - return false; + const char *cpuid; - /* In homogeneous system, simply use CPU0's metadata */ - if (spe->metadata) - metadata = spe->metadata[0]; + pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n"); + cpuid = perf_env__cpuid(spe->session->evlist->env); + midr = strtol(cpuid, NULL, 16); } else { - metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); - } + /* CPU ID is -1 for per-thread mode */ + if (speq->cpu < 0) { + /* + * On the heterogeneous system, due to CPU ID is -1, + * cannot confirm the data source packet is supported. + */ + if (!spe->is_homogeneous) + return false; + + /* In homogeneous system, simply use CPU0's metadata */ + if (spe->metadata) + metadata = spe->metadata[0]; + } else { + metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); + } - if (!metadata) - return false; + if (!metadata) + return false; - midr = metadata[ARM_SPE_CPU_MIDR]; + midr = metadata[ARM_SPE_CPU_MIDR]; + } is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus); if (is_in_cpu_list) -- Gitee From 87bc6ed1786db1fc87715345da40a81bd60e82de Mon Sep 17 00:00:00 2001 From: Ilkka Koskinen Date: Fri, 8 Nov 2024 20:29:45 +0000 Subject: [PATCH 14/19] perf arm-spe: Prepare for adding data source packet implementations for other cores mainline inclusion from mainline-v6.14-rc1 commit ccdc9e9c5ed7af44efaaf9039398998b5f239d64 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccdc9e9c5ed7af44efaaf9039398998b5f239d64 ----------------------------------------------- Split Data Source Packet handling to prepare adding support for other implementations. Reviewed-by: Leo Yan Signed-off-by: Ilkka Koskinen Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Graham Woodward Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Kan Liang Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20241108202946.16835-2-ilkka@os.amperecomputing.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/util/arm-spe.c | 42 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 8613db585064..a76d16c383f5 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -104,6 +104,18 @@ struct arm_spe_queue { u64 period_instructions; }; +struct data_source_handle { + const struct midr_range *midr_ranges; + void (*ds_synth)(const struct arm_spe_record *record, + union perf_mem_data_src *data_src); +}; + +#define DS(range, func) \ + { \ + .midr_ranges = range, \ + .ds_synth = arm_spe__synth_##func, \ + } + static void arm_spe_dump(struct arm_spe *spe __maybe_unused, unsigned char *buf, size_t len) { @@ -518,6 +530,10 @@ static void arm_spe__synth_data_source_common(const struct arm_spe_record *recor } } +static const struct data_source_handle data_source_handles[] = { + DS(common_ds_encoding_cpus, data_source_common), +}; + static void arm_spe__synth_memory_level(const struct arm_spe_record *record, union perf_mem_data_src *data_src) { @@ -541,12 +557,14 @@ static void arm_spe__synth_memory_level(const struct arm_spe_record *record, data_src->mem_lvl |= PERF_MEM_LVL_REM_CCE1; } -static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq) +static bool arm_spe__synth_ds(struct arm_spe_queue *speq, + const struct arm_spe_record *record, + union perf_mem_data_src *data_src) { struct arm_spe *spe = speq->spe; - bool is_in_cpu_list; u64 *metadata = NULL; - u64 midr = 0; + u64 midr; + unsigned int i; /* Metadata version 1 assumes all CPUs are the same (old behavior) */ if (spe->metadata_ver == 1) { @@ -578,18 +596,20 @@ static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq) midr = metadata[ARM_SPE_CPU_MIDR]; } - is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus); - if (is_in_cpu_list) - return true; - else - return false; + for (i = 0; i < ARRAY_SIZE(data_source_handles); i++) { + if (is_midr_in_range_list(midr, data_source_handles[i].midr_ranges)) { + data_source_handles[i].ds_synth(record, data_src); + return true; + } + } + + return false; } static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq, const struct arm_spe_record *record) { union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; - bool is_common = arm_spe__is_common_ds_encoding(speq); /* Only synthesize data source for LDST operations */ if (!is_ldst_op(record->op)) @@ -602,9 +622,7 @@ static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq, else return 0; - if (is_common) - arm_spe__synth_data_source_common(record, &data_src); - else + if (!arm_spe__synth_ds(speq, record, &data_src)) arm_spe__synth_memory_level(record, &data_src); if (record->type & (ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS)) { -- Gitee From f38dd08655c2b8350ed7fcab203d5aad39b0553b Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:42:58 +0100 Subject: [PATCH 15/19] perf arm-spe: Define metadata header version 2 mainline inclusion from mainline-v6.13-rc1 commit 0ca2c45404eed3b6bb80d3169bf672b09cf3a70d category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0ca2c45404eed3b6bb80d3169bf672b09cf3a70d ----------------------------------------------- The first version's metadata header structure doesn't include a field to indicate a header version, which is not friendly for extension. Define the metadata version 2 format with a new header structure and extend per CPU's metadata. In the meantime, the old metadata header will still be supported for backward compatibility. Signed-off-by: Leo Yan Reviewed-by: James Clark Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241003184302.190806-2-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/arch/arm64/util/arm-spe.c | 4 +-- tools/perf/util/arm-spe.c | 2 +- tools/perf/util/arm-spe.h | 38 +++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 9cc3d6dcb849..7b13a448ae43 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -40,7 +40,7 @@ static size_t arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, struct evlist *evlist __maybe_unused) { - return ARM_SPE_AUXTRACE_PRIV_SIZE; + return ARM_SPE_AUXTRACE_V1_PRIV_SIZE; } static int arm_spe_info_fill(struct auxtrace_record *itr, @@ -52,7 +52,7 @@ static int arm_spe_info_fill(struct auxtrace_record *itr, container_of(itr, struct arm_spe_recording, itr); struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; - if (priv_size != ARM_SPE_AUXTRACE_PRIV_SIZE) + if (priv_size != ARM_SPE_AUXTRACE_V1_PRIV_SIZE) return -EINVAL; if (!session->evlist->core.nr_mmaps) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index a76d16c383f5..8fe04d952fd0 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -1520,7 +1520,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event, struct perf_session *session) { struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; - size_t min_sz = sizeof(u64) * ARM_SPE_AUXTRACE_PRIV_MAX; + size_t min_sz = ARM_SPE_AUXTRACE_V1_PRIV_SIZE; struct perf_record_time_conv *tc = &session->time_conv; struct arm_spe *spe; u64 **metadata = NULL; diff --git a/tools/perf/util/arm-spe.h b/tools/perf/util/arm-spe.h index 98d3235781c3..c68c04cae5b5 100644 --- a/tools/perf/util/arm-spe.h +++ b/tools/perf/util/arm-spe.h @@ -12,10 +12,46 @@ enum { ARM_SPE_PMU_TYPE, ARM_SPE_PER_CPU_MMAPS, + ARM_SPE_AUXTRACE_V1_PRIV_MAX, +}; + +#define ARM_SPE_AUXTRACE_V1_PRIV_SIZE \ + (ARM_SPE_AUXTRACE_V1_PRIV_MAX * sizeof(u64)) + +enum { + /* + * The old metadata format (defined above) does not include a + * field for version number. Version 1 is reserved and starts + * from version 2. + */ + ARM_SPE_HEADER_VERSION, + /* Number of sizeof(u64) */ + ARM_SPE_HEADER_SIZE, + /* PMU type shared by CPUs */ + ARM_SPE_PMU_TYPE_V2, + /* Number of CPUs */ + ARM_SPE_CPUS_NUM, ARM_SPE_AUXTRACE_PRIV_MAX, }; -#define ARM_SPE_AUXTRACE_PRIV_SIZE (ARM_SPE_AUXTRACE_PRIV_MAX * sizeof(u64)) +enum { + /* Magic number */ + ARM_SPE_MAGIC, + /* CPU logical number in system */ + ARM_SPE_CPU, + /* Number of parameters */ + ARM_SPE_CPU_NR_PARAMS, + /* CPU MIDR */ + ARM_SPE_CPU_MIDR, + /* Associated PMU type */ + ARM_SPE_CPU_PMU_TYPE, + /* Minimal interval */ + ARM_SPE_CAP_MIN_IVAL, + ARM_SPE_CPU_PRIV_MAX, +}; + +#define ARM_SPE_HEADER_CURRENT_VERSION 2 + union perf_event; struct perf_session; -- Gitee From 24c5b0f26fa20003731c446b6db3acdd95601de7 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:42:59 +0100 Subject: [PATCH 16/19] perf arm-spe: Calculate meta data size mainline inclusion from mainline-v6.13-rc1 commit 59715b1908b051fa3e4c0efb8a3724786d98bc48 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=59715b1908b051fa3e4c0efb8a3724786d98bc48 ----------------------------------------------- The metadata is designed to contain a header and per CPU information. The arm_spe_find_cpus() function is introduced to identify how many CPUs support ARM SPE. Based on the CPU number, calculates the metadata size. Signed-off-by: Leo Yan Reviewed-by: James Clark Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241003184302.190806-3-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/arch/arm64/util/arm-spe.c | 39 +++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 7b13a448ae43..faaa9c3595e3 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -36,11 +36,44 @@ struct arm_spe_recording { bool *wrapped; }; +/* + * arm_spe_find_cpus() returns a new cpu map, and the caller should invoke + * perf_cpu_map__put() to release the map after use. + */ +static struct perf_cpu_map *arm_spe_find_cpus(struct evlist *evlist) +{ + struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus; + struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus(); + struct perf_cpu_map *intersect_cpus; + + /* cpu map is not "any" CPU , we have specific CPUs to work with */ + if (!perf_cpu_map__has_any_cpu(event_cpus)) { + intersect_cpus = perf_cpu_map__intersect(event_cpus, online_cpus); + perf_cpu_map__put(online_cpus); + /* Event can be "any" CPU so count all CPUs. */ + } else { + intersect_cpus = online_cpus; + } + + return intersect_cpus; +} + static size_t arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, - struct evlist *evlist __maybe_unused) + struct evlist *evlist) { - return ARM_SPE_AUXTRACE_V1_PRIV_SIZE; + struct perf_cpu_map *cpu_map = arm_spe_find_cpus(evlist); + size_t size; + + if (!cpu_map) + return 0; + + size = ARM_SPE_AUXTRACE_PRIV_MAX + + ARM_SPE_CPU_PRIV_MAX * perf_cpu_map__nr(cpu_map); + size *= sizeof(u64); + + perf_cpu_map__put(cpu_map); + return size; } static int arm_spe_info_fill(struct auxtrace_record *itr, @@ -52,7 +85,7 @@ static int arm_spe_info_fill(struct auxtrace_record *itr, container_of(itr, struct arm_spe_recording, itr); struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; - if (priv_size != ARM_SPE_AUXTRACE_V1_PRIV_SIZE) + if (priv_size != arm_spe_info_priv_size(itr, session->evlist)) return -EINVAL; if (!session->evlist->core.nr_mmaps) -- Gitee From 7597e45da942b48a3d1c3a2d60fa5d4a78943446 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Thu, 3 Oct 2024 19:43:00 +0100 Subject: [PATCH 17/19] perf arm-spe: Save per CPU information in metadata mainline inclusion from mainline-v6.13-rc1 commit 703f344d0c4a3a006d3e1466d38ee6d8791acd87 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=703f344d0c4a3a006d3e1466d38ee6d8791acd87 ----------------------------------------------- Save the Arm SPE information on a per-CPU basis. This approach is easier in the decoding phase for retrieving metadata based on the CPU number of every Arm SPE record. Signed-off-by: Leo Yan Reviewed-by: James Clark Cc: Will Deacon Cc: Mike Leach Cc: linux-arm-kernel@lists.infradead.org Cc: Besar Wicaksono Cc: John Garry Link: https://lore.kernel.org/r/20241003184302.190806-4-leo.yan@arm.com Signed-off-by: Namhyung Kim Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/arch/arm64/util/arm-spe.c | 83 +++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index faaa9c3595e3..259930684c7f 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -25,6 +25,8 @@ #include "../../../util/arm-spe.h" #include // reallocarray +#define ARM_SPE_CPU_MAGIC 0x1010101010101010ULL + #define KiB(x) ((x) * 1024) #define MiB(x) ((x) * 1024 * 1024) @@ -76,14 +78,70 @@ arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, return size; } +static int arm_spe_save_cpu_header(struct auxtrace_record *itr, + struct perf_cpu cpu, __u64 data[]) +{ + struct arm_spe_recording *sper = + container_of(itr, struct arm_spe_recording, itr); + struct perf_pmu *pmu = NULL; + struct perf_pmu tmp_pmu; + char cpu_id_str[16]; + char *cpuid = NULL; + u64 val; + + snprintf(cpu_id_str, sizeof(cpu_id_str), "%d", cpu.cpu); + tmp_pmu.cpus = perf_cpu_map__new(cpu_id_str); + if (!tmp_pmu.cpus) + return -ENOMEM; + + /* Read CPU MIDR */ + cpuid = perf_pmu__getcpuid(&tmp_pmu); + + /* The CPU map will not be used anymore, release it */ + perf_cpu_map__put(tmp_pmu.cpus); + + if (!cpuid) + return -ENOMEM; + val = strtol(cpuid, NULL, 16); + + data[ARM_SPE_MAGIC] = ARM_SPE_CPU_MAGIC; + data[ARM_SPE_CPU] = cpu.cpu; + data[ARM_SPE_CPU_NR_PARAMS] = ARM_SPE_CPU_PRIV_MAX - ARM_SPE_CPU_MIDR; + data[ARM_SPE_CPU_MIDR] = val; + + /* Find the associate Arm SPE PMU for the CPU */ + if (perf_cpu_map__has(sper->arm_spe_pmu->cpus, cpu)) + pmu = sper->arm_spe_pmu; + + if (!pmu) { + /* No Arm SPE PMU is found */ + data[ARM_SPE_CPU_PMU_TYPE] = ULLONG_MAX; + data[ARM_SPE_CAP_MIN_IVAL] = 0; + } else { + data[ARM_SPE_CPU_PMU_TYPE] = pmu->type; + + if (perf_pmu__scan_file(pmu, "caps/min_interval", "%lu", &val) != 1) + val = 0; + data[ARM_SPE_CAP_MIN_IVAL] = val; + } + + free(cpuid); + return ARM_SPE_CPU_PRIV_MAX; +} + static int arm_spe_info_fill(struct auxtrace_record *itr, struct perf_session *session, struct perf_record_auxtrace_info *auxtrace_info, size_t priv_size) { + int i, ret; + size_t offset; struct arm_spe_recording *sper = container_of(itr, struct arm_spe_recording, itr); struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; + struct perf_cpu_map *cpu_map; + struct perf_cpu cpu; + __u64 *data; if (priv_size != arm_spe_info_priv_size(itr, session->evlist)) return -EINVAL; @@ -91,10 +149,31 @@ static int arm_spe_info_fill(struct auxtrace_record *itr, if (!session->evlist->core.nr_mmaps) return -EINVAL; + cpu_map = arm_spe_find_cpus(session->evlist); + if (!cpu_map) + return -EINVAL; + auxtrace_info->type = PERF_AUXTRACE_ARM_SPE; - auxtrace_info->priv[ARM_SPE_PMU_TYPE] = arm_spe_pmu->type; + auxtrace_info->priv[ARM_SPE_HEADER_VERSION] = ARM_SPE_HEADER_CURRENT_VERSION; + auxtrace_info->priv[ARM_SPE_HEADER_SIZE] = + ARM_SPE_AUXTRACE_PRIV_MAX - ARM_SPE_HEADER_VERSION; + auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2] = arm_spe_pmu->type; + auxtrace_info->priv[ARM_SPE_CPUS_NUM] = perf_cpu_map__nr(cpu_map); + + offset = ARM_SPE_AUXTRACE_PRIV_MAX; + perf_cpu_map__for_each_cpu(cpu, i, cpu_map) { + assert(offset < priv_size); + data = &auxtrace_info->priv[offset]; + ret = arm_spe_save_cpu_header(itr, cpu, data); + if (ret < 0) + goto out; + offset += ret; + } - return 0; + ret = 0; +out: + perf_cpu_map__put(cpu_map); + return ret; } static void -- Gitee From 881bb64a29b3bd74a6cc5e946a322fb0d6cb29af Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Thu, 21 Nov 2024 16:02:51 +0800 Subject: [PATCH 18/19] perf arm-spe: Backport perf_cpu_map__new_online_cpus() driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA ----------------------------------------------- Backport perf_cpu_map__new_online_cpus() which is used in arm_spe_find_cpus(). This function is introduced in mainline thread https://lore.kernel.org/all/20231129060211.1890454-3-irogers@google.com/ Signed-off-by: Yicong Yang Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/perf/arch/arm64/util/arm-spe.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 259930684c7f..7a73c94f39df 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -38,6 +38,29 @@ struct arm_spe_recording { bool *wrapped; }; +static struct perf_cpu_map *cpu_map__new_sysfs_online(void) +{ + struct perf_cpu_map *cpus = NULL; + FILE *onlnf; + + onlnf = fopen("/sys/devices/system/cpu/online", "r"); + if (onlnf) { + cpus = perf_cpu_map__read(onlnf); + fclose(onlnf); + } + return cpus; +} + +static struct perf_cpu_map *perf_cpu_map__new_online_cpus(void) +{ + struct perf_cpu_map *cpus = cpu_map__new_sysfs_online(); + + if (cpus) + return cpus; + + return perf_cpu_map__default_new(); +} + /* * arm_spe_find_cpus() returns a new cpu map, and the caller should invoke * perf_cpu_map__put() to release the map after use. -- Gitee From a2c02ec9b3d78970c30e2f22fbc981be934d268a Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Fri, 25 Apr 2025 11:38:44 +0800 Subject: [PATCH 19/19] perf arm-spe: Add support for SPE Data Source packet on HiSilicon HIP12 mainline inclusion from mainline-v6.16-rc1 commit 846b62b3433d2e87018576ab386f7a96390f66e4 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IDBHTY CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=846b62b3433d2e87018576ab386f7a96390f66e4 ----------------------------------------------- Add data source encoding for HiSilicon HIP12 and coresponding mapping to the perf's memory data source. This will help to synthesize the data and support upper layer tools like perf-mem and perf-c2c. Reviewed-by: Leo Yan Signed-off-by: Yicong Yang Cc: CaiJingtao Cc: Catalin Marinas Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Jonathan Cameron Cc: Junhao He Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: Yushan Wang Cc: Zeng Tao Cc: xueshan2@huawei.com Link: https://lore.kernel.org/r/20250425033845.57671-3-yangyicong@huawei.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Yushan Wang Signed-off-by: Ying Jiang --- tools/arch/arm64/include/asm/cputype.h | 2 + .../util/arm-spe-decoder/arm-spe-decoder.h | 17 ++++ tools/perf/util/arm-spe.c | 96 +++++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h index f40a5d84c74f..62f01cd23180 100644 --- a/tools/arch/arm64/include/asm/cputype.h +++ b/tools/arch/arm64/include/asm/cputype.h @@ -127,6 +127,7 @@ #define FUJITSU_CPU_PART_A64FX 0x001 #define HISI_CPU_PART_TSV110 0xD01 +#define HISI_CPU_PART_HIP12 0xD06 #define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_FIRESTORM 0x023 @@ -199,6 +200,7 @@ #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) +#define MIDR_HISI_HIP12 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP12) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 358c611eeddb..33d832a80e78 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -67,6 +67,23 @@ enum arm_spe_common_data_source { ARM_SPE_COMMON_DS_DRAM = 0xe, }; +enum arm_spe_hisi_hip_data_source { + ARM_SPE_HISI_HIP_PEER_CPU = 0, + ARM_SPE_HISI_HIP_PEER_CPU_HITM = 1, + ARM_SPE_HISI_HIP_L3 = 2, + ARM_SPE_HISI_HIP_L3_HITM = 3, + ARM_SPE_HISI_HIP_PEER_CLUSTER = 4, + ARM_SPE_HISI_HIP_PEER_CLUSTER_HITM = 5, + ARM_SPE_HISI_HIP_REMOTE_SOCKET = 6, + ARM_SPE_HISI_HIP_REMOTE_SOCKET_HITM = 7, + ARM_SPE_HISI_HIP_LOCAL_MEM = 8, + ARM_SPE_HISI_HIP_REMOTE_MEM = 9, + ARM_SPE_HISI_HIP_NC_DEV = 13, + ARM_SPE_HISI_HIP_L2 = 16, + ARM_SPE_HISI_HIP_L2_HITM = 17, + ARM_SPE_HISI_HIP_L1 = 18, +}; + struct arm_spe_record { enum arm_spe_sample_type type; int err; diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 8fe04d952fd0..c4f621eb7f59 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -454,6 +454,11 @@ static const struct midr_range common_ds_encoding_cpus[] = { {}, }; +static const struct midr_range hisi_hip_ds_encoding_cpus[] = { + MIDR_ALL_VERSIONS(MIDR_HISI_HIP12), + {}, +}; + static void arm_spe__synth_data_source_common(const struct arm_spe_record *record, union perf_mem_data_src *data_src) { @@ -530,8 +535,99 @@ static void arm_spe__synth_data_source_common(const struct arm_spe_record *recor } } +static void arm_spe__synth_data_source_hisi_hip(const struct arm_spe_record *record, + union perf_mem_data_src *data_src) +{ + /* Use common synthesis method to handle store operations */ + if (record->op & ARM_SPE_OP_ST) { + arm_spe__synth_data_source_common(record, data_src); + return; + } + + switch (record->source) { + case ARM_SPE_HISI_HIP_PEER_CPU: + data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_PEER_CPU_HITM: + data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_L3: + data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; + data_src->mem_snoop = PERF_MEM_SNOOP_HIT; + break; + case ARM_SPE_HISI_HIP_L3_HITM: + data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + break; + case ARM_SPE_HISI_HIP_PEER_CLUSTER: + data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_PEER_CLUSTER_HITM: + data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_REMOTE_SOCKET: + data_src->mem_lvl = PERF_MEM_LVL_REM_CCE2; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; + data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_REMOTE_SOCKET_HITM: + data_src->mem_lvl = PERF_MEM_LVL_REM_CCE2; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; + data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; + break; + case ARM_SPE_HISI_HIP_LOCAL_MEM: + data_src->mem_lvl = PERF_MEM_LVL_LOC_RAM | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + break; + case ARM_SPE_HISI_HIP_REMOTE_MEM: + data_src->mem_lvl = PERF_MEM_LVL_REM_RAM1 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; + data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; + break; + case ARM_SPE_HISI_HIP_NC_DEV: + data_src->mem_lvl = PERF_MEM_LVL_IO | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_IO; + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + break; + case ARM_SPE_HISI_HIP_L2: + data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + break; + case ARM_SPE_HISI_HIP_L2_HITM: + data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + break; + case ARM_SPE_HISI_HIP_L1: + data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; + data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1; + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + break; + default: + break; + } +} + static const struct data_source_handle data_source_handles[] = { DS(common_ds_encoding_cpus, data_source_common), + DS(hisi_hip_ds_encoding_cpus, data_source_hisi_hip), }; static void arm_spe__synth_memory_level(const struct arm_spe_record *record, -- Gitee