From nobody Sun Jun 14 07:35:50 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF09A40FDA8 for ; Fri, 1 May 2026 18:20:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659631; cv=none; b=niDOddvtv/a/EPEDbUsOldUz/tyda8bYbNjqehZ0RcpWoCEUKQhedWArlby262z+tcWZOkudI7wsdkQ5OEenSx/PTgccXSn+fUR+J17z5XvMm2aogz0IJH+vEu0N1OVXXIHObZPH1AXo42x8Gxc2TMY5ZNPl0kctoeAocr6dG7c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659631; c=relaxed/simple; bh=5kvUlmCfHm3OIANXNzvUbizuHSm5xhdWMCwQeAJu2yc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qkT6A+cXPMHDRA9UKlB3Msu8pjwfFW0uxrXGCLAO9FGRQ3hvFeP6SC8qfwUDCb/H9pMJmdal98ddyC+UqRK1p/uIjDbnsJNCL52SiGsiw0nwnU7evM2Fm/NVPHF1EX50tBzqhjTDjZDBUnK2L6Q29Crv0piFfUI6gZiCRvD5H8U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gj2oU3kE; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gj2oU3kE" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-12dfdde7ce7so59008c88.1 for ; Fri, 01 May 2026 11:20:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777659629; x=1778264429; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=1E3XrgoGg8Gn6qjWpXRZdhkqAyFGP/uBkNcWZfisKxs=; b=gj2oU3kE/cwLDUHDS88MW1VZ07lNA0DbNceCgxIpHXw2djmGCfj4hF2xBbMUO7d2Ol aAkTU4gkU2TZO1u8Tfyg1nsVhMjuzoQ+/0VUjdjlplYhExM1/CsH60uJu1Yn9vkQiVQf 3LrCPEMJ2nwaEjuqomfwu8qA7/YoYtVVLQrAqB+NhPymCsiMQ4SkddWArZh4262jCQfi YMrGrdVcFieAO3unCDS16DJBTOMxtNQMRVhSEH59z9rtOxtoj6UabxDUR1YXWY/DDTsH +eoqcNHWfhtHXgcRrJnSN5/SlJIdtIpZjAH2pQyyXMh0/RS69DTok8a2gBDVJGsO+O5O SCGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777659629; x=1778264429; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1E3XrgoGg8Gn6qjWpXRZdhkqAyFGP/uBkNcWZfisKxs=; b=VeP+kvaVOBK6zgInit8czZTFTfsBmESOoeFnDlmNI0c2jjeqONgiQigQqtaAhICyf/ s8/KkdBtO+O7o4/NuN27gfrOqFsmJ14Sw3HcIwwJVKi+0VC7Ofhf9J7HS0nrF3vx/3lR QSGzbz44qRzdumVzF+AC/0h7BCFgYee2DDuiLGsupGzUpndhN6NEEfrayrMuxZzkyGgS aPp/g+cMzTTgl8Il26bjxoDJysYVFw9yUDOHJ5/pcVIUlOOvTu+KEB2V6gIblzTbvKHP ZJBuGFJwno4YcN9o4p7gvhCRHV5WuUkgNN7PtRv7KaT8dmnWiLFRkPcNASB05/MqTzYR LzGw== X-Forwarded-Encrypted: i=1; AFNElJ/oIwmbupHS4bw1pDc7NNnhLNT+960ePrfDZjpvTlx/pT9MWpWsj+3Q7MDpCLyV4gl6q61hZVzDY3K0kEQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yyf5CenVBEu83/cBuLmE2uI4DLPabNMdIuu8xXdX+wmE/bc32B2 EWDYZw+6U8SqXQkpZADFghcRUAArSUF5HwjCOIf98EDkSaLCRDJCzXzDjXsOcwe8uT6IiorePjk eCtBpi0x4xA== X-Received: from dlag5.prod.google.com ([2002:a05:701b:2505:b0:12d:dbf8:a2a8]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:f9c:b0:12d:de3f:d843 with SMTP id a92af1059eb24-12dfd876063mr161957c88.38.1777659628823; Fri, 01 May 2026 11:20:28 -0700 (PDT) Date: Fri, 1 May 2026 11:20:18 -0700 In-Reply-To: <20260501182021.3651851-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260409230620.4176210-2-irogers@google.com> <20260501182021.3651851-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <20260501182021.3651851-2-irogers@google.com> Subject: [PATCH v7 1/4] perf env: Add perf_env__e_machine helper and use in perf_env__arch From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org, tmricht@linux.ibm.com Cc: agordeev@linux.ibm.com, gor@linux.ibm.com, hca@linux.ibm.com, jameshongleiwang@126.com, japo@linux.ibm.com, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-s390@vger.kernel.org, sumanthk@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a helper that lazily computes the e_machine and falls back of EM_HOST. Use the perf_env's arch to compute the e_machine if available. Use a binary search for some efficiency in this, but handle somewhat complex duplicate rules. Switch perf_env__arch to be derived the e_machine for consistency. This switches arch from being uname derived to matching that of the perf binary (via EM_HOST). Update session to use the helper, which may mean using EM_HOST when no threads are available. This also updates the perf data file header that gets the e_machine/e_flags from the session. Signed-off-by: Ian Rogers --- tools/perf/util/env.c | 197 +++++++++++++++++++++++++++++++------- tools/perf/util/env.h | 1 + tools/perf/util/header.c | 47 +++++++-- tools/perf/util/session.c | 25 ++--- 4 files changed, 212 insertions(+), 58 deletions(-) diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 1e54e2c86360..1671769d4441 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 #include "cpumap.h" +#include "dwarf-regs.h" #include "debug.h" #include "env.h" #include "util/header.h" #include "util/rwsem.h" #include +#include #include #include #include @@ -588,51 +590,172 @@ void cpu_cache_level__free(struct cpu_cache_level *c= ache) zfree(&cache->size); } =20 +struct arch_to_e_machine { + const char *prefix; + uint16_t e_machine; +}; + /* - * Return architecture name in a normalized form. - * The conversion logic comes from the Makefile. + * A mapping from an arch prefix string to an ELF machine that can be used= in a + * bsearch. Some arch prefixes are shared an need additional processing as + * marked next to the architecture. The prefixes handle both perf's archit= ecture + * naming and those from uname. */ -static const char *normalize_arch(char *arch) -{ - if (!strcmp(arch, "x86_64")) - return "x86"; - if (arch[0] =3D=3D 'i' && arch[2] =3D=3D '8' && arch[3] =3D=3D '6') - return "x86"; - if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) - return "sparc"; - if (!strncmp(arch, "aarch64", 7) || !strncmp(arch, "arm64", 5)) - return "arm64"; - if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) - return "arm"; - if (!strncmp(arch, "s390", 4)) - return "s390"; - if (!strncmp(arch, "parisc", 6)) - return "parisc"; - if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3)) - return "powerpc"; - if (!strncmp(arch, "mips", 4)) - return "mips"; - if (!strncmp(arch, "sh", 2) && isdigit(arch[2])) - return "sh"; - if (!strncmp(arch, "loongarch", 9)) - return "loongarch"; - - return arch; +static const struct arch_to_e_machine prefix_to_e_machine[] =3D { + {"aarch64", EM_AARCH64}, + {"alpha", EM_ALPHA}, + {"arc", EM_ARC}, + {"arm", EM_ARM}, /* Check also for EM_AARCH64. */ + {"avr", EM_AVR}, /* Check also for EM_AVR32. */ + {"bfin", EM_BLACKFIN}, + {"blackfin", EM_BLACKFIN}, + {"cris", EM_CRIS}, + {"csky", EM_CSKY}, + {"hppa", EM_PARISC}, + {"i386", EM_386}, + {"i486", EM_386}, + {"i586", EM_386}, + {"i686", EM_386}, + {"loongarch", EM_LOONGARCH}, + {"m32r", EM_M32R}, + {"m68k", EM_68K}, + {"microblaze", EM_MICROBLAZE}, + {"mips", EM_MIPS}, + {"msp430", EM_MSP430}, + {"parisc", EM_PARISC}, + {"powerpc", EM_PPC}, /* Check also for EM_PPC64. */ + {"ppc", EM_PPC}, /* Check also for EM_PPC64. */ + {"riscv", EM_RISCV}, + {"s390", EM_S390}, + {"sa110", EM_ARM}, + {"sh", EM_SH}, + {"sparc", EM_SPARC}, /* Check also for EM_SPARCV9. */ + {"sun4u", EM_SPARC}, + {"x86", EM_X86_64}, /* Check also for EM_386. */ + {"xtensa", EM_XTENSA}, +}; + +static int compare_prefix(const void *key, const void *element) +{ + const char *search_key =3D key; + const struct arch_to_e_machine *map_element =3D element; + size_t prefix_len =3D strlen(map_element->prefix); + + return strncmp(search_key, map_element->prefix, prefix_len); +} + +static uint16_t perf_arch_to_e_machine(const char *perf_arch, int is_64_bi= t) +{ + /* Binary search for a matching prefix. */ + const struct arch_to_e_machine *result; + + if (!perf_arch) + return EM_HOST; + + result =3D bsearch(perf_arch, + prefix_to_e_machine, ARRAY_SIZE(prefix_to_e_machine), + sizeof(prefix_to_e_machine[0]), + compare_prefix); + + if (!result) { + pr_debug("Unknown perf arch for ELF machine mapping: %s\n", perf_arch); + return EM_NONE; + } + + /* + * Handle conflicting prefixes. If the is_64_bit is unknown (-1) then + * assume 64-bit. We can't use perf_env__kernel_is_64_bit as that + * depends on the arch string. + */ + switch (result->e_machine) { + case EM_ARM: + return !strcmp(perf_arch, "arm64") ? EM_AARCH64 : EM_ARM; + case EM_AVR: + return !strcmp(perf_arch, "avr32") ? EM_AVR32 : EM_AVR; + case EM_PPC: + return (is_64_bit !=3D 0) || strstarts(perf_arch, "ppc64") ? EM_PPC64 : = EM_PPC; + case EM_SPARC: + return (is_64_bit !=3D 0) || !strcmp(perf_arch, "sparc64") ? EM_SPARCV9 = : EM_SPARC; + case EM_X86_64: + return (is_64_bit !=3D 0) || !strcmp(perf_arch, "x86_64") ? EM_X86_64 : = EM_386; + default: + return result->e_machine; + } +} + +static const char *e_machine_to_perf_arch(uint16_t e_machine) +{ + /* + * Table for if either the perf arch string differs from uname or there + * are >1 ELF machine with the prefix. + */ + static const struct arch_to_e_machine extras[] =3D { + {"arm64", EM_AARCH64}, + {"avr32", EM_AVR32}, + {"powerpc", EM_PPC}, + {"powerpc", EM_PPC64}, + {"sparc", EM_SPARCV9}, + {"x86", EM_386}, + {"x86", EM_X86_64}, + {"none", EM_NONE}, + }; + + for (size_t i =3D 0; i < ARRAY_SIZE(extras); i++) { + if (extras[i].e_machine =3D=3D e_machine) + return extras[i].prefix; + } + + for (size_t i =3D 0; i < ARRAY_SIZE(prefix_to_e_machine); i++) { + if (prefix_to_e_machine[i].e_machine =3D=3D e_machine) + return prefix_to_e_machine[i].prefix; + + } + return "unknown"; +} + +uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags) +{ + if (!env) { + if (e_flags) + *e_flags =3D EF_HOST; + + return EM_HOST; + } + if (env->e_machine =3D=3D EM_NONE) { + env->e_machine =3D perf_arch_to_e_machine(env->arch, env->kernel_is_64_b= it); + + if (env->e_machine =3D=3D EM_HOST) + env->e_flags =3D EF_HOST; + } + if (e_flags) + *e_flags =3D env->e_flags; + + return env->e_machine; } =20 const char *perf_env__arch(struct perf_env *env) { - char *arch_name; + uint16_t e_machine; + const char *arch; =20 - if (!env || !env->arch) { /* Assume local operation */ - static struct utsname uts =3D { .machine[0] =3D '\0', }; - if (uts.machine[0] =3D=3D '\0' && uname(&uts) < 0) - return NULL; - arch_name =3D uts.machine; - } else - arch_name =3D env->arch; + if (!env) + return e_machine_to_perf_arch(EM_HOST); + + if (env->arch) + return env->arch; =20 - return normalize_arch(arch_name); + /* + * Lazily compute/allocate arch. The e_machine may have been + * read from a data file and so may not be EM_HOST. + */ + e_machine =3D perf_env__e_machine(env, /*e_flags=3D*/NULL); + arch =3D e_machine_to_perf_arch(e_machine); + env->arch =3D strdup(arch); + /* + * Avoid potential crashes on the arch string if memory allocation in + * strdup fails and NULL were to be returned. + */ + return env->arch ?: arch; } =20 #if defined(HAVE_LIBTRACEEVENT) diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index c7052ac1f856..d36a0fb2cd04 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -187,6 +187,7 @@ int perf_env__read_cpu_topology_map(struct perf_env *en= v); =20 void cpu_cache_level__free(struct cpu_cache_level *cache); =20 +uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags); const char *perf_env__arch(struct perf_env *env); const char *perf_env__arch_strerrno(struct perf_env *env, int err); const char *perf_env__cpuid(struct perf_env *env); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f30e48eb3fc3..8d5152bde25d 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -379,21 +379,28 @@ static int write_osrelease(struct feat_fd *ff, return do_write_string(ff, uts.release); } =20 -static int write_arch(struct feat_fd *ff, - struct evlist *evlist __maybe_unused) +static int write_arch(struct feat_fd *ff, struct evlist *evlist) { struct utsname uts; - int ret; + const char *arch =3D NULL; =20 - ret =3D uname(&uts); - if (ret < 0) - return -1; + if (evlist->session) { + /* Force the computation in the perf_env of the e_machine of the threads= . */ + perf_session__e_machine(evlist->session, /*e_flags=3D*/NULL); + arch =3D perf_env__arch(perf_session__env(evlist->session)); + } + + if (!arch) { + int ret =3D uname(&uts); =20 - return do_write_string(ff, uts.machine); + if (ret < 0) + return -1; + arch =3D uts.machine; + } + return do_write_string(ff, arch); } =20 -static int write_e_machine(struct feat_fd *ff, - struct evlist *evlist __maybe_unused) +static int write_e_machine(struct feat_fd *ff, struct evlist *evlist) { /* e_machine expanded from 16 to 32-bits for alignment. */ uint32_t e_flags; @@ -2684,10 +2691,30 @@ static int process_##__feat(struct feat_fd *ff, voi= d *data __maybe_unused) \ FEAT_PROCESS_STR_FUN(hostname, hostname); FEAT_PROCESS_STR_FUN(osrelease, os_release); FEAT_PROCESS_STR_FUN(version, version); -FEAT_PROCESS_STR_FUN(arch, arch); FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc); FEAT_PROCESS_STR_FUN(cpuid, cpuid); =20 +static int process_arch(struct feat_fd *ff, void *data __maybe_unused) +{ + uint16_t saved_e_machine =3D ff->ph->env.e_machine; + + free(ff->ph->env.arch); + ff->ph->env.arch =3D do_read_string(ff); + if (!ff->ph->env.arch) + return -ENOMEM; + /* + * Make the arch string canonical by computing the e_machine from it, + * then turning the e_machine back into an arch string. + */ + ff->ph->env.e_machine =3D EM_NONE; + if (perf_env__e_machine(&ff->ph->env, /*e_flags=3D*/NULL) !=3D EM_NONE) { + zfree(&ff->ph->env.arch); + perf_env__arch(&ff->ph->env); + } + ff->ph->env.e_machine =3D saved_e_machine; + return 0; +} + static int process_e_machine(struct feat_fd *ff, void *data __maybe_unused) { int ret; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index fe0de2a0277f..bc7add02a2de 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -3023,14 +3023,19 @@ uint16_t perf_session__e_machine(struct perf_sessio= n *session, uint32_t *e_flags return EM_HOST; } =20 + /* + * Is the env caching an e_machine? If not we want to compute from the + * more accurate threads. + */ env =3D perf_session__env(session); - if (env && env->e_machine !=3D EM_NONE) { - if (e_flags) - *e_flags =3D env->e_flags; - - return env->e_machine; - } + if (env && env->e_machine !=3D EM_NONE) + return perf_env__e_machine(env, e_flags); =20 + /* + * Compute from threads, note this is more accurate than + * perf_env__e_machine that falls back on EM_HOST and doesn't consider + * mixed 32-bit and 64-bit threads. + */ machines__for_each_thread(&session->machines, perf_session__e_machine_cb, &args); @@ -3048,10 +3053,8 @@ uint16_t perf_session__e_machine(struct perf_session= *session, uint32_t *e_flags =20 /* * Couldn't determine from the perf_env or current set of - * threads. Default to the host. + * threads. Potentially use logic that uses the arch string otherwise + * default to the host. */ - if (e_flags) - *e_flags =3D EF_HOST; - - return EM_HOST; + return perf_env__e_machine(env, e_flags); } --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 07:35:50 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC47E41B35C for ; Fri, 1 May 2026 18:20:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659633; cv=none; b=f0pUZMPLi8gEe0ylekzL/g8uMbolngvT9CEGJSWiAC2//nyeuWn+oS55bW3i6dxKOz549idzf51l4tZOPBnHHCnO3gAY32wzgonbPWZ5Uusxwz37BVdPspA6amDn+KfUl5jUEU+8mZ0z7UAx98N9deRPlZ+PZGDIk9fcFqG9IDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659633; c=relaxed/simple; bh=BDB2js4drqE6QfRtGJB3JwcQVzwBxzVRr/iaZN1OkTg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=n1C2EHWPIFiqlBD+qcJkp+XrDJ+ro+3Ks03Ydmx60cluAk1MyMpraxpZHDEpXOwsvx7KRNhVhyr7BKEOUa63BKF98ZIEFAEI9X7k9gMEDHbP4ShT71oltUWNQV/eFIeiBxpCRVLwfvPI3rego3hV7bKpDhLEpPPEd3brN8yO/JY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=FkAafez3; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FkAafez3" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2ba8013a9e3so3484142eec.0 for ; Fri, 01 May 2026 11:20:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777659631; x=1778264431; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Ca7k0d6Hn6jB3V8PRr9BUGUU/CgyMEw9LXb9LFro2BA=; b=FkAafez3SAaT7ysrZA5JlGfYIIupLXO2sjt4t4/mh++WqqSt88iC36+Bl459AJ3SKp HlBGTv6VYoIeSbWhAeVd3zDpBC0LttRArFE1t2687gqKqAHZtq4x4ofzDRwZVdIWYs5z E3ugeb7Wmk/gkcrHxVGIfPpCaClkkqixeEg51NdUoLHts4P6F2Lun3euvzXaPpaoBPNG HxW2/JzrYw7j98kqIBo72tqL+T7LOFNn9NmsjE8/iUK3HwDeT1ecqBLMBkjrl775cMO7 9Gr+xTQBB8awWtTQm90ZxSXCfWa0KjycN7oY3do7GPALyjpCMzD986Tr6PKVZqmgLa7Y zj+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777659631; x=1778264431; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Ca7k0d6Hn6jB3V8PRr9BUGUU/CgyMEw9LXb9LFro2BA=; b=KoVgmZNPSBptdBvSJeX98c45HixalB+CPg6wkirIuS3FHOzFh1b3hXCFvmLY5EP2qV 9Z4Qr9MmaAS5t83Wv6OnzzUNa2Tvik0xtUnbeBlwLLP6XmwRIyRJF2QXJwxdzjlI4sRM xD3F2KpGU9eSWQCbx38hyGeuwGz5+t4F2Bf2Xr4HepwRWSrhJr0ju4R4YjxecxoU95mU nxLZbqlob4wSzsjZMoZbq5tsKPEEILxkf3G6nH7NubAu6ovIm2UseF+ALlUAI3GYnuu3 tHKTmDcT9D902v5/vMQCJnPgzX5Lc+38lmm36bEQubZNAzDIncPK+LqIqM/sWfiAIh5z Ms6w== X-Forwarded-Encrypted: i=1; AFNElJ+2d+jpPOsN/eoRpjg+8x8e4hK5z2qoVxRxd3zscNF6ZEBoi6svii4COJwlputYZrRIhvhqpOK3013+akw=@vger.kernel.org X-Gm-Message-State: AOJu0YzoPOf5F4EaxmFPgMMnHmzbWAFrQUqY4FVg14XR1VJQ5FWPv1oX PHQM4W7QEzd+N6bvlmAjNERpmejmwOpD1pp6B+RhXvpaeWbOOqTfNnuAUnfLXnoQM5uFRRkrocT xjpR/fP1QOA== X-Received: from dycue4.prod.google.com ([2002:a05:7300:84:b0:2d1:6536:ac8a]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:f194:b0:2e2:a4ba:84ae with SMTP id 5a478bee46e88-2efba28b2f0mr191995eec.25.1777659630551; Fri, 01 May 2026 11:20:30 -0700 (PDT) Date: Fri, 1 May 2026 11:20:19 -0700 In-Reply-To: <20260501182021.3651851-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260409230620.4176210-2-irogers@google.com> <20260501182021.3651851-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <20260501182021.3651851-3-irogers@google.com> Subject: [PATCH v7 2/4] perf env: Add helper to lazily compute the os_release From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org, tmricht@linux.ibm.com Cc: agordeev@linux.ibm.com, gor@linux.ibm.com, hca@linux.ibm.com, jameshongleiwang@126.com, japo@linux.ibm.com, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-s390@vger.kernel.org, sumanthk@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In live mode the os_release isn't being initialized, make a lazy initialization helper that assumes when the os_release isn't initialized this is live mode. Signed-off-by: Ian Rogers --- tools/perf/util/data-convert-bt.c | 2 +- tools/perf/util/env.c | 21 +++++++++++++++++++++ tools/perf/util/env.h | 1 + tools/perf/util/header.c | 16 +++++++++++----- tools/perf/util/symbol.c | 4 ++-- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-conve= rt-bt.c index 3b8f2df823a9..2c88420fe33e 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -1414,7 +1414,7 @@ do { \ =20 ADD("host", env->hostname); ADD("sysname", "Linux"); - ADD("release", env->os_release); + ADD("release", perf_env__os_release(env)); ADD("version", env->version); ADD("machine", env->arch); ADD("domain", "kernel"); diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 1671769d4441..c3e464c6de2f 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -330,6 +330,27 @@ int perf_env__kernel_is_64_bit(struct perf_env *env) return env->kernel_is_64_bit; } =20 +const char *perf_env__os_release(struct perf_env *env) +{ + struct utsname uts; + int ret; + + if (!env) + return perf_version_string; + + if (env->os_release) + return env->os_release; + + /* + * The os_release is being accessed but wasn't initialized from a data + * file, assume this is 'live' mode and use the release from uname. If + * uname or strdup fails then use the current perf tool version. + */ + ret =3D uname(&uts); + env->os_release =3D strdup(ret < 0 ? perf_version_string : uts.release); + return env->os_release ?: perf_version_string; +} + int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv= []) { int i; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index d36a0fb2cd04..56020f4381cd 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -175,6 +175,7 @@ void free_cpu_domain_info(struct cpu_domain_map **cd_ma= p, u32 schedstat_version, void perf_env__exit(struct perf_env *env); =20 int perf_env__kernel_is_64_bit(struct perf_env *env); +const char *perf_env__os_release(struct perf_env *env); =20 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv= []); =20 diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 8d5152bde25d..cfafed3cc69f 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -370,13 +370,19 @@ static int write_osrelease(struct feat_fd *ff, struct evlist *evlist __maybe_unused) { struct utsname uts; - int ret; + const char *release =3D NULL; =20 - ret =3D uname(&uts); - if (ret < 0) - return -1; + if (evlist->session) + release =3D perf_env__os_release(perf_session__env(evlist->session)); =20 - return do_write_string(ff, uts.release); + if (!release) { + int ret =3D uname(&uts); + + if (ret < 0) + return -1; + release =3D uts.release; + } + return do_write_string(ff, release); } =20 static int write_arch(struct feat_fd *ff, struct evlist *evlist) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fcaeeddbbb6b..fd332db56157 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2209,7 +2209,7 @@ static int vmlinux_path__init(struct perf_env *env) { struct utsname uts; char bf[PATH_MAX]; - char *kernel_version; + const char *kernel_version; unsigned int i; =20 vmlinux_path =3D malloc(sizeof(char *) * (ARRAY_SIZE(vmlinux_paths) + @@ -2226,7 +2226,7 @@ static int vmlinux_path__init(struct perf_env *env) return 0; =20 if (env) { - kernel_version =3D env->os_release; + kernel_version =3D perf_env__os_release(env); } else { if (uname(&uts) < 0) goto out_fail; --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 07:35:50 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A330F40F8DC for ; Fri, 1 May 2026 18:20:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659636; cv=none; b=fz/7f61L+7dOThhCjeHSbmLajOQzO4yCG5PlrxwCa6d6mGUpQMdChZf7IJ7twjdYXL+t0G/fUTJU9jTFlpOBvPVRiM8gEdaSBtfrkFQ+xAjCbS/ypXmlkuTDZONRmCLsqCpnhX/2v2naQz7xWvSpiiHCr+TJXeAPoWUR14NchoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659636; c=relaxed/simple; bh=jSVLm/hnBbimnPznGWy7hEl7PRSNrGRNHmI3giDWJ48=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T8SuSESjDD283CH4ZaxUyInGU4mJiYY7Vd8fbdK3tU797+4QGzJJ2rQO+71Gz+pfFIcgkAyWpnG3Gly2g2er6QCeRxr+U87cKcmuJqu2E7ZJXQGqIsYmPQ6IEFP5/tkuSIxJz1K4G2tNF9OUYl8njcyLK4fYu8RnrOgBu/IILxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=pYjhck1Q; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="pYjhck1Q" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-12c726f4055so3646981c88.1 for ; Fri, 01 May 2026 11:20:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777659633; x=1778264433; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tsujg9g6KcaFNFnJNN1/Y10jrPhP9zpCu+VlfQAKK4Y=; b=pYjhck1QovBlAPHXlzfzMGrtum7XOj3HBOQsjF5+/3e/yXbnRoUf8M0Xxfv6i6xJr2 tWX6Msux1/Kka40v0hO3KRou2V2LcGqPfvZAAxN7TjHytQoXcZ05mDowM1vPlBbXeSmm j8zXmAkKgubsL8l4XSd/B4OqIlxKWlNhM4eQjyawhgkZRD7TxfNjOmqNgtrTU3aKeeJ3 d7INZQ49lWw7nigp7M33mAiP8vRVCL5hDHu0wG4DjOmq3311EM3yQZUs2TQkYTF9T3y8 08eRVJHNyPDNuYE4AcQ68/HStdYDO/neA8ZQ3tzEU3tPf1F7ps1tA6qAR2IxY1db3EdL aasg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777659633; x=1778264433; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tsujg9g6KcaFNFnJNN1/Y10jrPhP9zpCu+VlfQAKK4Y=; b=Rurh1MtIbla/3Q6/ruDJ2tKZ1A6FkKcG/18pbwUZ0mqUvCsTKUtWd3QzMMgvePbsgl gBjqv0pFvGXwEUnd1sLOsesFY7YXH1XkimwcGrcI5dEYlFsUSr6A8SyTnhAJ+gSsva00 lOEeg0gV1Ni/nZ4ogYn/iAvKd5PrQurMQhXyPQ4nPMtUj/VqaWxI+V5JfHL9k+m2RFJT IOxH8tzPod9l8B7M2BUCpzOCT5jDrfzfj2lNl+FPxoiW+Yc4BOiSmUzzTq3sapJiEzja 22xFvRpRne1MVXK49cLtey80sKvyO4s7BhziBrdoPlP92HshYkhmm1+J0GprFtqINCOY Eu/Q== X-Forwarded-Encrypted: i=1; AFNElJ+9iCguQmpH6zqBVh4MK5DzXK6IXF9lnoRv8FC6BknASu3WKF2Ra7JCQqE3+AwQ1hOf/0V4/7WFXLiaE+w=@vger.kernel.org X-Gm-Message-State: AOJu0YyoWR7C5iR4peuEtOXGUjdYIXwhnjYFkSzBG1vxRCL9QguXtS5p k4SquC1DaVdQzDAVfR63xUktviMW1DYCUsF0z23X7PMEL63Az4Eh44w8ALGnhvdAlTS7xQHOeud h7p075KFLEg== X-Received: from dleb6-n1.prod.google.com ([2002:a05:701b:4246:10b0:12a:9ef0:93ed]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:427:b0:12b:ec15:69d2 with SMTP id a92af1059eb24-12dfd8622dcmr180034c88.33.1777659632579; Fri, 01 May 2026 11:20:32 -0700 (PDT) Date: Fri, 1 May 2026 11:20:20 -0700 In-Reply-To: <20260501182021.3651851-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260409230620.4176210-2-irogers@google.com> <20260501182021.3651851-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <20260501182021.3651851-4-irogers@google.com> Subject: [PATCH v7 3/4] perf symbol: Add setters for bitfields sharing a byte to avoid concurrent update issues From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org, tmricht@linux.ibm.com Cc: agordeev@linux.ibm.com, gor@linux.ibm.com, hca@linux.ibm.com, jameshongleiwang@126.com, japo@linux.ibm.com, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-s390@vger.kernel.org, sumanthk@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A problem with putting bitfields into struct symbol is that other bits in the symbol could be updated concurrently and only one update to the underlying storage unit happen, leading to lost updates. To avoid this, introduce a global lock `symbol_bits_lock` in `symbol.c` and helper functions to update the bits sharing a byte: `symbol__set_ignore` and `symbol__set_annotate2`. `inlined` is not given a setter as it is only initialized in `new_inline_sym` when the symbol is under construction and not shared. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers --- tools/perf/builtin-kwork.c | 2 +- tools/perf/builtin-sched.c | 2 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/symbol.c | 22 ++++++++++++++++++++++ tools/perf/util/symbol.h | 3 +++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 9d3a4c779a41..7337ee956dc9 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -725,7 +725,7 @@ static void timehist_save_callchain(struct perf_kwork *= kwork, if (sym) { if (!strcmp(sym->name, "__softirqentry_text_start") || !strcmp(sym->name, "__do_softirq")) - sym->ignore =3D 1; + symbol__set_ignore(sym, true); } =20 callchain_cursor_advance(cursor); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 555247568e7a..655e95f660c2 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2371,7 +2371,7 @@ static void save_task_callchain(struct perf_sched *sc= hed, if (!strcmp(sym->name, "schedule") || !strcmp(sym->name, "__schedule") || !strcmp(sym->name, "preempt_schedule")) - sym->ignore =3D 1; + symbol__set_ignore(sym, true); } =20 callchain_cursor_advance(cursor); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index e745f3034a0e..d550a0061159 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2224,7 +2224,7 @@ int symbol__annotate2(struct map_symbol *ms, struct e= vsel *evsel, =20 annotation__init_column_widths(notes, sym); annotation__update_column_widths(notes); - sym->annotate2 =3D 1; + symbol__set_annotate2(sym, true); =20 return 0; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fd332db56157..e6a1f23634ec 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -31,6 +31,7 @@ #include "map.h" #include "symbol.h" #include "map_symbol.h" +#include "mutex.h" #include "mem-events.h" #include "mem-info.h" #include "symsrc.h" @@ -52,6 +53,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct m= ap *map); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map); static bool symbol__is_idle(const char *name); =20 +static struct mutex symbol_bits_lock; + int vmlinux_path__nr_entries; char **vmlinux_path; =20 @@ -345,6 +348,20 @@ void symbol__delete(struct symbol *sym) free(((void *)sym) - symbol_conf.priv_size); } =20 +void symbol__set_ignore(struct symbol *sym, bool ignore) +{ + mutex_lock(&symbol_bits_lock); + sym->ignore =3D ignore; + mutex_unlock(&symbol_bits_lock); +} + +void symbol__set_annotate2(struct symbol *sym, bool annotate2) +{ + mutex_lock(&symbol_bits_lock); + sym->annotate2 =3D annotate2; + mutex_unlock(&symbol_bits_lock); +} + void symbols__delete(struct rb_root_cached *symbols) { struct symbol *pos; @@ -2398,6 +2415,8 @@ int symbol__init(struct perf_env *env) if (symbol_conf.initialized) return 0; =20 + mutex_init(&symbol_bits_lock); + symbol_conf.priv_size =3D PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); =20 symbol__elf_init(); @@ -2476,6 +2495,9 @@ void symbol__exit(void) { if (!symbol_conf.initialized) return; + + mutex_destroy(&symbol_bits_lock); + strlist__delete(symbol_conf.bt_stop_list); strlist__delete(symbol_conf.sym_list); strlist__delete(symbol_conf.dso_list); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index bd6eb90c8668..5d98d7e84d57 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -77,6 +77,9 @@ struct symbol { void symbol__delete(struct symbol *sym); void symbols__delete(struct rb_root_cached *symbols); =20 +void symbol__set_ignore(struct symbol *sym, bool ignore); +void symbol__set_annotate2(struct symbol *sym, bool annotate2); + /* symbols__for_each_entry - iterate over symbols (rb_root) * * @symbols: the rb_root of symbols --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 07:35:50 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C86CF34A3C9 for ; Fri, 1 May 2026 18:20:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659638; cv=none; b=U1XeKaOVLYgl1MtpNpuUEYefd7Fzwf1NtVBfhH/G8q6E0tihEopkdAMV9VChoycBTodaJzfm9jSsV8CrpC+rFnZ738tEwiUi8FZnif8gKNMWOO4SJqbsBpDGlBchU2/6HeVAZorlY0bOPLdnmRoI0Z8U/w+LfhRaGlCmPFOBl7c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777659638; c=relaxed/simple; bh=vrfKaNU5Om2wRMB9M7Cg5YDJsuWUaYbkwPyDT98em2Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qAFKxkcYA8ZG9geTqWnBXcuenZxGa4qRMqhrSuidqxFDNfofNhp/+ZDdXKS6th2hpJPujl4HSIrZImEMtOa0kRUKx1vGXY1ZMDuNvGPTMlUlP3GxiWC2enooxFECkNb7n5rM3/mh4JTnCxnOFNRjO0AOysqODN8HfcrnUfgPYR0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=pTj651C5; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="pTj651C5" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-12c87ba0890so11727356c88.0 for ; Fri, 01 May 2026 11:20:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777659635; x=1778264435; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=K/zT8c2FyqRA8sOkSAMze+wDB7+iMrhpp2q1e8UyItE=; b=pTj651C5cG6nPtpbs3/sWHB3wB3rVY8ItT5QSYDGgMNd+L7GNYu+XMej82AwA72bgw 7sE7+/xeTXawvU8texND6O7s04V6clDgzeJyBvWpCVNaQRa//MPUSXmzqV7puDYyIz1f uolv22vMSleYGsAyknjY5pUHbqG+preBFTOe5Iyy/FmaSgCj5nuRltkXcXwMNyTswQWd /ShNMJ7RRn++L6SDWF3BwatT3I42/9HRP+ZOcQvcnXHb9XzUZ4u+2lMosu5Nj1QidcgJ TX0uIy5WJT+lxJrKdg1oHjuLnfexNlqn2fcbATBdYEIGhwYP29kFrIC4+8a4utYxFNtF Latw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777659635; x=1778264435; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K/zT8c2FyqRA8sOkSAMze+wDB7+iMrhpp2q1e8UyItE=; b=TuHpqWUE7p/spfWTjmQ4Il8kigkewtObwKLAadUSOsq9/YXzl2WFQWUsAjzeflPqZU 7UgnuRlmO9G1qeoIz5iCQnoFBO8OxLVxgANQf4HUBe7WlxxTQpQ9kYOjBcb7qiZDuazV vzh3CdbdrMWgVQYMqPyZ15H+e2/E6H2yTjMtbHN1XeltL1pVGAKKSkbyP4UMOKv0b5B+ /XI8O6S32phykPcCiKbc+ihCDX9SMElT3MLtFqYjSFvMtYglHY8rsg2DHlffob+AsLoF LOOTFRA35N6DH68uPNiL2hzL/AD840yZ92oUHSqugvUSZEMtTgEUCIHUZrX1iom1hf95 81mQ== X-Forwarded-Encrypted: i=1; AFNElJ9PZMtdPznOinKe1SAjRB7op6BpJHLfTmlHJ92hHNiMRzoquHv0EToRBK10e9PL1Nm1E66SW2VI4pNKYKQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxHaaKTdEl7QIXooxspp2DbUg0Ktk3LF83fwkvHHj4h0A8RB7Ao bhmti+h6o556jQ4L+TajSrFqAti39iXJRj4doRiA76TqcAfQrIA1K+WCfQUtM+I8/Gs+W3tTgJw cbPUiWdG2Dw== X-Received: from dleb6-n1.prod.google.com ([2002:a05:701b:4246:10b0:12a:9ef0:93ed]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:20d:b0:12d:c039:6599 with SMTP id a92af1059eb24-12dfd82f217mr180533c88.22.1777659634578; Fri, 01 May 2026 11:20:34 -0700 (PDT) Date: Fri, 1 May 2026 11:20:21 -0700 In-Reply-To: <20260501182021.3651851-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260409230620.4176210-2-irogers@google.com> <20260501182021.3651851-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <20260501182021.3651851-5-irogers@google.com> Subject: [PATCH v7 4/4] perf symbol: Lazily compute idle and use a global lock for updates From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org, tmricht@linux.ibm.com Cc: agordeev@linux.ibm.com, gor@linux.ibm.com, hca@linux.ibm.com, jameshongleiwang@126.com, japo@linux.ibm.com, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-s390@vger.kernel.org, sumanthk@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the idle boolean to a helper symbol__is_idle function. In the function lazily compute whether a symbol is an idle function taking into consideration the kernel version and architecture of the machine. As symbols__insert no longer needs to know if a symbol is for the kernel, remove the argument. This change is inspired by mailing list discussion, particularly from Thomas Richter and Heiko Carstens : https://lore.kernel.org/lkml/20260219113850.354271-1-tmricht@linux.ibm.com/ The change switches x86 matches to use strstarts which means intel_idle_irq is matched as part of strstarts(name, "intel_idle"), a change suggested by Honglei Wang in: https://lore.kernel.org/lkml/20260323085255.98173-1-jameshongleiwang@126.co= m/ To avoid concurrent update issues with other bitfields in `struct symbol`, this change uses the global lock `symbol_bits_lock` (introduced in a previous commit) for updates to the `idle` field. A static helper `symbol__set_idle` taking a boolean is used to encapsulate the lock and mapping to `enum symbol_idle_kind`. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers --- tools/perf/util/symbol-elf.c | 2 +- tools/perf/util/symbol.c | 108 +++++++++++++++++++++++------------ tools/perf/util/symbol.h | 14 +++-- 3 files changed, 81 insertions(+), 43 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 7afa8a117139..e8f7fe3f19fc 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1727,7 +1727,7 @@ dso__load_sym_internal(struct dso *dso, struct map *m= ap, struct symsrc *syms_ss, =20 arch__sym_update(f, &sym); =20 - __symbols__insert(dso__symbols(curr_dso), f, dso__kernel(dso)); + __symbols__insert(dso__symbols(curr_dso), f); nr++; } dso__put(curr_dso); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e6a1f23634ec..8ec4b2836b44 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -51,7 +51,6 @@ =20 static int dso__load_kernel_sym(struct dso *dso, struct map *map); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map); -static bool symbol__is_idle(const char *name); =20 static struct mutex symbol_bits_lock; =20 @@ -362,6 +361,13 @@ void symbol__set_annotate2(struct symbol *sym, bool an= notate2) mutex_unlock(&symbol_bits_lock); } =20 +static void symbol__set_idle(struct symbol *sym, bool idle) +{ + mutex_lock(&symbol_bits_lock); + sym->idle =3D idle ? SYMBOL_IDLE__IDLE : SYMBOL_IDLE__NOT_IDLE; + mutex_unlock(&symbol_bits_lock); +} + void symbols__delete(struct rb_root_cached *symbols) { struct symbol *pos; @@ -375,8 +381,7 @@ void symbols__delete(struct rb_root_cached *symbols) } } =20 -void __symbols__insert(struct rb_root_cached *symbols, - struct symbol *sym, bool kernel) +void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym) { struct rb_node **p =3D &symbols->rb_root.rb_node; struct rb_node *parent =3D NULL; @@ -384,17 +389,6 @@ void __symbols__insert(struct rb_root_cached *symbols, struct symbol *s; bool leftmost =3D true; =20 - if (kernel) { - const char *name =3D sym->name; - /* - * ppc64 uses function descriptors and appends a '.' to the - * start of every instruction address. Remove it. - */ - if (name[0] =3D=3D '.') - name++; - sym->idle =3D symbol__is_idle(name); - } - while (*p !=3D NULL) { parent =3D *p; s =3D rb_entry(parent, struct symbol, rb_node); @@ -411,7 +405,7 @@ void __symbols__insert(struct rb_root_cached *symbols, =20 void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym) { - __symbols__insert(symbols, sym, false); + __symbols__insert(symbols, sym); } =20 static struct symbol *symbols__find(struct rb_root_cached *symbols, u64 ip) @@ -572,7 +566,7 @@ void dso__reset_find_symbol_cache(struct dso *dso) =20 void dso__insert_symbol(struct dso *dso, struct symbol *sym) { - __symbols__insert(dso__symbols(dso), sym, dso__kernel(dso)); + __symbols__insert(dso__symbols(dso), sym); =20 /* update the symbol cache if necessary */ if (dso__last_find_result_addr(dso) >=3D sym->start && @@ -738,43 +732,81 @@ int modules__parse(const char *filename, void *arg, * These are symbols in the kernel image, so make sure that * sym is from a kernel DSO. */ -static bool symbol__is_idle(const char *name) +static int sym_name_cmp(const void *a, const void *b) { - const char * const idle_symbols[] =3D { + const char *name =3D a; + const char *const *sym =3D b; + + return strcmp(name, *sym); +} + +bool symbol__is_idle(struct symbol *sym, const struct dso *dso, struct per= f_env *env) +{ + static const char * const idle_symbols[] =3D { "acpi_idle_do_entry", "acpi_processor_ffh_cstate_enter", "arch_cpu_idle", "cpu_idle", "cpu_startup_entry", - "idle_cpu", - "intel_idle", - "intel_idle_ibrs", "default_idle", - "native_safe_halt", "enter_idle", "exit_idle", - "mwait_idle", - "mwait_idle_with_hints", - "mwait_idle_with_hints.constprop.0", + "idle_cpu", + "native_safe_halt", "poll_idle", - "ppc64_runlatch_off", "pseries_dedicated_idle_sleep", - "psw_idle", - "psw_idle_exit", - NULL }; - int i; - static struct strlist *idle_symbols_list; + const char *name =3D sym->name; + uint16_t e_machine =3D perf_env__e_machine(env, /*e_flags=3D*/NULL); =20 - if (idle_symbols_list) - return strlist__has_entry(idle_symbols_list, name); + if (sym->idle) + return sym->idle =3D=3D SYMBOL_IDLE__IDLE; =20 - idle_symbols_list =3D strlist__new(NULL, NULL); + if (!dso || dso__kernel(dso) =3D=3D DSO_SPACE__USER) { + symbol__set_idle(sym, /*idle=3D*/false); + return false; + } =20 - for (i =3D 0; idle_symbols[i]; i++) - strlist__add(idle_symbols_list, idle_symbols[i]); + /* + * ppc64 uses function descriptors and appends a '.' to the + * start of every instruction address. Remove it. + */ + if (name[0] =3D=3D '.') + name++; + + if (bsearch(name, idle_symbols, ARRAY_SIZE(idle_symbols), + sizeof(idle_symbols[0]), sym_name_cmp)) { + symbol__set_idle(sym, /*idle=3D*/true); + return true; + } + + if (e_machine =3D=3D EM_386 || e_machine =3D=3D EM_X86_64) { + if (strstarts(name, "mwait_idle") || + strstarts(name, "intel_idle")) { + symbol__set_idle(sym, /*idle=3D*/true); + return true; + } + } =20 - return strlist__has_entry(idle_symbols_list, name); + if (e_machine =3D=3D EM_PPC64 && !strcmp(name, "ppc64_runlatch_off")) { + symbol__set_idle(sym, /*idle=3D*/true); + return true; + } + + if (e_machine =3D=3D EM_S390 && strstarts(name, "psw_idle")) { + int major =3D 0, minor =3D 0; + const char *release =3D perf_env__os_release(env); + + /* Before v6.10, s390 used psw_idle. */ + if (release && sscanf(release, "%d.%d", &major, &minor) =3D=3D 2 && + (major < 6 || (major =3D=3D 6 && minor < 10))) { + symbol__set_idle(sym, /*idle=3D*/true); + return true; + } + } + + symbol__set_idle(sym, /*idle=3D*/false); + return false; } =20 static int map__process_kallsym_symbol(void *arg, const char *name, @@ -803,7 +835,7 @@ static int map__process_kallsym_symbol(void *arg, const= char *name, * We will pass the symbols to the filter later, in * map__split_kallsyms, when we have split the maps per module */ - __symbols__insert(root, sym, !strchr(name, '[')); + __symbols__insert(root, sym); =20 return 0; } diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 5d98d7e84d57..717d2f876d58 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -43,6 +43,12 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, GElf_Shdr *shp, const char *name, size_t *idx); #endif =20 +enum symbol_idle_kind { + SYMBOL_IDLE__UNKNOWN =3D 0, + SYMBOL_IDLE__NOT_IDLE =3D 1, + SYMBOL_IDLE__IDLE =3D 2, +}; + /** * A symtab entry. When allocated this may be preceded by an annotation (s= ee * symbol__annotation) and/or a browser_index (see symbol__browser_index). @@ -58,8 +64,8 @@ struct symbol { u8 type:4; /** ELF binding type as defined for st_info. E.g. STB_WEAK or STB_GLOBAL.= */ u8 binding:4; - /** Set true for kernel symbols of idle routines. */ - u8 idle:1; + /** Cache for symbol__is_idle holding enum symbol_idle_kind values. */ + u8 idle:2; /** Resolvable but tools ignore it (e.g. idle routines). */ u8 ignore:1; /** Symbol for an inlined function. */ @@ -197,8 +203,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct= symsrc *ss); =20 char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name= ); =20 -void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym, - bool kernel); +void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym); void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym); void symbols__fixup_duplicate(struct rb_root_cached *symbols); void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms); @@ -281,5 +286,6 @@ enum { }; =20 int symbol__validate_sym_arguments(void); +bool symbol__is_idle(struct symbol *sym, const struct dso *dso, struct per= f_env *env); =20 #endif /* __PERF_SYMBOL */ --=20 2.54.0.545.g6539524ca2-goog