- Track and expose idle PURR and SPURR ticks

- ofpathname: speed up l2of_scsi()
- ofpathname: failed to boot
- update lparstat man page with -E option
- enable support for ibm,drc-info property
This commit is contained in:
Than Ngo 2020-07-09 15:15:41 +02:00
parent bf1b9db5ee
commit 6119fdc606
21 changed files with 2857 additions and 1 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,85 @@
From 4fe0e76e1d02787b4cf60eafd2fb3667897becf4 Mon Sep 17 00:00:00 2001
From: Michael Bringmann <mwb@linux.vnet.ibm.com>
Date: Tue, 23 Jul 2019 15:58:21 -0500
Subject: [PATCH 1/1] powerpc-utils: Suppress errors reading kernel
files
A problem was observed with the evaluation of the '${devspec}'
by the script 'ofpathname'. This patch provided improved
handling of errors within that script, and by some of the
follow-on uses of the tool by the 'bootlist' script.
* Deal with error messages returned sometimes by evaluation
of ${devspec} in 'ofpathname'.
* Strip embedded nulls from values provided by kernel files,
especially, /proc/device-tree${devspec}/namespace/name,
in 'ofpathname'.
* Redirect more error messages to /dev/null
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
scripts/bootlist | 8 ++++----
scripts/ofpathname | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/scripts/bootlist b/scripts/bootlist
index 65926d7..5ce20cf 100755
--- a/scripts/bootlist
+++ b/scripts/bootlist
@@ -169,7 +169,7 @@ get_logical_device_name()
local devname=$1
local logical_name
- logical_name=`$OFPATHNAME -l $devname 2>/dev/null`
+ logical_name=`$OFPATHNAME -l $devname 2>/dev/null | tr -d '\000'`
if [[ $? -ne 0 ]]; then
echo ""
else
@@ -207,11 +207,11 @@ show_bootlist()
local devlist=$1
local i
- for i in `$NVRAM --print-config=${devlist} | sed 's/ /\n/g'`; do
+ for i in `$NVRAM --print-config=${devlist} 2> /dev/null | sed 's/ /\n/g'`; do
if [[ $TRANSLATE_NAMES = "yes" ]]; then
name=`get_logical_device_name $i`
if [[ -z $name ]]; then
- echo "Could not translate $i to logical device name"
+ echo "Could not translate $i to logical device name" 2>&1
else
case $name in
eth*) parse_eth_info $name $i ;;
@@ -230,7 +230,7 @@ show_bootlist()
. $PSERIES_PLATFORM
if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then
- echo "bootlist: is not supported on the $platform_name platform"
+ echo "bootlist: is not supported on the $platform_name platform" 2>&1
exit 1
fi
diff --git a/scripts/ofpathname b/scripts/ofpathname
index c37c6bd..09c0209 100755
--- a/scripts/ofpathname
+++ b/scripts/ofpathname
@@ -656,7 +656,7 @@ l2of_nvme()
goto_dir $PWD "device/devspec"
- devspec=`$CAT $PWD/device/devspec`
+ devspec=`$CAT $PWD/device/devspec | tr -d '\000'`
if [[ -n $devspec ]]; then
found=1
break
@@ -681,7 +681,7 @@ l2of_nvme()
# Device type is usually 'namespace'.
# Get it from device-tree just in case.
- devtype=`$CAT /proc/device-tree${devspec}/namespace/name`
+ devtype=`$CAT /proc/device-tree${devspec}/namespace/name | tr -d '\000'` 2> /dev/null
if [[ -z $devtype ]]; then
err $ERR_NO_OFPATH
fi
--
1.8.3.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 *);
extern void get_per_entc(struct sysentry *, char *);
extern void get_cpu_app(struct sysentry *, char *);
extern void get_sys_uptime(struct sysentry *, char *);
+extern void get_cpu_util_purr(struct sysentry *unused_se, char *buf);
+extern void get_cpu_idle_purr(struct sysentry *unused_se, char *buf);
+extern void get_cpu_util_spurr(struct sysentry *unused_se, char *buf);
+extern void get_cpu_idle_spurr(struct sysentry *uunused_se, char *buf);
struct sysentry system_data[] = {
/* System Names */
@@ -280,6 +284,24 @@ struct sysentry system_data[] = {
{.name = "idle_spurr",
.descr = "Scaled Processor Utilization Resource Idle Values"},
+ /* Dervied from above sysfs values */
+ /* PURR Utilization */
+ {.name = "purr_cpu_util",
+ .descr = "Physical CPU consumed - PURR",
+ .get = &get_cpu_util_purr},
+ /* PURR Idle time */
+ {.name = "purr_cpu_idle",
+ .descr = "Idle CPU value - PURR",
+ .get = &get_cpu_idle_purr},
+ /* SPURR Utilization */
+ {.name = "spurr_cpu_util",
+ .descr = "Physical CPU consumed - SPURR",
+ .get = &get_cpu_util_spurr},
+ /* SPURR Idle time */
+ {.name = "spurr_cpu_idle",
+ .descr = "Idle CPU value - SPURR",
+ .get = &get_cpu_idle_spurr},
+
{.name[0] = '\0'},
};
--
2.25.3

View File

@ -0,0 +1,66 @@
From 1b176657dea3da2fc8b2c00bf6f0d8b25c92ee74 Mon Sep 17 00:00:00 2001
Message-Id: <1b176657dea3da2fc8b2c00bf6f0d8b25c92ee74.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:09:12 -0500
Subject: [PATCH V4 11/14] lparstat: Move displaying system configuration
details to new func
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>
System configuration details is required while displaying the
scaled metrics too. Move it to a new function, to be called by both
default, scaled metrics too.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/lparstat.c b/src/lparstat.c
index 84a6544..3768b79 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -989,16 +989,13 @@ int print_iflag_data()
return 0;
}
-void print_default_output(int interval, int count)
+void print_system_configuration(void)
{
- char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s %5s\n";
char *descr;
char buf[128];
int offset, smt, active_proc;
char type[32];
char value[32];
- char user[32], sys[32], wait[32], idle[32], physc[32], entc[32];
- char lbusy[32], app[32], vcsw[32], phint[32];
memset(buf, 0, 128);
get_sysdata("shared_processor_mode", &descr, value);
@@ -1031,6 +1028,16 @@ void print_default_output(int interval, int count)
offset += sprintf(buf + offset, "ent=%s ", value);
fprintf(stdout, "\nSystem Configuration\n%s\n\n", buf);
+}
+
+void print_default_output(int interval, int count)
+{
+ char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s %5s\n";
+ char *descr;
+ char user[32], sys[32], wait[32], idle[32], physc[32], entc[32];
+ char lbusy[32], app[32], vcsw[32], phint[32];
+
+ print_system_configuration();
fprintf(stdout, fmt, "\%user", "\%sys", "\%wait", "\%idle", "physc",
"\%entc", "lbusy", "app", "vcsw", "phint");
--
2.25.3

View File

@ -0,0 +1,161 @@
From 9ffdec9aca02761034cd5e87d8f6da0b54a4f770 Mon Sep 17 00:00:00 2001
Message-Id: <9ffdec9aca02761034cd5e87d8f6da0b54a4f770.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:15:25 -0500
Subject: [PATCH V4 12/14] lparstat: Add switch to print Scaled metrics
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 '-E' command line switch to print scaled version of meterics, this
switch prints CPU utilization/Idle based on Actual (PURR) and Scaled
(SPURR) values along with the current effective frequency of the system.
output:
~ # lparstat -E 1 3
System Configuration
type=Dedicated mode=Capped smt=8 lcpu=2 mem=4324928 kB cpus=0 ent=2.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
0.10 99.90 2.13GHz[ 70%] 0.10 69.91
0.07 99.92 2.10GHz[ 69%] 0.05 68.95
0.08 99.92 2.10GHz[ 69%] 0.05 68.95
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/src/lparstat.c b/src/lparstat.c
index 3768b79..5390b9f 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -40,6 +40,7 @@
#define SE_NOT_VALID "-"
static bool o_legacy = false;
+static bool o_scaled = false;
static int threads_per_cpu;
static int cpus_in_system;
@@ -928,6 +929,10 @@ void init_sysinfo(void)
exit(rc);
}
+ /* refer to init_sysdata for explanation */
+ if (!o_scaled)
+ return;
+
get_online_cores();
rc = get_nominal_frequency();
@@ -953,6 +958,12 @@ void init_sysdata(void)
parse_proc_stat();
parse_proc_ints();
get_time_base();
+
+ /* Skip reading spurr, purr, idle_{purr,spurr} and calculating
+ * effective frequency for default option */
+ if (!o_scaled)
+ return;
+
rc = parse_sysfs_values();
if (rc)
exit(rc);
@@ -1067,6 +1078,42 @@ void print_default_output(int interval, int count)
} while (--count > 0);
}
+void print_scaled_output(int interval, int count)
+{
+ char purr[32], purr_idle[32], spurr[32], spurr_idle[32];
+ char nominal_f[32], effective_f[32];
+ double nominal_freq, effective_freq;
+ char *descr;
+
+ print_system_configuration();
+
+ fprintf(stdout, "---Actual--- -Normalized-\n");
+ fprintf(stdout, "%%busy %%idle Frequency %%busy %%idle\n");
+ fprintf(stdout, "------ ------ ------------- ------ ------\n");
+ do {
+ if (interval) {
+ sleep(interval);
+ update_sysdata();
+ }
+
+ get_sysdata("purr_cpu_util", &descr, purr);
+ get_sysdata("purr_cpu_idle", &descr, purr_idle);
+ get_sysdata("spurr_cpu_util", &descr, spurr);
+ get_sysdata("spurr_cpu_idle", &descr, spurr_idle);
+ get_sysdata("nominal_freq", &descr, nominal_f);
+ get_sysdata("effective_freq", &descr, effective_f);
+ nominal_freq = strtod(nominal_f, NULL);
+ effective_freq = strtod(effective_f, NULL);
+
+ fprintf(stdout, "%6s %6s %5.2fGHz[%3d%%] %6s %6s\n",
+ purr, purr_idle,
+ effective_freq/1000,
+ (int)((effective_freq/nominal_freq * 100)+ 0.44 ),
+ spurr, spurr_idle );
+ fflush(stdout);
+ } while (--count > 0);
+}
+
static void usage(void)
{
printf("Usage: lparstat [ options ]\n\tlparstat <interval> [ count ]\n\n"
@@ -1074,6 +1121,7 @@ static void usage(void)
"\t-h, --help Show this message and exit.\n"
"\t-V, --version \tDisplay lparstat version information.\n"
"\t-i Lists details on the LPAR configuration.\n"
+ "\t-E Print SPURR metrics.\n"
"\t-l, --legacy Print the report in legacy format.\n"
"interval The interval parameter specifies the amount of time between each report.\n"
"count The count parameter specifies how many reports will be displayed.\n");
@@ -1098,7 +1146,7 @@ int main(int argc, char *argv[])
exit(1);
}
- while ((c = getopt_long(argc, argv, "iVhl",
+ while ((c = getopt_long(argc, argv, "iEVhl",
long_opts, &opt_index)) != -1) {
switch(c) {
case 'i':
@@ -1107,6 +1155,9 @@ int main(int argc, char *argv[])
case 'l':
o_legacy = true;
break;
+ case 'E':
+ o_scaled = true;
+ break;
case 'V':
printf("lparstat - %s\n", VERSION);
return 0;
@@ -1134,9 +1185,11 @@ int main(int argc, char *argv[])
if (i_option)
print_iflag_data();
- else
+ else if (o_scaled) {
+ print_scaled_output(interval, count);
+ close_cpu_sysfs_fds(threads_in_system);
+ } else {
print_default_output(interval, count);
-
- close_cpu_sysfs_fds(threads_in_system);
+ }
return 0;
}
--
2.25.3

View File

@ -0,0 +1,177 @@
From 179d461b79387bd3877cd239da933a8dfceae05c Mon Sep 17 00:00:00 2001
Message-Id: <179d461b79387bd3877cd239da933a8dfceae05c.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:23:24 -0500
Subject: [PATCH V4 13/14] lparstat: Add support for cpu-hotplug
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 optimizing the read of sysfs file, the file descriptors are
assigned at the beginning of the run but they do not change dynamically
in event of a cpu hotplug, resulting under-estimated load average in
case of new cpus onlined or error in case of cpu removed. This can be
solved by checking for the online cpus every interval and re-assign
the file descriptors again with new set of cpu on hotplug event.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 78 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 71 insertions(+), 7 deletions(-)
diff --git a/src/lparstat.c b/src/lparstat.c
index 5390b9f..51caa3d 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -21,6 +21,7 @@
* @author Nathan Fontenot <nfont@linux.vnet.ibm.com>
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
@@ -28,6 +29,7 @@
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sched.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -47,6 +49,7 @@ static int cpus_in_system;
static int threads_in_system;
static cpu_sysfs_fd *cpu_sysfs_fds;
+static cpu_set_t *online_cpus;
struct sysentry *get_sysentry(char *name)
{
@@ -180,7 +183,7 @@ int parse_sysfs_values(void)
if (rc == -1) {
fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/spurr\n",
cpu_sysfs_fds[i].cpu);
- goto error;
+ goto check_cpu_hotplug;
}
value = strtoll(line, NULL, 16);
@@ -190,7 +193,7 @@ int parse_sysfs_values(void)
if (rc == -1) {
fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_purr\n",
cpu_sysfs_fds[i].cpu);
- goto error;
+ goto check_cpu_hotplug;
}
value = strtoll(line, NULL, 16);
@@ -200,7 +203,7 @@ int parse_sysfs_values(void)
if (rc == -1) {
fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_spurr\n",
cpu_sysfs_fds[i].cpu);
- goto error;
+ goto check_cpu_hotplug;
}
value = strtoll(line, NULL, 16);
@@ -216,9 +219,11 @@ int parse_sysfs_values(void)
return 0;
-error:
- close_cpu_sysfs_fds(threads_in_system);
- return -1;
+check_cpu_hotplug:
+ if(!cpu_online(cpu_sysfs_fds[i].cpu))
+ return 1;
+
+ return rc;
}
static void sig_int_handler(int signal)
@@ -917,6 +922,52 @@ void get_cpu_stat(struct sysentry *se, char *buf)
sprintf(buf, "%.2f", percent);
}
+int has_cpu_topology_changed(void)
+{
+ int i, changed = 1;
+ cpu_set_t *tmp_cpuset;
+ size_t online_cpus_size = CPU_ALLOC_SIZE(threads_in_system);
+
+ if (!online_cpus) {
+ online_cpus = CPU_ALLOC(threads_in_system);
+ if (!online_cpus) {
+ fprintf(stderr, "Failed to allocate memory for cpu_set\n");
+ return -1;
+ }
+
+ CPU_ZERO_S(online_cpus_size, online_cpus);
+
+ for (i = 0; i < threads_in_system; i++) {
+ if (!cpu_online(i))
+ continue;
+ CPU_SET_S(i, online_cpus_size, online_cpus);
+ }
+
+ return changed;
+ }
+
+ tmp_cpuset = CPU_ALLOC(threads_in_system);
+ if (!tmp_cpuset) {
+ fprintf(stderr, "Failed to allocate memory for cpu_set\n");
+ return -1;
+ }
+
+ CPU_ZERO_S(online_cpus_size, tmp_cpuset);
+
+ for (i = 0; i < threads_in_system; i++) {
+ if (!cpu_online(i))
+ continue;
+ CPU_SET_S(i, online_cpus_size, tmp_cpuset);
+ }
+
+ changed = CPU_EQUAL_S(online_cpus_size, online_cpus, tmp_cpuset);
+
+ CPU_FREE(online_cpus);
+ online_cpus = tmp_cpuset;
+
+ return changed;
+}
+
void init_sysinfo(void)
{
int rc = 0;
@@ -964,10 +1015,23 @@ void init_sysdata(void)
if (!o_scaled)
return;
+ rc = has_cpu_topology_changed();
+ if (!rc)
+ goto cpu_hotplug_restart;
+
rc = parse_sysfs_values();
- if (rc)
+ if (rc == -1)
exit(rc);
+ else if (rc)
+ goto cpu_hotplug_restart;
+
get_effective_frequency();
+
+ return;
+
+cpu_hotplug_restart:
+ close_cpu_sysfs_fds(threads_in_system);
+ init_sysinfo();
}
void update_sysdata(void)
--
2.25.3

