import powerpc-utils-1.3.6-11.el8
This commit is contained in:
parent
e802888477
commit
aeb08e3947
@ -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
|
||||
|
34
SOURCES/0001-update_flash-Fix-warning.patch
Normal file
34
SOURCES/0001-update_flash-Fix-warning.patch
Normal 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
|
||||
|
165
SOURCES/0002-lparstat-Remove-ppc64_cpu-tool-dependency.patch
Normal file
165
SOURCES/0002-lparstat-Remove-ppc64_cpu-tool-dependency.patch
Normal 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
|
||||
|
99
SOURCES/0003-lparstat-Read-the-online-cores.patch
Normal file
99
SOURCES/0003-lparstat-Read-the-online-cores.patch
Normal 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
|
||||
|
94
SOURCES/0004-lparstat-Capture-nominal-frequency.patch
Normal file
94
SOURCES/0004-lparstat-Capture-nominal-frequency.patch
Normal 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
|
||||
|
@ -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
|
||||
|
134
SOURCES/0006-lparstat-Read-SPURR-Idle_-PURR-SPURR-values.patch
Normal file
134
SOURCES/0006-lparstat-Read-SPURR-Idle_-PURR-SPURR-values.patch
Normal 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
|
||||
|
@ -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
|
||||
|
89
SOURCES/0008-lparstat-Derive-effective-frequency.patch
Normal file
89
SOURCES/0008-lparstat-Derive-effective-frequency.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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 *);
|
||||