import powerpc-utils-1.3.6-11.el8

This commit is contained in:
CentOS Sources 2020-11-03 06:45:22 -05:00 committed by Stepan Oksanichenko
parent e802888477
commit aeb08e3947
20 changed files with 2787 additions and 50 deletions

View File

@ -0,0 +1,702 @@
From ca2e17833fa81026f0dfcf35b6b01a5f9f6c0806 Mon Sep 17 00:00:00 2001
Message-Id: <ca2e17833fa81026f0dfcf35b6b01a5f9f6c0806.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 07:05:00 -0500
Subject: [PATCH V4 01/14] common/cpu_info_helpers: library to capture CPU
information
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
ppc64_cpu tool does a lots of heavy lifting in finding the information
about the underlying CPU topology and various other details. These
details might be required by other tools, probing the underlying
platform for similar details. Moving such functions to a common
library, allows sharing across ppc64_cpu and others tools, instead of
multiple implementation of functions capturing same information.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
Makefile.am | 4 +-
src/common/cpu_info_helpers.c | 290 ++++++++++++++++++++++++++++++++++
src/common/cpu_info_helpers.h | 46 ++++++
src/ppc64_cpu.c | 227 +-------------------------
4 files changed, 346 insertions(+), 221 deletions(-)
create mode 100644 src/common/cpu_info_helpers.c
create mode 100644 src/common/cpu_info_helpers.h
diff --git a/Makefile.am b/Makefile.am
index a272008..1f0b4f6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -63,6 +63,8 @@ pseries_platform_SOURCES = src/common/pseries_platform.c src/common/pseries_plat
librtas_error_SOURCES = src/common/librtas_error.c src/common/librtas_error.h
+cpu_info_helpers_SOURCES = src/common/cpu_info_helpers.c src/common/cpu_info_helpers.h
+
src_nvram_SOURCES = src/nvram.c src/nvram.h $(pseries_platform_SOURCES)
src_nvram_LDADD = -lz @LIBDL@
@@ -70,7 +72,7 @@ src_lsprop_SOURCES = src/lsprop.c $(pseries_platform_SOURCES)
src_lparstat_SOURCES = src/lparstat.c src/lparstat.h $(pseries_platform_SOURCES)
-src_ppc64_cpu_SOURCES = src/ppc64_cpu.c $(pseries_platform_SOURCES)
+src_ppc64_cpu_SOURCES = src/ppc64_cpu.c $(pseries_platform_SOURCES) $(cpu_info_helpers_SOURCES)
src_ppc64_cpu_LDADD = -lpthread
diff --git a/src/common/cpu_info_helpers.c b/src/common/cpu_info_helpers.c
new file mode 100644
index 0000000..0bb1dfe
--- /dev/null
+++ b/src/common/cpu_info_helpers.c
@@ -0,0 +1,290 @@
+/**
+ * @file cpu_info_helpers.c
+ * @brief Common routines to capture cpu information
+ *
+ * Copyright (c) 2007, 2020 International Business Machines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * @author Anton Blanchard <anton@au.ibm.com>
+ * @author Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "cpu_info_helpers.h"
+
+int get_attribute(char *path, const char *fmt, int *value)
+{
+ FILE *fp;
+ int rc;
+
+ rc = access(path, F_OK);
+ if (rc)
+ return -1;
+
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+
+ rc = fscanf(fp, fmt, value);
+ fclose(fp);
+
+ if (rc == EOF)
+ return -1;
+
+ return 0;
+}
+
+static int test_sysattr(char *attribute, int perms, int threads_in_system)
+{
+ char path[SYSFS_PATH_MAX];
+ int i;
+
+ for (i = 0; i < threads_in_system; i++) {
+ sprintf(path, SYSFS_CPUDIR"/%s", i, attribute);
+ if (access(path, F_OK))
+ continue;
+
+ if (access(path, perms))
+ return 0;
+ }
+
+ return 1;
+}
+
+int __sysattr_is_readable(char *attribute, int threads_in_system)
+{
+ return test_sysattr(attribute, R_OK, threads_in_system);
+}
+
+int __sysattr_is_writeable(char *attribute, int threads_in_system)
+{
+ return test_sysattr(attribute, W_OK, threads_in_system);
+}
+
+int cpu_online(int thread)
+{
+ char path[SYSFS_PATH_MAX];
+ int rc, online;
+
+ sprintf(path, SYSFS_CPUDIR"/online", thread);
+ rc = get_attribute(path, "%d", &online);
+
+ /* This attribute does not exist in kernels without hotplug enabled */
+ if (rc && errno == ENOENT)
+ return 1;
+
+ if (rc || !online)
+ return 0;
+
+ return 1;
+}
+
+int is_subcore_capable(void)
+{
+ return access(SYSFS_SUBCORES, F_OK) == 0;
+}
+
+int num_subcores(void)
+{
+ int rc, subcores;
+
+ rc = get_attribute(SYSFS_SUBCORES, "%d", &subcores);
+ if (rc)
+ return -1;
+ return subcores;
+}
+
+int get_cpu_info(int *_threads_per_cpu, int *_cpus_in_system,
+ int *_threads_in_system)
+{
+ DIR *d;
+ struct dirent *de;
+ int first_cpu = 1;
+ int rc;
+ int subcores;
+ int threads_in_system;
+ int threads_per_cpu = 0;
+ int cpus_in_system = 0;
+
+ d = opendir("/proc/device-tree/cpus");
+ if (!d)
+ return -1;
+
+ while ((de = readdir(d)) != NULL) {
+ if (!strncmp(de->d_name, "PowerPC", 7)) {
+ if (first_cpu) {
+ struct stat sbuf;
+ char path[128];
+
+ snprintf(path, sizeof(path), INTSERV_PATH, de->d_name);
+ rc = stat(path, &sbuf);
+ if (!rc)
+ threads_per_cpu = sbuf.st_size / 4;
+
+ first_cpu = 0;
+ }
+
+ cpus_in_system++;
+ }
+ }
+
+ closedir(d);
+ threads_in_system = cpus_in_system * threads_per_cpu;
+
+ subcores = num_subcores();
+ if (is_subcore_capable() && subcores > 0) {
+ threads_per_cpu /= subcores;
+ cpus_in_system *= subcores;
+ }
+
+ *_threads_per_cpu = threads_per_cpu;
+ *_threads_in_system = threads_in_system;
+ *_cpus_in_system = cpus_in_system;
+
+ return 0;
+}
+
+int __is_smt_capable(int threads_in_system)
+{
+ struct stat sb;
+ char path[SYSFS_PATH_MAX];
+ int i;
+
+ for (i = 0; i < threads_in_system; i++) {
+ sprintf(path, SYSFS_CPUDIR"/smt_snooze_delay", i);
+ if (stat(path, &sb))
+ continue;
+ return 1;
+ }
+
+ return 0;
+}
+
+int __get_one_smt_state(int core, int threads_per_cpu)
+{
+ int primary_thread = core * threads_per_cpu;
+ int smt_state = 0;
+ int i;
+
+ if (!__sysattr_is_readable("online", threads_per_cpu)) {
+ perror("Cannot retrieve smt state");
+ return -2;
+ }
+
+ for (i = 0; i < threads_per_cpu; i++) {
+ smt_state += cpu_online(primary_thread + i);
+ }
+
+ return smt_state;
+}
+
+static void print_cpu_list(const cpu_set_t *cpuset, int cpuset_size,
+ int cpus_in_system)
+{
+ int core;
+ const char *comma = "";
+
+ for (core = 0; core < cpus_in_system; core++) {
+ int begin = core;
+ if (CPU_ISSET_S(core, cpuset_size, cpuset)) {
+ while (CPU_ISSET_S(core+1, cpuset_size, cpuset))
+ core++;
+
+ if (core > begin)
+ printf("%s%d-%d", comma, begin, core);
+ else
+ printf("%s%d", comma, core);
+ comma = ",";
+ }
+ }
+}
+
+int __do_smt(bool numeric, int cpus_in_system, int threads_per_cpu,
+ bool print_smt_state)
+{
+ int thread, c, smt_state = 0;
+ cpu_set_t **cpu_states = NULL;
+ int cpu_state_size = CPU_ALLOC_SIZE(cpus_in_system);
+ int start_cpu = 0, stop_cpu = cpus_in_system;
+ int rc = 0;
+
+ cpu_states = (cpu_set_t **)calloc(threads_per_cpu, sizeof(cpu_set_t));
+ if (!cpu_states)
+ return -ENOMEM;
+
+ for (thread = 0; thread < threads_per_cpu; thread++) {
+ cpu_states[thread] = CPU_ALLOC(cpus_in_system);
+ CPU_ZERO_S(cpu_state_size, cpu_states[thread]);
+ }
+
+ for (c = start_cpu; c < stop_cpu; c++) {
+ int threads_online = __get_one_smt_state(c, threads_per_cpu);
+
+ if (threads_online < 0) {
+ rc = threads_online;
+ goto cleanup_get_smt;
+ }
+ if (threads_online)
+ CPU_SET_S(c, cpu_state_size,
+ cpu_states[threads_online - 1]);
+ }
+
+ for (thread = 0; thread < threads_per_cpu; thread++) {
+ if (CPU_COUNT_S(cpu_state_size, cpu_states[thread])) {
+ if (smt_state == 0)
+ smt_state = thread + 1;
+ else if (smt_state > 0)
+ smt_state = -1; /* mix of SMT modes */
+ }
+ }
+
+ if (!print_smt_state)
+ return smt_state;
+
+ if (smt_state == 1) {
+ if (numeric)
+ printf("SMT=1\n");
+ else
+ printf("SMT is off\n");
+ } else if (smt_state == -1) {
+ for (thread = 0; thread < threads_per_cpu; thread++) {
+ if (CPU_COUNT_S(cpu_state_size,
+ cpu_states[thread])) {
+ printf("SMT=%d: ", thread + 1);
+ print_cpu_list(cpu_states[thread],
+ cpu_state_size, cpus_in_system);
+ printf("\n");
+ }
+ }
+ } else {
+ printf("SMT=%d\n", smt_state);
+ }
+
+cleanup_get_smt:
+ for (thread = 0; thread < threads_per_cpu; thread++)
+ CPU_FREE(cpu_states[thread]);
+
+ return rc;
+}
diff --git a/src/common/cpu_info_helpers.h b/src/common/cpu_info_helpers.h
new file mode 100644
index 0000000..8f09d79
--- /dev/null
+++ b/src/common/cpu_info_helpers.h
@@ -0,0 +1,46 @@
+/**
+ * @file cpu_info_helpers.h
+ * @brief Header of common routines to capture cpu information
+ *
+ * Copyright (c) 2007, 2020 International Business Machines
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * @author Anton Blanchard <anton@au.ibm.com>
+ * @author Kamalesh Babulal <kamaleshb@linux.vnet.ibm.com>
+ */
+#ifndef _CPU_INFO_HELPERS_H
+#define _CPU_INFO_HELPERS_H
+
+#define SYSFS_CPUDIR "/sys/devices/system/cpu/cpu%d"
+#define SYSFS_SUBCORES "/sys/devices/system/cpu/subcores_per_core"
+#define INTSERV_PATH "/proc/device-tree/cpus/%s/ibm,ppc-interrupt-server#s"
+
+#define SYSFS_PATH_MAX 128
+
+extern int __sysattr_is_readable(char *attribute, int threads_in_system);
+extern int __sysattr_is_writeable(char *attribute, int threads_in_system);
+extern int cpu_online(int thread);
+extern int is_subcore_capable(void);
+extern int num_subcores(void);
+extern int get_attribute(char *path, const char *fmt, int *value);
+extern int get_cpu_info(int *threads_per_cpu, int *cpus_in_system,
+ int *threads_in_system);
+extern int __is_smt_capable(int threads_in_system);
+extern int __get_one_smt_state(int core, int threads_per_cpu);
+extern int __do_smt(bool numeric, int cpus_in_system, int threads_per_cpu,
+ bool print_smt_state);
+
+#endif /* CPU_INFO_H */
diff --git a/src/ppc64_cpu.c b/src/ppc64_cpu.c
index 6d02235..cacbf1a 100644
--- a/src/ppc64_cpu.c
+++ b/src/ppc64_cpu.c
@@ -47,15 +47,12 @@
#endif
#include <errno.h>
+#include "cpu_info_helpers.h"
#define PPC64_CPU_VERSION "1.2"
-#define SYSFS_CPUDIR "/sys/devices/system/cpu/cpu%d"
-#define SYSFS_SUBCORES "/sys/devices/system/cpu/subcores_per_core"
#define DSCR_DEFAULT_PATH "/sys/devices/system/cpu/dscr_default"
-#define INTSERV_PATH "/proc/device-tree/cpus/%s/ibm,ppc-interrupt-server#s"
-#define SYSFS_PATH_MAX 128
#define MAX_NR_CPUS 1024
#define DIAGNOSTICS_RUN_MODE 42
#define CPU_OFFLINE -1
@@ -80,54 +77,14 @@ static int threads_in_system = 0;
static int do_info(void);
-static int test_sysattr(char *attribute, int perms)
-{
- char path[SYSFS_PATH_MAX];
- int i;
-
- for (i = 0; i < threads_in_system; i++) {
- sprintf(path, SYSFS_CPUDIR"/%s", i, attribute);
- if (access(path, F_OK))
- continue;
-
- if (access(path, perms))
- return 0;
- }
-
- return 1;
-}
-
static int sysattr_is_readable(char *attribute)
{
- return test_sysattr(attribute, R_OK);
+ return __sysattr_is_readable(attribute, threads_in_system);
}
static int sysattr_is_writeable(char *attribute)
{
- return test_sysattr(attribute, W_OK);
-}
-
-static int get_attribute(char *path, const char *fmt, int *value)
-{
- FILE *fp;
- int rc;
-
- rc = access(path, F_OK);
- if (rc)
- return -1;
-
-
- fp = fopen(path, "r");
- if (!fp)
- return -1;
-
- rc = fscanf(fp, fmt, value);
- fclose(fp);
-
- if (rc == EOF)
- return -1;
-
- return 0;
+ return __sysattr_is_writeable(attribute, threads_in_system);
}
static int set_attribute(const char *path, const char *fmt, int value)
@@ -156,24 +113,6 @@ close:
return rc;
}
-static int cpu_online(int thread)
-{
- char path[SYSFS_PATH_MAX];
- int rc, online;
-
- sprintf(path, SYSFS_CPUDIR"/online", thread);
- rc = get_attribute(path, "%d", &online);
-
- /* This attribute does not exist in kernels without hotplug enabled */
- if (rc && errno == ENOENT)
- return 1;
-
- if (rc || !online)
- return 0;
-
- return 1;
-}
-
static int get_system_attribute(char *attribute, const char *fmt, int *value,
int *inconsistent)
{
@@ -316,93 +255,14 @@ static int offline_thread(const char *path)
return set_attribute(path, "%d", 0);
}
-static int is_subcore_capable(void)
-{
- return access(SYSFS_SUBCORES, F_OK) == 0;
-}
-
-static int num_subcores(void)
-{
- int rc, subcores;
- rc = get_attribute(SYSFS_SUBCORES, "%d", &subcores);
- if (rc)
- return -1;
- return subcores;
-}
-
-static int get_cpu_info(void)
-{
- DIR *d;
- struct dirent *de;
- int first_cpu = 1;
- int rc;
- int subcores;
-
- d = opendir("/proc/device-tree/cpus");
- if (!d)
- return -1;
-
- while ((de = readdir(d)) != NULL) {
- if (!strncmp(de->d_name, "PowerPC", 7)) {
- if (first_cpu) {
- struct stat sbuf;
- char path[128];
-
- sprintf(path, INTSERV_PATH, de->d_name);
- rc = stat(path, &sbuf);
- if (!rc)
- threads_per_cpu = sbuf.st_size / 4;
-
- first_cpu = 0;
- }
-
- cpus_in_system++;
- }
- }
-
- closedir(d);
- threads_in_system = cpus_in_system * threads_per_cpu;
-
- subcores = num_subcores();
- if (is_subcore_capable() && subcores > 0) {
- threads_per_cpu /= subcores;
- cpus_in_system *= subcores;
- }
- return 0;
-}
-
static int is_smt_capable(void)
{
- struct stat sb;
- char path[SYSFS_PATH_MAX];
- int i;
-
- for (i = 0; i < threads_in_system; i++) {
- sprintf(path, SYSFS_CPUDIR"/smt_snooze_delay", i);
- if (stat(path, &sb))
- continue;
- return 1;
- }
-
- return 0;
+ return __is_smt_capable(threads_in_system);
}
static int get_one_smt_state(int core)
{
- int primary_thread = core * threads_per_cpu;
- int smt_state = 0;
- int i;
-
- if (!sysattr_is_readable("online")) {
- perror("Cannot retrieve smt state");
- return -2;
- }
-
- for (i = 0; i < threads_per_cpu; i++) {
- smt_state += cpu_online(primary_thread + i);
- }
-
- return smt_state;
+ return __get_one_smt_state(core, threads_per_cpu);
}
static int get_smt_state(void)
@@ -513,26 +373,6 @@ static int is_dscr_capable(void)
return 0;
}
-void print_cpu_list(const cpu_set_t *cpuset, int cpuset_size)
-{
- int core;
- const char *comma = "";
-
- for (core = 0; core < cpus_in_system; core++) {
- int begin = core;
- if (CPU_ISSET_S(core, cpuset_size, cpuset)) {
- while (CPU_ISSET_S(core+1, cpuset_size, cpuset))
- core++;
-
- if (core > begin)
- printf("%s%d-%d", comma, begin, core);
- else
- printf("%s%d", comma, core);
- comma = ",";
- }
- }
-}
-
static int do_smt(char *state, bool numeric)
{
int rc = 0;
@@ -547,60 +387,7 @@ static int do_smt(char *state, bool numeric)
}
if (!state) {
- int thread, c;
- cpu_set_t *cpu_states[threads_per_cpu];
- int cpu_state_size = CPU_ALLOC_SIZE(cpus_in_system);
- int start_cpu = 0, stop_cpu = cpus_in_system;
-
- for (thread = 0; thread < threads_per_cpu; thread++) {
- cpu_states[thread] = CPU_ALLOC(cpus_in_system);
- CPU_ZERO_S(cpu_state_size, cpu_states[thread]);
- }
-
- for (c = start_cpu; c < stop_cpu; c++) {
- int threads_online = get_one_smt_state(c);
-
- if (threads_online < 0) {
- rc = threads_online;
- goto cleanup_get_smt;
- }
- if (threads_online)
- CPU_SET_S(c, cpu_state_size,
- cpu_states[threads_online - 1]);
- }
-
- for (thread = 0; thread < threads_per_cpu; thread++) {
- if (CPU_COUNT_S(cpu_state_size, cpu_states[thread])) {
- if (smt_state == 0)
- smt_state = thread + 1;
- else if (smt_state > 0)
- smt_state = -1; /* mix of SMT modes */
- }
- }
-
- if (smt_state == 1) {
- if (numeric)
- printf("SMT=1\n");
- else
- printf("SMT is off\n");
- } else if (smt_state == -1) {
- for (thread = 0; thread < threads_per_cpu; thread++) {
- if (CPU_COUNT_S(cpu_state_size,
- cpu_states[thread])) {
- printf("SMT=%d: ", thread + 1);
- print_cpu_list(cpu_states[thread],
- cpu_state_size);
- printf("\n");
- }
- }
- } else {
- printf("SMT=%d\n", smt_state);
- }
-
-cleanup_get_smt:
- for (thread = 0; thread < threads_per_cpu; thread++)
- CPU_FREE(cpu_states[thread]);
-
+ rc = __do_smt(numeric, cpus_in_system, threads_per_cpu, true);
} else {
if (!strcmp(state, "on"))
smt_state = threads_per_cpu;
@@ -1510,7 +1297,7 @@ int main(int argc, char *argv[])
return 0;
}
- rc = get_cpu_info();
+ rc = get_cpu_info(&threads_per_cpu, &cpus_in_system, &threads_in_system);
if (rc) {
printf("Could not determine system cpu/thread information.\n");
return rc;
--
2.25.3

View File

@ -0,0 +1,34 @@
From 9a509d69ef675291a4fa842f6f281b2a968f4b52 Mon Sep 17 00:00:00 2001
From: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Date: Mon, 24 Feb 2020 19:57:57 +0530
Subject: [PATCH] update_flash: Fix warning
With recent bash `update_flash -v -f <image>` is throwing below warning.
update_flash_nv: line 316: warning: command substitution: ignored null byte in input
bash enhancement: https://lists.gnu.org/archive/html/bug-bash/2016-09/msg00015.html
This patch fixes above issue.
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
scripts/update_flash_nv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/update_flash_nv b/scripts/update_flash_nv
index bb9dfee..8be9e8e 100755
--- a/scripts/update_flash_nv
+++ b/scripts/update_flash_nv
@@ -313,7 +313,7 @@ fsp_validate_flash() {
echo 1 > $SYS_VALIDATE_FLASH 2>/dev/null
# Display appropriate message, exiting if necessary
- output="$(cat $SYS_VALIDATE_FLASH)"
+ output="$(tr -d '\0' < $SYS_VALIDATE_FLASH)"
fsp_echo_validate_return_status "$output"
}
--
2.21.1

View File

@ -0,0 +1,165 @@
From 5cd8f63b62394840de818328d275d7f20efe79a7 Mon Sep 17 00:00:00 2001
Message-Id: <5cd8f63b62394840de818328d275d7f20efe79a7.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 07:10:54 -0500
Subject: [PATCH V4 02/14] lparstat: Remove ppc64_cpu tool dependency
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
get_smt_mode(), calls ppc64_cpu tool to get the current SMT mode, this
method of probing has its disadvantages like tightly coupling lparstat
with ppc64_cpu to mention one. Use, the internal library to fetch this
information.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
Makefile.am | 3 ++-
src/lparstat.c | 54 ++++++++++++++++++++++++++++++++++----------------
src/lparstat.h | 2 +-
3 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 1f0b4f6..15f8bcc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -70,7 +70,8 @@ src_nvram_LDADD = -lz @LIBDL@
src_lsprop_SOURCES = src/lsprop.c $(pseries_platform_SOURCES)
-src_lparstat_SOURCES = src/lparstat.c src/lparstat.h $(pseries_platform_SOURCES)
+src_lparstat_SOURCES = src/lparstat.c src/lparstat.h $(pseries_platform_SOURCES) \
+ $(cpu_info_helpers_SOURCES)
src_ppc64_cpu_SOURCES = src/ppc64_cpu.c $(pseries_platform_SOURCES) $(cpu_info_helpers_SOURCES)
src_ppc64_cpu_LDADD = -lpthread
diff --git a/src/lparstat.c b/src/lparstat.c
index ffb2cfa..b7cb2d2 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -31,6 +31,7 @@
#include <sys/time.h>
#include "lparstat.h"
#include "pseries_platform.h"
+#include "cpu_info_helpers.h"
#define LPARCFG_FILE "/proc/ppc64/lparcfg"
#define SE_NOT_FOUND "???"
@@ -38,6 +39,10 @@
static bool o_legacy = false;
+static int threads_per_cpu;
+static int cpus_in_system;
+static int threads_in_system;
+
struct sysentry *get_sysentry(char *name)
{
struct sysentry *se = &system_data[0];
@@ -73,6 +78,16 @@ void get_sysdata(char *name, char **descr, char *value)
*descr = se->descr;
}
+static int is_smt_capable(void)
+{
+ return __is_smt_capable(threads_in_system);
+}
+
+static int parse_smt_state(void)
+{
+ return __do_smt(false, cpus_in_system, threads_per_cpu, false);
+}
+
void get_time()
{
struct timeval t;
@@ -522,32 +537,23 @@ void get_mem_total(struct sysentry *se, char *buf)
void get_smt_mode(struct sysentry *se, char *buf)
{
- FILE *f;
- char line[128];
- char *cmd = "/usr/sbin/ppc64_cpu --smt";
- char *first_line;
+ int smt_state = 0;
- f = popen(cmd, "r");
- if (!f) {
- fprintf(stderr, "Failed to execute %s\n", cmd);
+ if (!is_smt_capable()) {
+ sprintf(buf, "1");
return;
}
- first_line = fgets(line, 128, f);
- pclose(f);
-
- if (!first_line) {
- fprintf(stderr, "Could not read output of %s\n", cmd);
+ smt_state = parse_smt_state();
+ if (smt_state < 0) {
+ fprintf(stderr, "Failed to get smt state\n");
return;
}
- /* The output is either "SMT=x" or "SMT is off", we can cheat
- * by looking at line[8] for an 'f'.
- */
- if (line[8] == 'f')
+ if (smt_state == 1)
sprintf(buf, "Off");
else
- sprintf(buf, "%c", line[4]);
+ sprintf(buf, "%d", smt_state);
}
long long get_cpu_time_diff()
@@ -574,6 +580,19 @@ void get_cpu_stat(struct sysentry *se, char *buf)
sprintf(buf, "%.2f", percent);
}
+void init_sysinfo(void)
+{
+ int rc = 0;
+
+ /* probe one time system cpu information */
+ rc = get_cpu_info(&threads_per_cpu, &cpus_in_system,
+ &threads_in_system);
+ if (rc) {
+ fprintf(stderr, "Failed to capture system CPUs information\n");
+ exit(rc);
+ }
+}
+
void init_sysdata(void)
{
get_time();
@@ -746,6 +765,7 @@ int main(int argc, char *argv[])
if (optind < argc)
count = atoi(argv[optind++]);
+ init_sysinfo();
init_sysdata();
if (i_option)
diff --git a/src/lparstat.h b/src/lparstat.h
index 3aee192..ae84caf 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -184,7 +184,7 @@ struct sysentry system_data[] = {
.descr = "Online Memory",
.get = &get_mem_total},
- /* ppc64_cpu --smt */
+ /* smt mode, cpu_info_helpers::__do_smt() */
{.name = "smt_state",
.descr = "SMT",
.get = &get_smt_mode},
--
2.25.3

View File

@ -0,0 +1,99 @@
From 9263de80d08451beacc29e4eb83492234d648796 Mon Sep 17 00:00:00 2001
Message-Id: <9263de80d08451beacc29e4eb83492234d648796.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 07:54:01 -0500
Subject: [PATCH V4 03/14] lparstat: Read the online cores
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
The accumulation of PURR/SPURR values are total of all online CPU in
the system, hence the timebase also needs to be scaled to the number
of cores. Add a helper to read the online cores.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 32 ++++++++++++++++++++++++++++++++
src/lparstat.h | 4 ++++
2 files changed, 36 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index b7cb2d2..1d0b3a7 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -88,6 +88,11 @@ static int parse_smt_state(void)
return __do_smt(false, cpus_in_system, threads_per_cpu, false);
}
+static int get_one_smt_state(int core)
+{
+ return __get_one_smt_state(core, threads_per_cpu);
+}
+
void get_time()
{
struct timeval t;
@@ -556,6 +561,31 @@ void get_smt_mode(struct sysentry *se, char *buf)
sprintf(buf, "%d", smt_state);
}
+void get_online_cores(void)
+{
+ struct sysentry *se;
+ int *core_state;
+ int online_cores = 0;
+ int i;
+
+ core_state = calloc(cpus_in_system, sizeof(int));
+ if (!core_state) {
+ fprintf(stderr, "Failed to read online cores\n");
+ return;
+ }
+
+ for (i = 0; i < cpus_in_system; i++) {
+ core_state[i] = (get_one_smt_state(i) > 0);
+ if (core_state[i])
+ online_cores++;
+ }
+
+ se = get_sysentry("online_cores");
+ sprintf(se->value, "%d", online_cores);
+
+ free(core_state);
+}
+
long long get_cpu_time_diff()
{
long long old_total = 0, new_total = 0;
@@ -591,6 +621,8 @@ void init_sysinfo(void)
fprintf(stderr, "Failed to capture system CPUs information\n");
exit(rc);
}
+
+ get_online_cores();
}
void init_sysdata(void)
diff --git a/src/lparstat.h b/src/lparstat.h
index ae84caf..6b65b48 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -189,6 +189,10 @@ struct sysentry system_data[] = {
.descr = "SMT",
.get = &get_smt_mode},
+ /* online cores, cpu_info_helpers::get_one_smt_state() */
+ {.name = "online_cores",
+ .descr = "Online Cores"},
+
/* /proc/stat */
{.name = "cpu_total",
.descr = "CPU Total Time"},
--
2.25.3

View File

@ -0,0 +1,94 @@
From e8f0f534bab72cecdaf6b5822324d71884cb9133 Mon Sep 17 00:00:00 2001
Message-Id: <e8f0f534bab72cecdaf6b5822324d71884cb9133.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 07:55:28 -0500
Subject: [PATCH V4 04/14] lparstat: Capture nominal frequency
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Capture the nominal frequency/clock from the /proc/cpuinfo. This value
will be used later to calculate the effective/current frequency at which
the processor is running.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 36 ++++++++++++++++++++++++++++++++++++
src/lparstat.h | 2 ++
2 files changed, 38 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 1d0b3a7..24c48ad 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -171,6 +171,38 @@ void get_sys_uptime(struct sysentry *unused_se, char *uptime)
fclose(f);
}
+int get_nominal_frequency(void)
+{
+ FILE *f;
+ char buf[80];
+ struct sysentry *se;
+ char *nfreq = NULL;
+
+ f = fopen("/proc/cpuinfo", "r");
+ if (!f) {
+ fprintf(stderr, "Could not open /proc/cpuinfo\n");
+ return -1;
+ }
+
+ while ((fgets(buf, 80, f)) != NULL) {
+ if (!strncmp(buf, "clock", 5)) {
+ nfreq = strchr(buf, ':') + 2;
+ break;
+ }
+ }
+
+ fclose(f);
+
+ if (!nfreq) {
+ fprintf(stderr, "Failed to read Nominal frequency\n");
+ return -1;
+ }
+
+ se = get_sysentry("nominal_freq");
+ snprintf(se->value, sizeof(se->value), "%s", nfreq);
+
+ return 0;
+}
void get_cpu_physc(struct sysentry *unused_se, char *buf)
{
@@ -623,6 +655,10 @@ void init_sysinfo(void)
}
get_online_cores();
+
+ rc = get_nominal_frequency();
+ if (rc)
+ exit(rc);
}
void init_sysdata(void)
diff --git a/src/lparstat.h b/src/lparstat.h
index 6b65b48..c1bac28 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -242,6 +242,8 @@ struct sysentry system_data[] = {
/* /proc/cpuinfo */
{.name = "timebase",
.descr = "Timebase"},
+ {.name = "nominal_freq",
+ .descr = "Nominal Frequency"},
/* /proc/interrupts */
{.name = "phint",
--
2.25.3

View File

@ -0,0 +1,215 @@
From 8f0bf6a9dd14c16ee95092f43c45ee256f10637b Mon Sep 17 00:00:00 2001
Message-Id: <8f0bf6a9dd14c16ee95092f43c45ee256f10637b.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 07:58:19 -0500
Subject: [PATCH V4 05/14] lparstat: Assign file descriptors to speed up read
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
For every sampling interval, three per-cpu sysfs files is read to
capture spurr, idle_purr and idle_spurr values. Every read takes
three file operation such as open, read, close, future this scales
with number of CPUs in the system. To reduce the latency involved
in open and close, assign a permanent file descriptors per online cpu.
without caching file descriptors
---------------------------------
System Configuration
type=Dedicated mode=Capped smt=8 lcpu=4 mem=8302464 kB cpus=0 ent=4.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
0.04 99.95 3.16GHz[100%] 0.04 99.95 1.1003219
0.15 99.85 3.16GHz[100%] 0.15 99.85 1.1003222
0.04 99.96 3.16GHz[100%] 0.04 99.96 1.1003179
0.03 99.97 3.16GHz[100%] 0.03 99.97 1.1003183
0.03 99.97 3.16GHz[100%] 0.03 99.97 1.1003166
with caching file descriptors
------------------------------
System Configuration
type=Dedicated mode=Capped smt=8 lcpu=4 mem=8302464 kB cpus=0 ent=4.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
0.03 99.96 3.16GHz[100%] 0.03 99.97 1.1001793
0.03 99.97 3.16GHz[100%] 0.03 99.97 1.1001775
0.03 99.97 3.16GHz[100%] 0.03 99.97 1.1001775
0.02 99.98 3.16GHz[100%] 0.02 99.98 1.1001766
0.02 99.98 3.16GHz[100%] 0.02 99.98 1.1001762
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lparstat.h | 12 +++++++
2 files changed, 100 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 24c48ad..f5c0ce5 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -27,6 +27,8 @@
#include <string.h>
#include <getopt.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "lparstat.h"
@@ -43,6 +45,8 @@ static int threads_per_cpu;
static int cpus_in_system;
static int threads_in_system;
+static cpu_sysfs_fd *cpu_sysfs_fds;
+
struct sysentry *get_sysentry(char *name)
{
struct sysentry *se = &system_data[0];
@@ -93,6 +97,80 @@ static int get_one_smt_state(int core)
return __get_one_smt_state(core, threads_per_cpu);
}
+static int assign_read_fd(const char *path)
+{
+ int rc = 0;
+
+ rc = access(path, R_OK);
+ if (rc)
+ return -1;
+
+ rc = open(path, O_RDONLY);
+ return rc;
+}
+
+static void close_cpu_sysfs_fds(int threads_in_system)
+{
+ int i;
+
+ for (i = 0; i < threads_in_system && cpu_sysfs_fds[i].spurr; i++) {
+ close(cpu_sysfs_fds[i].spurr);
+ close(cpu_sysfs_fds[i].idle_purr);
+ close(cpu_sysfs_fds[i].idle_spurr);
+ }
+
+ free(cpu_sysfs_fds);
+}
+
+static int assign_cpu_sysfs_fds(int threads_in_system)
+{
+ int cpu_idx, i;
+ char sysfs_file_path[SYSFS_PATH_MAX];
+
+ cpu_sysfs_fds =
+ (cpu_sysfs_fd*)calloc(sizeof(cpu_sysfs_fd), threads_in_system);
+ if (!cpu_sysfs_fds) {
+ fprintf(stderr, "Failed to allocate memory for sysfs file descriptors\n");
+ return -1;
+ }
+
+ for (cpu_idx = 0, i = 0; i < threads_in_system; i++) {
+ if (!cpu_online(i))
+ continue;
+
+ cpu_sysfs_fds[cpu_idx].cpu = i;
+
+ snprintf(sysfs_file_path, SYSFS_PATH_MAX, SYSFS_PERCPU_SPURR, i);
+ cpu_sysfs_fds[cpu_idx].spurr = assign_read_fd(sysfs_file_path);
+ if (cpu_sysfs_fds[cpu_idx].spurr == -1)
+ goto error;
+
+ snprintf(sysfs_file_path, SYSFS_PATH_MAX, SYSFS_PERCPU_IDLE_PURR, i);
+ cpu_sysfs_fds[cpu_idx].idle_purr = assign_read_fd(sysfs_file_path);
+ if (cpu_sysfs_fds[cpu_idx].idle_purr == -1)
+ goto error;
+
+ snprintf(sysfs_file_path, SYSFS_PATH_MAX, SYSFS_PERCPU_IDLE_SPURR, i);
+ cpu_sysfs_fds[cpu_idx].idle_spurr = assign_read_fd(sysfs_file_path);
+ if (cpu_sysfs_fds[cpu_idx].idle_spurr == -1)
+ goto error;
+
+ cpu_idx++;
+ }
+
+ return 0;
+error:
+ fprintf(stderr, "Failed to open %s\n", sysfs_file_path);
+ close_cpu_sysfs_fds(threads_in_system);
+ return -1;
+}
+
+static void sig_int_handler(int signal)
+{
+ close_cpu_sysfs_fds(threads_in_system);
+ exit(1);
+}
+
void get_time()
{
struct timeval t;
@@ -659,6 +737,15 @@ void init_sysinfo(void)
rc = get_nominal_frequency();
if (rc)
exit(rc);
+
+ if (signal(SIGINT, sig_int_handler) == SIG_ERR) {
+ fprintf(stderr, "Failed to add signal handler\n");
+ exit(-1);
+ }
+
+ rc = assign_cpu_sysfs_fds(threads_in_system);
+ if (rc)
+ exit(rc);
}
void init_sysdata(void)
@@ -841,5 +928,6 @@ int main(int argc, char *argv[])
else
print_default_output(interval, count);
+ close_cpu_sysfs_fds(threads_in_system);
return 0;
}
diff --git a/src/lparstat.h b/src/lparstat.h
index c1bac28..617737b 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -25,6 +25,10 @@
#define SYSDATA_NAME_SZ 64
#define SYSDATA_DESCR_SZ 128
+#define SYSFS_PERCPU_SPURR "/sys/devices/system/cpu/cpu%d/spurr"
+#define SYSFS_PERCPU_IDLE_PURR "/sys/devices/system/cpu/cpu%d/idle_purr"
+#define SYSFS_PERCPU_IDLE_SPURR "/sys/devices/system/cpu/cpu%d/idle_spurr"
+
struct sysentry {
char value[SYSDATA_VALUE_SZ]; /* value from file */
char old_value[SYSDATA_VALUE_SZ]; /* previous value from file */
@@ -33,6 +37,14 @@ struct sysentry {
void (*get)(struct sysentry *, char *);
};
+struct cpu_sysfs_file_desc {
+ int cpu; /* cpu number */
+ int spurr; /* per-cpu /sys/devices/system/cpu/cpuX/spurr file descriptor */
+ int idle_purr; /* per-cpu /sys/devices/system/cpu/cpuX/idle_purr file descriptor */
+ int idle_spurr; /* per-cpu /sys/devices/system/cpu/cpuX/idle_spurr file descriptor */
+};
+typedef struct cpu_sysfs_file_desc cpu_sysfs_fd;
+
extern void get_smt_state(struct sysentry *, char *);
extern void get_capped_mode(struct sysentry *, char *);
extern void get_memory_mode(struct sysentry *, char *);
--
2.25.3

View File

@ -0,0 +1,134 @@
From 6bc0d4f1e181c2254b7e35f9b3f77128f663a525 Mon Sep 17 00:00:00 2001
Message-Id: <6bc0d4f1e181c2254b7e35f9b3f77128f663a525.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 08:00:49 -0500
Subject: [PATCH V4 06/14] lparstat: Read SPURR, Idle_{PURR, SPURR} values
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Parse per-cpu
/sys/devices/system/cpu/cpu/{spurr, idle_purr, idle_spurr} files to
accumulate system wide SPURR, Idle PURR, Idle SPURR values like
PURR value captured in /proc/powerpc/lparcfg. Calculating scaled
utilization metrics, need them.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lparstat.h | 11 +++++++++
2 files changed, 71 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index f5c0ce5..7c55a8c 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -165,6 +165,61 @@ error:
return -1;
}
+int parse_sysfs_values(void)
+{
+ unsigned long long spurr, idle_spurr, idle_purr, value;
+ char line[SYSDATA_VALUE_SZ];
+ struct sysentry *se;
+ int i, rc;
+
+ spurr = idle_spurr = idle_purr = 0UL;
+
+ for (i = 0; cpu_sysfs_fds[i].spurr > 0; i++) {
+ rc = pread(cpu_sysfs_fds[i].spurr, (void *)line, sizeof(line), 0);
+ if (rc == -1) {
+ fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/spurr\n",
+ cpu_sysfs_fds[i].cpu);
+ goto error;
+ }
+
+ value = strtoll(line, NULL, 16);
+ spurr += value;
+
+ rc = pread(cpu_sysfs_fds[i].idle_purr, (void *)line, sizeof(line), 0);
+ if (rc == -1) {
+ fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_purr\n",
+ cpu_sysfs_fds[i].cpu);
+ goto error;
+ }
+
+ value = strtoll(line, NULL, 16);
+ idle_purr += value;
+
+ rc = pread(cpu_sysfs_fds[i].idle_spurr, (void *)line, sizeof(line), 0);
+ if (rc == -1) {
+ fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_spurr\n",
+ cpu_sysfs_fds[i].cpu);
+ goto error;
+ }
+
+ value = strtoll(line, NULL, 16);
+ idle_spurr += value;
+ }
+
+ se = get_sysentry("spurr");
+ sprintf(se->value, "%llu", spurr);
+ se = get_sysentry("idle_purr");
+ sprintf(se->value, "%llu", idle_purr);
+ se = get_sysentry("idle_spurr");
+ sprintf(se->value, "%llu", idle_spurr);
+
+ return 0;
+
+error:
+ close_cpu_sysfs_fds(threads_in_system);
+ return -1;
+}
+
static void sig_int_handler(int signal)
{
close_cpu_sysfs_fds(threads_in_system);
@@ -750,11 +805,16 @@ void init_sysinfo(void)
void init_sysdata(void)
{
+ int rc = 0;
+
get_time();
parse_lparcfg();
parse_proc_stat();
parse_proc_ints();
get_time_base();
+ rc = parse_sysfs_values();
+ if (rc)
+ exit(rc);
}
void update_sysdata(void)
diff --git a/src/lparstat.h b/src/lparstat.h
index 617737b..eec59d6 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -266,6 +266,17 @@ struct sysentry system_data[] = {
.descr = "System Uptime",
.get = &get_sys_uptime},
+ /* /sys/devices/system/cpu/cpu<n>/ */
+ /* Sum of per CPU SPURR registers */
+ {.name = "spurr",
+ .descr = "Scaled Processor Utilization Resource Register"},
+ /* Sum of per CPU Idle PURR Values */
+ {.name = "idle_purr",
+ .descr = "Processor Utilization Resource Idle Values"},
+ /* Sum of per CPU Idle SPURR Values */
+ {.name = "idle_spurr",
+ .descr = "Scaled Processor Utilization Resource Idle Values"},
+
{.name[0] = '\0'},
};
--
2.25.3