View File

@ -0,0 +1,148 @@
From 1ee9fc2d08a1a4aa34e17fce2234ba5abec9b4ae Mon Sep 17 00:00:00 2001
Message-Id: <1ee9fc2d08a1a4aa34e17fce2234ba5abec9b4ae.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:24:43 -0500
Subject: [PATCH V4 14/14] lparstat: Use get_delta_value() helper
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>
Use get_delta_value(), helper, to calculate the delta of interested
values instead of duplicating it in various functions. This reduces
the amount of duplication and makes code more readable.
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
src/lparstat.c | 61 ++++++++++++++------------------------------------
1 file changed, 17 insertions(+), 44 deletions(-)
diff --git a/src/lparstat.c b/src/lparstat.c
index 51caa3d..29e6365 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -259,18 +259,6 @@ void get_time()
(long long)t.tv_sec * 1000000LL + (long long)t.tv_usec);
}
-long long elapsed_time()
-{
- long long newtime, oldtime = 0;
- struct sysentry *se;
-
- se = get_sysentry("time");
- newtime = strtoll(se->value, NULL, 0);
- oldtime = strtoll(se->old_value, NULL, 0);
-
- return newtime - oldtime;
-}
-
int get_time_base()
{
FILE *f;
@@ -309,7 +297,8 @@ double get_scaled_tb(void)
se = get_sysentry("online_cores");
online_cores = atoi(se->value);
- elapsed = elapsed_time() / 1000000.0;
+ elapsed = get_delta_value("time");
+ elapsed = elapsed / 1000000.0;
se = get_sysentry("timebase");
timebase = atoi(se->value);
@@ -401,27 +390,25 @@ void get_cpu_physc(struct sysentry *unused_se, char *buf)
{
struct sysentry *se;
float elapsed;
- float new_purr, old_purr;
+ float delta_purr;
float timebase, physc;
- float new_tb, old_tb;
+ float delta_tb;
- se = get_sysentry("purr");
- new_purr = strtoll(se->value, NULL, 0);
- old_purr = strtoll(se->old_value, NULL, 0);
+ delta_purr = get_delta_value("purr");
se = get_sysentry("tbr");
if (se->value[0] != '\0') {
- new_tb = strtoll(se->value, NULL, 0);
- old_tb = strtoll(se->old_value, NULL, 0);
+ delta_tb = get_delta_value("tbr");
- physc = (new_purr - old_purr) / (new_tb - old_tb);
+ physc = delta_purr / delta_tb;
} else {
- elapsed = elapsed_time() / 1000000.0;
+ elapsed = get_delta_value("time");
+ elapsed = elapsed / 1000000.0;
se = get_sysentry("timebase");
timebase = atoi(se->value);
- physc = (new_purr - old_purr)/timebase/elapsed;
+ physc = delta_purr/timebase/elapsed;
}
sprintf(buf, "%.2f", physc);
@@ -443,7 +430,7 @@ void get_cpu_app(struct sysentry *unused_se, char *buf)
{
struct sysentry *se;
float timebase, app, elapsed_time;
- long long new_app, old_app, newtime, oldtime;
+ long long new_app, old_app, delta_time;
char *descr, uptime[32];
se = get_sysentry("time");
@@ -457,9 +444,8 @@ void get_cpu_app(struct sysentry *unused_se, char *buf)
}
elapsed_time = atof(uptime);
} else {
- newtime = strtoll(se->value, NULL, 0);
- oldtime = strtoll(se->old_value, NULL, 0);
- elapsed_time = (newtime - oldtime) / 1000000.0;
+ delta_time = get_delta_value("time");
+ elapsed_time = delta_time / 1000000.0;
}
se = get_sysentry("timebase");
@@ -898,27 +884,14 @@ void get_online_cores(void)
free(core_state);
}
-long long get_cpu_time_diff()
-{
- long long old_total = 0, new_total = 0;
- struct sysentry *se;
-
- se = get_sysentry("cpu_total");
- new_total = strtoll(se->value, NULL, 0);
- old_total = strtoll(se->old_value, NULL, 0);
-
- return new_total - old_total;
-}
-
void get_cpu_stat(struct sysentry *se, char *buf)
{
float percent;
- long long total, old_val, new_val;
+ long long total, delta_val;
- total = get_cpu_time_diff();
- new_val = atoll(se->value);
- old_val = atoll(se->old_value);
- percent = ((new_val - old_val)/(long double)total) * 100;
+ total = get_delta_value("cpu_total");
+ delta_val = get_delta_value(se->name);
+ percent = (delta_val/(long double)total) * 100;
sprintf(buf, "%.2f", percent);
}
--
2.25.3

