From patchwork Mon Mar 10 17:19:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shuah Khan X-Patchwork-Id: 873020 Received: from mail-il1-f171.google.com (mail-il1-f171.google.com [209.85.166.171]) (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 D5A5517C225 for ; Mon, 10 Mar 2025 17:19:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741627157; cv=none; b=mc4ykM3Qm8tKvGeYx0VRt5o7wH/qLovO6No4jsdZvzi5EUThQ6s5HNzCyVzisQ8ZZtb9Dc1nqx1f19ZitznY9x0cQNsDzpLwMaHv9P8mFe9fgX6bFNtwZKOzAsiW+0Z/Mjn9HY39raN8p0BGQMw9a7uL7MzQKY4uFRSlmozvTwo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741627157; c=relaxed/simple; bh=YFlJYLeJ6RZUABa8RhmNikuTLtNI+gtuEkrjT8XBcUE=; h=Content-Type:Message-ID:Date:MIME-Version:To:Cc:From:Subject; b=dUpCviGCPYcKQHcm/mnMrYQugYhkR2I0k/znXqu3HVyY34cI4GVx2Q+dSYFacD0rb+kwob/YF/r26yr5BthUb4V0WJcZLyYD0XIz0MgUwrAZDGEE1+BwCYx6CNmKy4HH1KBzWYLwbNjdJhc/OFnbrNk9EHDZ27mu8WTeFKH6rIE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linuxfoundation.org; spf=pass smtp.mailfrom=linuxfoundation.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=Rnalm4ve; arc=none smtp.client-ip=209.85.166.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linuxfoundation.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linuxfoundation.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="Rnalm4ve" Received: by mail-il1-f171.google.com with SMTP id e9e14a558f8ab-3ce886a2d5bso34864265ab.1 for ; Mon, 10 Mar 2025 10:19:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1741627154; x=1742231954; darn=vger.kernel.org; h=subject:from:cc:to:content-language:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=whk/7neCN9gwKwzYytw5P08v6ZbgevrD/pRo+lEEuBw=; b=Rnalm4ve3CYOY5/NWIwcB6g0BVkI3FjftBMYnOGPAZ4d+HnBJh1eNC7baS3slREJWz vEtpR133/i59sUbS/Vs8nKbQfE3PvKWKcdfz18JCMAaAOe3B1u05MrDQmsrm8eSf+D0+ 5vnT1Png18zcaf+zmXzf5/wac9bQNjBNn4aDs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741627154; x=1742231954; h=subject:from:cc:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=whk/7neCN9gwKwzYytw5P08v6ZbgevrD/pRo+lEEuBw=; b=V3sJZ6qxJ/QvKZkF10+U6Idef8qLUDjyvS/RH8z8uDO0N58Tt+fLMN45ieWemNyDry a1X8IHnJ8iI1XBpIaq06iRRcZFv9uOtKENLTozom3HzUCFmYrejoKIB7IEXgwRJPvq2t hjfJJVVdPZt5N3dthykNdP+6dWS3UyWKQIg1EQpArAUKXJXC8JbFiH2siOabt3ZwToHu lW6J8AvGEQiZc9dOzgfs87n06nZZzJhad19U6bEYsrru8ebLGT0hWbKVYGBgEbUeW+Nr 31dSz9lVAoptE6E8YAqexKHWXAJBYL5whC7q3nJiseO2r66JO9fOl0FHypPS+F5xojpl XLzA== X-Forwarded-Encrypted: i=1; AJvYcCUnT2r358789ahlm7ziCKlyx9cihVxh2WfLXOtNrqQlIh4tfTPbsccvwXDJ7m6K8RWv+B79nXe6lA==@vger.kernel.org X-Gm-Message-State: AOJu0YwsCS7sCcb3o/twG3Al0jrASELLzk2zdui+vlplYXi7KtLFO75/ PTKJV0p8SsQATEJaIrdsHvx5Gg1A+SsTMmtpsltd2x9Q2V12Ea+mARfO0HWYCiE= X-Gm-Gg: ASbGncvg2Vvn1Pf98unmR6+HM50maRXUm3wHtXshdeF8GYAXqo8Yu8s7Y8kIUkZV0ex tIcrT1vsBW9sQRy98KlYnQu8M7RuNCqYuxFac4CchSqcouWyv67I+bLVoybEaKujsIj/yXsqPS8 CVn+Yw0Tn2KMju1zj0TVZXql1vTbUoaBdQiX0pUXjbBqWQeUm9N0YGMwKZBoG3mX5+rFOR2fxHP gQrR8X/CKFixhOl1P6jlglOwwT77hZ4IjILkJWvVpia5dt3R74qkvYVAzPjnmMeU692yEXLx/N8 DVw+MWY/2idgdV5AoZXs5DtHk0Z4ECrVG+mwAc48xkh9cXqGWUi7s1k= X-Google-Smtp-Source: AGHT+IFlubCUMTKk60R0aEoZRhOa6NDaApgVW8P8j3T/OzTf8ODHcXEU7wtr4IJTsg2l0aG9D1P/rA== X-Received: by 2002:a05:6e02:184e:b0:3d1:92fc:fb45 with SMTP id e9e14a558f8ab-3d44187c0demr186407365ab.5.1741627153916; Mon, 10 Mar 2025 10:19:13 -0700 (PDT) Received: from [192.168.1.14] ([38.175.170.29]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4f22b9bf883sm1148689173.92.2025.03.10.10.19.12 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 10 Mar 2025 10:19:12 -0700 (PDT) Message-ID: <826ecff6-5b43-4cf8-ba8e-3d5a44e5a318@linuxfoundation.org> Date: Mon, 10 Mar 2025 11:19:12 -0600 Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: "Rafael J. Wysocki" Cc: Thomas Renninger , Thomas Renninger , "John B. Wyatt IV" , John Kacur , skhan@linuxfoundation.org, shuah , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org From: Shuah Khan Subject: [GIT PULL] cpupower update for Linux 6.15-rc1 Hi Rafael, Please pull the following cpupower update for Linux 6.15-rc1. Fixes lib version-ing, memory leaks in error legs, removes hard-coded values, and implements CPU physical core querying. diff is attached. thanks, -- Shuah ---------------------------------------------------------------- The following changes since commit a64dcfb451e254085a7daee5fe51bf22959d52d3: Linux 6.14-rc2 (2025-02-09 12:45:03 -0800) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux tags/linux-cpupower-6.15-rc1 for you to fetch changes up to fffadbdd6b5acdb6390d6d0bc3ad6d3da5d2bd53: cpupower: Make lib versioning scheme more obvious and fix version link (2025-03-07 13:58:10 -0700) ---------------------------------------------------------------- linux-cpupower-6.15-rc1 Fixes lib version-ing, memory leaks in error legs, removes hard-coded values, and implements CPU physical core querying. ---------------------------------------------------------------- John B. Wyatt IV (1): cpupower: Implement CPU physical core querying Shuah Khan (2): pm: cpupower: Fix cmd_monitor() error legs to free cpu_topology pm: cpupower: remove hard-coded topology depth values Thomas Renninger (1): cpupower: Make lib versioning scheme more obvious and fix version link Yiwei Lin (1): cpupower: monitor: Exit with error status if execvp() fail Zhongqiu Han (1): pm: cpupower: bench: Prevent NULL dereference on malloc failure tools/power/cpupower/Makefile | 19 +++++---- tools/power/cpupower/bench/parse.c | 4 ++ tools/power/cpupower/lib/cpupower.c | 48 ++++++++++++++++++---- tools/power/cpupower/lib/cpupower.h | 3 ++ .../cpupower/utils/idle_monitor/cpupower-monitor.c | 48 ++++++++++++++++------ 5 files changed, 94 insertions(+), 28 deletions(-) ---------------------------------------------------------------- diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index 51a95239fe06..835123add0ed 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -52,8 +52,11 @@ DESTDIR ?= # and _should_ modify the PACKAGE_BUGREPORT definition VERSION:= $(shell ./utils/version-gen.sh) -LIB_MAJ= 0.0.1 -LIB_MIN= 1 +LIB_FIX= 1 +LIB_MIN= 0 +LIB_MAJ= 1 +LIB_VER= $(LIB_MAJ).$(LIB_MIN).$(LIB_FIX) + PACKAGE = cpupower PACKAGE_BUGREPORT = linux-pm@vger.kernel.org @@ -200,14 +203,14 @@ $(OUTPUT)lib/%.o: $(LIB_SRC) $(LIB_HEADERS) $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c -$(OUTPUT)libcpupower.so.$(LIB_MAJ): $(LIB_OBJS) +$(OUTPUT)libcpupower.so.$(LIB_VER): $(LIB_OBJS) $(ECHO) " LD " $@ $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ - -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS) + -Wl,-soname,libcpupower.so.$(LIB_MAJ) $(LIB_OBJS) @ln -sf $(@F) $(OUTPUT)libcpupower.so - @ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MIN) + @ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MAJ) -libcpupower: $(OUTPUT)libcpupower.so.$(LIB_MAJ) +libcpupower: $(OUTPUT)libcpupower.so.$(LIB_VER) # Let all .o files depend on its .c file and all headers # Might be worth to put this into utils/Makefile at some point of time @@ -217,7 +220,7 @@ $(OUTPUT)%.o: %.c $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c -$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ) +$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_VER) $(ECHO) " CC " $@ ifeq ($(strip $(STATIC)),true) $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lrt -lpci -L$(OUTPUT) -o $@ @@ -262,7 +265,7 @@ update-po: $(OUTPUT)po/$(PACKAGE).pot done; endif -compile-bench: $(OUTPUT)libcpupower.so.$(LIB_MAJ) +compile-bench: $(OUTPUT)libcpupower.so.$(LIB_VER) @V=$(V) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) # we compile into subdirectories. if the target directory is not the diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c index 080678d9d74e..bd67c758b33a 100644 --- a/tools/power/cpupower/bench/parse.c +++ b/tools/power/cpupower/bench/parse.c @@ -121,6 +121,10 @@ FILE *prepare_output(const char *dirname) struct config *prepare_default_config() { struct config *config = malloc(sizeof(struct config)); + if (!config) { + perror("malloc"); + return NULL; + } dprintf("loading defaults\n"); diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c index 7a2ef691b20e..ce8dfb8e46ab 100644 --- a/tools/power/cpupower/lib/cpupower.c +++ b/tools/power/cpupower/lib/cpupower.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "cpupower.h" #include "cpupower_intern.h" @@ -150,15 +151,25 @@ static int __compare(const void *t1, const void *t2) return 0; } +static int __compare_core_cpu_list(const void *t1, const void *t2) +{ + struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1; + struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2; + + return strcmp(top1->core_cpu_list, top2->core_cpu_list); +} + /* * Returns amount of cpus, negative on error, cpu_top must be * passed to cpu_topology_release to free resources * - * Array is sorted after ->pkg, ->core, then ->cpu + * Array is sorted after ->cpu_smt_list ->pkg, ->core */ int get_cpu_topology(struct cpupower_topology *cpu_top) { int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF); + char path[SYSFS_PATH_MAX]; + char *last_cpu_list; cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus); if (cpu_top->core_info == NULL) @@ -183,6 +194,34 @@ int get_cpu_topology(struct cpupower_topology *cpu_top) cpu_top->core_info[cpu].core = -1; continue; } + if (cpu_top->core_info[cpu].core == -1) { + strncpy(cpu_top->core_info[cpu].core_cpu_list, "-1", CPULIST_BUFFER); + continue; + } + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s", + cpu, "core_cpus_list"); + if (cpupower_read_sysfs( + path, + cpu_top->core_info[cpu].core_cpu_list, + CPULIST_BUFFER) < 1) { + printf("Warning CPU%u has a 0 size core_cpus_list string", cpu); + } + } + + /* Count the number of distinct cpu lists to get the physical core + * count. + */ + qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info), + __compare_core_cpu_list); + + last_cpu_list = cpu_top->core_info[0].core_cpu_list; + cpu_top->cores = 1; + for (cpu = 1; cpu < cpus; cpu++) { + if (strcmp(cpu_top->core_info[cpu].core_cpu_list, last_cpu_list) != 0 && + cpu_top->core_info[cpu].pkg != -1) { + last_cpu_list = cpu_top->core_info[cpu].core_cpu_list; + cpu_top->cores++; + } } qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info), @@ -203,13 +242,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top) if (!(cpu_top->core_info[0].pkg == -1)) cpu_top->pkgs++; - /* Intel's cores count is not consecutively numbered, there may - * be a core_id of 3, but none of 2. Assume there always is 0 - * Get amount of cores by counting duplicates in a package - for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) { - if (cpu_top->core_info[cpu].core == 0) - cpu_top->cores++; - */ return cpus; } diff --git a/tools/power/cpupower/lib/cpupower.h b/tools/power/cpupower/lib/cpupower.h index e4e4292eacec..2e67a080f203 100644 --- a/tools/power/cpupower/lib/cpupower.h +++ b/tools/power/cpupower/lib/cpupower.h @@ -2,6 +2,8 @@ #ifndef __CPUPOWER_CPUPOWER_H__ #define __CPUPOWER_CPUPOWER_H__ +#define CPULIST_BUFFER 5 + struct cpupower_topology { /* Amount of CPU cores, packages and threads per core in the system */ unsigned int cores; @@ -16,6 +18,7 @@ struct cpuid_core_info { int pkg; int core; int cpu; + char core_cpu_list[CPULIST_BUFFER]; /* flags */ unsigned int is_online:1; diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c index f746099b5dac..ad493157f826 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c @@ -6,6 +6,7 @@ */ +#include #include #include #include @@ -91,7 +92,11 @@ int fill_string_with_spaces(char *s, int n) return 0; } -#define MAX_COL_WIDTH 6 +#define MAX_COL_WIDTH 6 +#define TOPOLOGY_DEPTH_PKG 3 +#define TOPOLOGY_DEPTH_CORE 2 +#define TOPOLOGY_DEPTH_CPU 1 + void print_header(int topology_depth) { int unsigned mon; @@ -113,12 +118,19 @@ void print_header(int topology_depth) } printf("\n"); - if (topology_depth > 2) + switch (topology_depth) { + case TOPOLOGY_DEPTH_PKG: printf(" PKG|"); - if (topology_depth > 1) + break; + case TOPOLOGY_DEPTH_CORE: printf("CORE|"); - if (topology_depth > 0) + break; + case TOPOLOGY_DEPTH_CPU: printf(" CPU|"); + break; + default: + return; + } for (mon = 0; mon < avail_monitors; mon++) { if (mon != 0) @@ -152,12 +164,19 @@ void print_results(int topology_depth, int cpu) cpu_top.core_info[cpu].pkg == -1) return; - if (topology_depth > 2) + switch (topology_depth) { + case TOPOLOGY_DEPTH_PKG: printf("%4d|", cpu_top.core_info[cpu].pkg); - if (topology_depth > 1) + break; + case TOPOLOGY_DEPTH_CORE: printf("%4d|", cpu_top.core_info[cpu].core); - if (topology_depth > 0) + break; + case TOPOLOGY_DEPTH_CPU: printf("%4d|", cpu_top.core_info[cpu].cpu); + break; + default: + return; + } for (mon = 0; mon < avail_monitors; mon++) { if (mon != 0) @@ -294,7 +313,10 @@ int fork_it(char **argv) if (!child_pid) { /* child */ - execvp(argv[0], argv); + if (execvp(argv[0], argv) == -1) { + printf("Invalid monitor command %s\n", argv[0]); + exit(errno); + } } else { /* parent */ if (child_pid == -1) { @@ -423,11 +445,13 @@ int cmd_monitor(int argc, char **argv) if (avail_monitors == 0) { printf(_("No HW Cstate monitors found\n")); + cpu_topology_release(cpu_top); return 1; } if (mode == list) { list_monitors(); + cpu_topology_release(cpu_top); exit(EXIT_SUCCESS); } @@ -448,15 +472,15 @@ int cmd_monitor(int argc, char **argv) /* ToDo: Topology parsing needs fixing first to do this more generically */ if (cpu_top.pkgs > 1) - print_header(3); + print_header(TOPOLOGY_DEPTH_PKG); else - print_header(1); + print_header(TOPOLOGY_DEPTH_CPU); for (cpu = 0; cpu < cpu_count; cpu++) { if (cpu_top.pkgs > 1) - print_results(3, cpu); + print_results(TOPOLOGY_DEPTH_PKG, cpu); else - print_results(1, cpu); + print_results(TOPOLOGY_DEPTH_CPU, cpu); } for (num = 0; num < avail_monitors; num++) {