View File

@ -0,0 +1,51 @@
From b79f34df37d605954beaa381e6309d50386434b2 Mon Sep 17 00:00:00 2001
Message-Id: <b79f34df37d605954beaa381e6309d50386434b2.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 08:02:51 -0500
Subject: [PATCH V4 07/14] lparstat: Add helper function to calculate delta
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Add a helper function for one of the most often used arithmetics of
calculating delta of a sysentry.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 7c55a8c..152e5fa 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -226,6 +226,21 @@ static void sig_int_handler(int signal)
exit(1);
}
+long long get_delta_value(char *se_name)
+{
+ long long value, old_value;
+ struct sysentry *se;
+
+ se = get_sysentry(se_name);
+ if (se->value[0] == '\0')
+ return 0LL;
+
+ value = strtoll(se->value, NULL, 0);
+ old_value = strtoll(se->old_value, NULL, 0);
+
+ return (value - old_value);
+}
+
void get_time()
{
struct timeval t;
--
2.25.3

View File

@ -0,0 +1,89 @@
From 9f4055e95380a19a824f13cd3e629d2e73be075f Mon Sep 17 00:00:00 2001
Message-Id: <9f4055e95380a19a824f13cd3e629d2e73be075f.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 08:05:45 -0500
Subject: [PATCH V4 08/14] lparstat: Derive effective frequency
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Effective/current operating frequency is derived by following:
Effective frequency = (delta SPURR / delta PURR) * nominal frequency
it required to calculate the scaled variants using SPURR, whereas
the currently computed values based on the PURR.
performed.
Effective frequency is derived from PURR/SPURR values, hence call
get_frequency() after function updating sysfs values.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 23 +++++++++++++++++++++++
src/lparstat.h | 3 +++
2 files changed, 26 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 152e5fa..0f9dffc 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -352,6 +352,28 @@ int get_nominal_frequency(void)
return 0;
}
+void get_effective_frequency()
+{
+ struct sysentry *se;
+ double delta_purr, delta_spurr;
+ double nominal_freq, effective_freq;
+
+ se = get_sysentry("nominal_freq");
+ nominal_freq = strtol(se->value, NULL, 10);
+
+ /*
+ * Calculate the Effective Frequency (EF)
+ * EF = (delta SPURR / delta PURR) * nominal frequency
+ */
+ delta_purr = get_delta_value("purr");
+ delta_spurr = get_delta_value("spurr");
+
+ effective_freq = (delta_spurr / delta_purr) * nominal_freq;
+
+ se = get_sysentry("effective_freq");
+ sprintf(se->value, "%f", effective_freq);
+}
+
void get_cpu_physc(struct sysentry *unused_se, char *buf)
{
struct sysentry *se;
@@ -830,6 +852,7 @@ void init_sysdata(void)
rc = parse_sysfs_values();
if (rc)
exit(rc);
+ get_effective_frequency();
}
void update_sysdata(void)
diff --git a/src/lparstat.h b/src/lparstat.h
index eec59d6..5e91d67 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -256,6 +256,9 @@ struct sysentry system_data[] = {
.descr = "Timebase"},
{.name = "nominal_freq",
.descr = "Nominal Frequency"},
+ /* derived from nominal freq */
+ {.name = "effective_freq",
+ .descr = "Effective Frequency"},
/* /proc/interrupts */
{.name = "phint",
--
2.25.3

View File

@ -0,0 +1,57 @@
From 39cb3fba241a3fa77be3b3065e638aa4d807dae7 Mon Sep 17 00:00:00 2001
Message-Id: <39cb3fba241a3fa77be3b3065e638aa4d807dae7.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 08:06:40 -0500
Subject: [PATCH V4 09/14] lparstat: Add helper to calculate scaled timebase
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Timebase is used to derive system wide CPU utilization, scale it to
the number of online cores too like the PURR/SPURR registers values
accumulated across all online CPU cores. This helper also scales the
timebase register value to the interval passed.
Timebase = (Timebase * Elapsed Time) * online cores
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 0f9dffc..7628afa 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -294,6 +294,23 @@ int get_time_base()
return 0;
}
+double get_scaled_tb(void)
+{
+ double elapsed, timebase;
+ struct sysentry *se;
+ int online_cores;
+
+ se = get_sysentry("online_cores");
+ online_cores = atoi(se->value);
+
+ elapsed = elapsed_time() / 1000000.0;
+
+ se = get_sysentry("timebase");
+ timebase = atoi(se->value);
+
+ return (timebase * elapsed) * online_cores;
+}
+
void get_sys_uptime(struct sysentry *unused_se, char *uptime)
{
FILE *f;
--
2.25.3

View File

@ -0,0 +1,164 @@
From ec05852c7d2e10c924e9521c32fe002e0f8cde71 Mon Sep 17 00:00:00 2001
Message-Id: <ec05852c7d2e10c924e9521c32fe002e0f8cde71.1587532692.git.kamalesh@linux.vnet.ibm.com>
In-Reply-To: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
References: <cover.1587532692.git.kamalesh@linux.vnet.ibm.com>
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Tue, 21 Apr 2020 08:08:12 -0500
Subject: [PATCH V4 10/14] lparstat: Add helpers to derive PURR/SPURR values
To: powerpc-utils-devel@googlegroups.com
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>,
Nathan Lynch <nathanl@linux.ibm.com>,
Naveen N . Rao <naveen.n.rao@linux.vnet.ibm.com>,
Gautham R . Shenoy <ego@linux.vnet.ibm.com>,
Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
For every interval specified by the user, the PURR/SPURR delta values
are needed to be calculated. Add helpers to derive them.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lparstat.h | 22 +++++++++++++
2 files changed, 109 insertions(+)
diff --git a/src/lparstat.c b/src/lparstat.c
index 7628afa..84a6544 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -471,6 +471,93 @@ void get_cpu_app(struct sysentry *unused_se, char *buf)
sprintf(buf, "%.2f", app);
}
+static double round_off_freq(void)
+{
+ double effective_freq, nominal_freq, freq;
+ struct sysentry *se;
+
+ se = get_sysentry("effective_freq");
+ effective_freq = strtod(se->value, NULL);
+
+ se = get_sysentry("nominal_freq");
+ nominal_freq = strtod(se->value, NULL);
+
+ freq = ((int)((effective_freq/nominal_freq * 100)+ 0.44) -
+ (effective_freq/nominal_freq * 100)) /
+ (effective_freq/nominal_freq * 100) * 100;
+
+ return freq;
+}
+
+void get_cpu_util_purr(struct sysentry *unused_se, char *buf)
+{
+ double delta_tb, delta_purr, delta_idle_purr;
+ double physc;
+
+ delta_tb = get_scaled_tb();
+ delta_purr = get_delta_value("purr");
+ delta_idle_purr = get_delta_value("idle_purr");
+
+ physc = (delta_purr - delta_idle_purr) / delta_tb;
+ physc *= 100.00;
+
+ sprintf(buf, "%.2f", physc);
+}
+
+void get_cpu_idle_purr(struct sysentry *unused_se, char *buf)
+{
+ double delta_tb, delta_purr, delta_idle_purr;
+ double physc, idle;
+
+ delta_tb = get_scaled_tb();
+ delta_purr = get_delta_value("purr");
+ delta_idle_purr = get_delta_value("idle_purr");
+
+ physc = (delta_purr - delta_idle_purr) / delta_tb;
+ idle = (delta_purr / delta_tb) - physc;
+ idle *= 100.00;
+
+ sprintf(buf, "%.2f", idle);
+}
+
+void get_cpu_util_spurr(struct sysentry *unused_se, char *buf)
+{
+ double delta_tb, delta_spurr, delta_idle_spurr;
+ double physc, rfreq;
+
+ delta_tb = get_scaled_tb();
+ delta_spurr = get_delta_value("spurr");
+ delta_idle_spurr = get_delta_value("idle_spurr");
+
+ physc = (delta_spurr - delta_idle_spurr) / delta_tb;
+ physc *= 100.00;
+
+ rfreq = round_off_freq();
+ physc += ((physc * rfreq) / 100);
+
+ sprintf(buf, "%.2f", physc);
+}
+
+void get_cpu_idle_spurr(struct sysentry *unused_se, char *buf)
+{
+ double delta_tb, delta_spurr, delta_idle_spurr;
+ double physc, idle;
+ double rfreq;
+
+ delta_tb = get_scaled_tb();
+ delta_spurr = get_delta_value("spurr");
+ delta_idle_spurr = get_delta_value("idle_spurr");
+
+ physc = (delta_spurr - delta_idle_spurr) / delta_tb;
+ idle = (delta_spurr / delta_tb) - physc;
+ idle *= 100.00;
+
+ rfreq = round_off_freq();
+ idle += ((idle * rfreq) / 100);
+
+ sprintf(buf, "%.2f", idle);
+}
+
int parse_lparcfg()
{
FILE *f;
diff --git a/src/lparstat.h b/src/lparstat.h
index 5e91d67..9b7117f 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -60,6 +60,10 @@ extern void get_cpu_physc(struct sysentry *, char *);