View File

@ -0,0 +1,12 @@
diff -up powerpc-utils-1.3.6/scripts/ofpathname.me powerpc-utils-1.3.6/scripts/ofpathname
--- powerpc-utils-1.3.6/scripts/ofpathname.me 2020-06-24 09:53:03.145041606 +0200
+++ powerpc-utils-1.3.6/scripts/ofpathname 2020-06-24 09:55:11.040981495 +0200
@@ -286,7 +286,7 @@ get_usb_storage_no()
# $3 on_exit behavior on error
goto_dir()
{
- local start_dir=$1
+ local start_dir=$(readlink -f $1)
local fname=$2
local found=0
local on_exit=1

View File

@ -0,0 +1,272 @@
commit b0586b5938e9d371e55671422b2f0a5d2cd10c54
Author: Michael Bringmann <mwb@linux.vnet.ibm.com>
Date: Wed Oct 2 16:54:52 2019 -0500
powerpc-utils/devtree: Parse 'ibm,drc-info' property
Parse new DRC Info: Define data structures to support parsing
the new "ibm,drc-info" device tree property. Integrate the new
property information into the existing search mechanisms of the
userspace 'drmgr' driver.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
diff --git a/src/drmgr/common_ofdt.c b/src/drmgr/common_ofdt.c
index 8c9e224..c110bc0 100644
--- a/src/drmgr/common_ofdt.c
+++ b/src/drmgr/common_ofdt.c
@@ -41,6 +41,16 @@ struct drc_prop_grp {
struct of_list_prop drc_domains;
};
+struct drc_info {
+ char *drc_type;
+ char *drc_name_prefix;
+ int drc_index_start;
+ int drc_name_suffix_start;
+ int n_seq_elems;
+ int seq_inc;
+ int drc_power_domain;
+};
+
struct dr_connector *all_drc_lists = NULL;
/**
@@ -186,6 +196,169 @@ build_connectors_list(struct drc_prop_grp *group, int n_entries,
return 0;
}
+/**
+ * drc_info_connectors_v1
+ *
+ * @param full_path
+ * @param ofdt_path
+ * @param list
+ * @returns 0 on success, !0 otherwise
+ */
+static int drc_info_connectors_v1(char *full_path, char *ofdt_path,
+ struct dr_connector **list)
+{
+ struct dr_connector *out_list = NULL;
+ struct drc_prop_grp prop_grp;
+ struct of_list_prop *drc_names;
+ int n_drcs;
+ int rc = 0;
+
+ rc = get_drc_prop_grp(full_path, &prop_grp);
+ if (rc) {
+ say(DEBUG,
+ "Could not find DRC property group in path: %s.\n",
+ full_path);
+ goto done;
+ }
+
+ drc_names = &prop_grp.drc_names;
+ n_drcs = drc_names->n_entries;
+
+ out_list = zalloc(n_drcs * sizeof(struct dr_connector));
+ if (out_list == NULL)
+ goto done;
+
+ build_connectors_list(&prop_grp, n_drcs, out_list);
+
+done:
+ if (rc) {
+ free_drc_props(&prop_grp);
+ free(out_list);
+ } else {
+ snprintf(out_list->ofdt_path, DR_PATH_MAX, "%s", ofdt_path);
+ *list = out_list;
+ }
+
+ return rc;
+}
+
+/**
+ * drc_info_connectors_v2
+ *
+ * @param full_path
+ * @param ofdt_path
+ * @param list
+ * @returns 0 on success, !0 otherwise
+ */
+static int drc_info_connectors_v2(char *full_path, char *ofdt_path,
+ struct dr_connector **list)
+{
+ struct dr_connector *out_list = NULL;
+ struct drc_info info;
+ char *prop_name = "ibm,drc-info";
+ char *prop_data, *data_ptr;
+ int i, j, n_entries, size, connector_size, ics, rc;
+
+ size = get_property_size(full_path, prop_name);
+ prop_data = zalloc(size);
+ if (prop_data == NULL)
+ return -1;
+ rc = get_property(full_path, prop_name, prop_data, size);
+ if (rc) {
+ free(prop_data);
+ return -1;
+ }
+
+ /* Num of DRC-info sets */
+ data_ptr = prop_data;
+ n_entries = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ /* Extract drc-info data */
+ for (j = 0, connector_size = 0; j < n_entries; j++) {
+ info.drc_type = data_ptr;
+ data_ptr += strlen(info.drc_type)+1;
+ info.drc_name_prefix = data_ptr;
+ data_ptr += strlen(info.drc_name_prefix)+1;
+ data_ptr += 4; /* Skip drc-index-start */
+ data_ptr += 4; /* Skip drc-name-suffix-start */
+ info.n_seq_elems = be32toh(*(uint *)data_ptr);
+ data_ptr += 4; /* Advance over n-seq-elems */
+ data_ptr += 4; /* Skip sequential-increment */
+ data_ptr += 4; /* Skip drc-power-domain */
+ if (info.n_seq_elems <= 0)
+ continue;
+ connector_size += info.n_seq_elems;
+ }
+
+ /* Allocate list entry */
+ out_list = zalloc(connector_size * sizeof(struct dr_connector));
+ if (out_list == NULL) {
+ rc = -1;
+ goto done;
+ }
+
+ /* Extract drc-info data */
+ data_ptr = prop_data;
+ data_ptr += 4;
+ for (j = 0, ics = 0; j < n_entries; j++) {
+ info.drc_type = data_ptr;
+ data_ptr += strlen(info.drc_type)+1;
+ info.drc_name_prefix = data_ptr;
+ data_ptr += strlen(info.drc_name_prefix)+1;
+
+ info.drc_index_start = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.drc_name_suffix_start = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.n_seq_elems = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.seq_inc = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.drc_power_domain = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ /* Build connector list */
+ if (info.n_seq_elems <= 0)
+ continue;
+
+ for (i = 0; i < info.n_seq_elems; i++, ics++) {
+ out_list[ics].index = info.drc_index_start+
+ (i*info.seq_inc);
+ out_list[ics].powerdomain = info.drc_power_domain;
+
+ sprintf(out_list[ics].name, "%s%d",
+ info.drc_name_prefix,
+ info.drc_name_suffix_start+(i*info.seq_inc));
+
+ strncpy(out_list[ics].type, info.drc_type, DRC_STR_MAX);
+
+ out_list[ics].next = &out_list[ics+1];
+ }
+ }
+ if (ics > 0)
+ out_list[ics-1].next = NULL;
+
+done:
+ if (prop_data)
+ free(prop_data);
+
+ if (rc) {
+ free(out_list);
+ *list = NULL;
+ } else {
+ snprintf(out_list->ofdt_path, DR_PATH_MAX, "%s", ofdt_path);
+ *list = out_list;
+ }
+
+ return rc;
+}
+
+
/**
* of_to_full_path
*
@@ -232,11 +405,12 @@ of_to_full_path(const char *of_path)
struct dr_connector *
get_drc_info(const char *of_path)
{
- struct dr_connector *list = NULL;
- struct of_list_prop *drc_names;
- struct drc_prop_grp prop_grp;
+ struct stat sbuf;
+ char fname[DR_PATH_MAX];
+ char ofdt_path[DR_PATH_MAX];
char *full_path = NULL;
- int rc, n_drcs;
+ struct dr_connector *list = NULL;
+ int rc;
for (list = all_drc_lists; list; list = list->all_next) {
if (! strcmp(list->ofdt_path, of_path))
@@ -246,33 +420,24 @@ get_drc_info(const char *of_path)
full_path = of_to_full_path(of_path);
if (full_path == NULL)
return NULL;
-
- rc = get_drc_prop_grp(full_path, &prop_grp);
- if (rc) {
- say(DEBUG, "Could not find DRC property group in path: %s.\n",
- full_path);
- goto done;
- }
- drc_names = &prop_grp.drc_names;
- n_drcs = drc_names->n_entries;
-
- list = zalloc(n_drcs * sizeof(struct dr_connector));
- if (list == NULL)
- goto done;
-
- /* XXX Unchecked rc */
- rc = build_connectors_list(&prop_grp, n_drcs, list);
-
- snprintf(list->ofdt_path, DR_PATH_MAX, "%s", of_path);
-
- list->all_next = all_drc_lists;
- all_drc_lists = list;
+ /* ibm,drc-info vs the old implementation */
+ sprintf(fname, "%s/%s", full_path, "ibm,drc-info");
+ snprintf(ofdt_path, DR_PATH_MAX, "%s", of_path);
+ rc = stat(fname, &sbuf);
+ if (rc)
+ rc = drc_info_connectors_v1(full_path, ofdt_path, &list);
+ else
+ rc = drc_info_connectors_v2(full_path, ofdt_path, &list);
-done:
- free_drc_props(&prop_grp);
- if (full_path)
- free(full_path);
+ if (rc == 0) {
+ list->all_next = all_drc_lists;
+ all_drc_lists = list;
+ } else {
+ if (full_path)
+ free(full_path);
+ list = NULL;
+ }
return list;
}

View File

@ -0,0 +1,64 @@
commit ea4db66e941720313af2c6b1afb32a74f3e360f4
Author: Michael Bringmann <mwb@linux.vnet.ibm.com>
Date: Tue Sep 10 14:31:42 2019 -0500
Safe bootlist update
This patch is intended to prevent problems with identifying or parsing
the bootlist devices from propagating into the system NVRAM configuration.
A number of such problems have been observed when processing USB devices.
* If 'bootlist' encounters an invalid OF_DEVPATH entry, it will print
an notice, but still continue on to write invalid data to nvram.
Changed to abort the script before writing bad data to nvram.
* When 'ofpathname' encounters an invalid 'devspec' file or invalid
value in a 'devspec' file, while trying to find the logical pathname
for a scsi device, it may continue to return the invalid 'devspec'
value to the caller/invoking script.
Changed to abort with an error message instead of returning that
invalid value to a caller like 'bootlist'.
Example:
# bootlist -m normal sdb
# bootlist -m normal -o
Could not translate (null)/scsi@0/sd@0,0 to logical device name
Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
diff --git a/scripts/bootlist b/scripts/bootlist
index 65926d7..acdaf89 100755
--- a/scripts/bootlist
+++ b/scripts/bootlist
@@ -459,6 +459,7 @@ if [[ ${#LOGICAL_NAMES[*]} -ne 0 ]]; then
if [[ -z ${OF_DEVPATH[$ctr]} ]]; then
echo "Device ${LOGICAL_NAMES[$ctr]} does not appear to be valid." >&2
+ exit 1
else
# See if this is an ethernet adapter. If so, the next entries
# may be parameters for the bootlist entry.
diff --git a/scripts/ofpathname b/scripts/ofpathname
index c37c6bd..dc452c4 100755
--- a/scripts/ofpathname
+++ b/scripts/ofpathname
@@ -803,9 +803,16 @@ l2of_scsi()
# move up directories until we find one with devspec information
goto_dir $PWD "devspec"
- OF_PATH=`$CAT $PWD/devspec`
+ if [[ -e $PWD/devspec ]]; then
+ OF_PATH=`$CAT $PWD/devspec`
+ else
+ err $ERR_NO_OFPATH
+ fi
+
if [[ -z $OF_PATH ]]; then
err $ERR_NO_OFPATH
+ elif [[ ! -e /proc/device-tree/$OF_PATH ]]; then
+ err $ERR_NO_OFPATH
fi
local vdev=${OF_PATH%/*}

View File

@ -0,0 +1,40 @@
lparstat -E option reports the actual and normalized system utilization
based on the PURR/SPURR registers. Update the lparstat man page too with
the -E option details.
Reported-by: Pavithra Prakash <pavr...@in.ibm.com>
Signed-off-by: Kamalesh Babulal <kama...@linux.vnet.ibm.com>
---
Applies on top of next branch.
man/lparstat.8 | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/man/lparstat.8 b/man/lparstat.8
index 0f4c923aaef5..d00e42600165 100644
--- a/man/lparstat.8
+++ b/man/lparstat.8
@@ -209,6 +209,17 @@ The variable memory capacity weight of the LPAR.
.TP
.SH
.TP
+\fB\-E\fR
+Display Scaled Processor Utilization Resource Register(SPURR) based CPU utilization.
+.RS
+.RS
+Actual CPU utilization is based on Processor Utilization Resource Register(PURR).
+.RS
+.RE
+Normalized CPU utilization is based on Scaled Processor Utilization Resource Register(SPURR).
+.TP
+.SH
+.TP
\fB\-l, --legacy\fR
Display the report in legacy format.
.RS
base-commit: 60d9f54b13b75feee3fd7b25a92b24d0d97ea984
--
2.26.2

View File

@ -0,0 +1,30 @@
commit c97fe35b5b6d767b88419fa2084a59e986ac3da0
Author: Nathan Lynch <nathanl@linux.ibm.com>
Date: Mon Apr 27 20:48:04 2020 -0500
ofpathname: speed up l2of_scsi()
There is no need to search the entire /sys hierarchy for kernel device
names like "sda". We know that if it is present it will be in
/sys/class/block.
In an environment with more than 800 scsi devices, this brings the
execution time for a command like "lsdevinfo -F name -c -q
parent=host1" from over 20 minutes to under two minutes.
Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
diff --git a/scripts/ofpathname b/scripts/ofpathname
index 7c6345e..bd61ee0 100755
--- a/scripts/ofpathname
+++ b/scripts/ofpathname
@@ -773,7 +773,7 @@ l2of_scsi()
local devtype
# There may be many instances of DEVICE under /sys
- for dir in `$FIND /sys -name $DEVICE`; do
+ for dir in `$FIND /sys/class/block -name $DEVICE`; do
# Move up until we find one with a device link
goto_dir $dir "device" 0
if [ $? -eq 0 ]; then

View File

@ -1,6 +1,6 @@
Name: powerpc-utils Name: powerpc-utils
Version: 1.3.7 Version: 1.3.7
Release: 5%{?dist} Release: 6%{?dist}
Summary: Utilities for PowerPC platforms Summary: Utilities for PowerPC platforms
License: GPLv2 License: GPLv2
@ -38,6 +38,30 @@ Patch5: powerpc-utils-1.3.5-install-man.patch
Patch6: powerpc-utils-1.3.4-systemd.patch Patch6: powerpc-utils-1.3.4-systemd.patch
Patch7: powerpc-utils-segfault_when_running_drmgr_-c_pmig_-h.patch Patch7: powerpc-utils-segfault_when_running_drmgr_-c_pmig_-h.patch
Patch8: powerpc-utils-fixup_null_byte.patch Patch8: powerpc-utils-fixup_null_byte.patch
# Improve handling of errors from subsidiary scripts
Patch12: 0001-powerpc-utils-Suppress-errors-reading-kern.v2.patch
Patch13: powerpc-utils-ea4db66e941720313af2c6b1afb32a74f3e360f4.patch
Patch15: powerpc-utils-b0586b5938e9d371e55671422b2f0a5d2cd10c54.patch
# Track and expose idle PURR and SPURR ticks
Patch17: 0001-common-cpu_info_helpers-library-to-capture-CPU-infor.patch
Patch18: 0002-lparstat-Remove-ppc64_cpu-tool-dependency.patch
Patch19: 0003-lparstat-Read-the-online-cores.patch
Patch20: 0004-lparstat-Capture-nominal-frequency.patch
Patch21: 0005-lparstat-Assign-file-descriptors-to-speed-up-read.patch
Patch22: 0006-lparstat-Read-SPURR-Idle_-PURR-SPURR-values.patch
Patch23: 0007-lparstat-Add-helper-function-to-calculate-delta.patch
Patch24: 0008-lparstat-Derive-effective-frequency.patch
Patch25: 0009-lparstat-Add-helper-to-calculate-scaled-timebase.patch
Patch26: 0010-lparstat-Add-helpers-to-derive-PURR-SPURR-values.patch
Patch27: 0011-lparstat-Move-displaying-system-configuration-detail.patch
Patch28: 0012-lparstat-Add-switch-to-print-Scaled-metrics.patch
Patch29: 0013-lparstat-Add-support-for-cpu-hotplug.patch
Patch30: 0014-lparstat-Use-get_delta_value-helper.patch
# ofpathname: speed up l2of_scsi()
Patch31: powerpc-utils-ofpathname-c97fe35b5b6d767b88419fa2084a59e986ac3da0.patch
# Update man page with -E option
Patch32: powerpc-utils-manpage-lparstat.patch
Patch33: powerpc-utils-1.3.6-bz#1847604.patch
%description %description
Utilities for PowerPC platforms. Utilities for PowerPC platforms.
@ -181,6 +205,13 @@ rm -f $RPM_BUILD_ROOT%{_sbindir}/snap $RPM_BUILD_ROOT%{_mandir}/man8/snap.8*
%changelog %changelog
* Thu Jul 09 2020 Than Ngo <than@redhat.com> - 1.3.7-6
- Track and expose idle PURR and SPURR ticks
- ofpathname: speed up l2of_scsi()
- ofpathname: failed to boot
- update lparstat man page with -E option
- enable support for ibm,drc-info property
* Sat Mar 28 2020 Than Ngo <than@redhat.com> - 1.3.7-5 * Sat Mar 28 2020 Than Ngo <than@redhat.com> - 1.3.7-5
- move drmgr in core to avoid pulling in Perl - move drmgr in core to avoid pulling in Perl