From fbcb3f384aaa79884c3b831bbe33b7239dfb0fdc Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 23 Dec 2021 13:24:18 +0100 Subject: [PATCH] cpumf/chcpumf-lscpumf: Use libcpumf.a library functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new library functions defined in libcpumf/libcpumf.a Signed-off-by: Thomas Richter Acked-by: Sumanth Korikkar Signed-off-by: Jan Höppner --- common.mak | 4 + cpumf/Makefile | 2 +- cpumf/chcpumf.c | 59 +++++---------- cpumf/lscpumf.c | 195 ++++++++++++------------------------------------ 4 files changed, 74 insertions(+), 186 deletions(-) diff --git a/common.mak b/common.mak index feac2996..9624f354 100644 --- a/common.mak +++ b/common.mak @@ -371,6 +371,10 @@ $(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp $(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a .PHONY: $(rootdir)/libvmcp +$(rootdir)/libcpumf/libcpumf.a: $(rootdir)/libcpumf + $(MAKE) -C $(rootdir)/libcpumf/ libcpumf.a +.PHONY: $(rootdir)/libcpumf + $(rootdir)/libekmfweb/libekmfweb.so: $(rootdir)/libekmfweb $(MAKE) -C $(rootdir)/libekmfweb/ libekmfweb.so .PHONY: $(rootdir)/libekmfweb diff --git a/cpumf/Makefile b/cpumf/Makefile index 78612e75..9f3ebee9 100644 --- a/cpumf/Makefile +++ b/cpumf/Makefile @@ -5,7 +5,7 @@ MAN_FILES = lscpumf.1 chcpumf.8 lshwc.1 all: $(BIN_FILES) -libs = $(rootdir)/libutil/libutil.a +libs = $(rootdir)/libutil/libutil.a $(rootdir)/libcpumf/libcpumf.a lscpumf: lscpumf.o $(libs) chcpumf: chcpumf.o $(libs) diff --git a/cpumf/chcpumf.c b/cpumf/chcpumf.c index 0ba8e7b1..55094078 100644 --- a/cpumf/chcpumf.c +++ b/cpumf/chcpumf.c @@ -1,7 +1,7 @@ /* * chcpumf - Change CPU Measurement Facility Characteristics * - * Copyright IBM Corp. 2020 + * Copyright IBM Corp. 2020, 2022 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -20,9 +20,9 @@ #include "lib/util_prg.h" #include "lib/util_base.h" -#include "defines.h" +#include "lib/libcpumf.h" -static int verbose; +static unsigned int verbose; static unsigned long min_sdb, max_sdb; static struct util_opt opt_vec[] = { @@ -85,55 +85,30 @@ static long parse_buffersize(char *string) return bytes; } -static void read_sfb(unsigned long *min, unsigned long *max) -{ - unsigned long cur_min_sdb, cur_max_sdb; - FILE *fp; - - if (geteuid()) - errx(EXIT_FAILURE, "Must run as root"); - fp = fopen(PERF_SFB_SIZE, "r"); - if (!fp) - err(EXIT_FAILURE, PERF_SFB_SIZE); - if (fscanf(fp, "%ld,%ld", &cur_min_sdb, &cur_max_sdb) != 2) { - fclose(fp); - errx(EXIT_FAILURE, "Can not parse file " PERF_SFB_SIZE); - } else { - if (*min == 0) - *min = cur_min_sdb; - if (*max == 0) - *max = cur_max_sdb; - } - fclose(fp); - if (*min >= *max) - errx(EXIT_FAILURE, - "The specified maximum must be greater than the minimum"); -} - -static int write_sfb(unsigned long min, unsigned long max) +static int write_sfb(unsigned int min, unsigned int max) { int rc = EXIT_SUCCESS; char text[64]; size_t len; FILE *fp; - fp = fopen(PERF_SFB_SIZE, "w"); + fp = fopen(S390_CPUMSF_BUFFERSZ, "w"); if (!fp) - err(EXIT_FAILURE, PERF_SFB_SIZE); - snprintf(text, sizeof text, "%ld,%ld", min, max); + err(EXIT_FAILURE, S390_CPUMSF_BUFFERSZ); + snprintf(text, sizeof(text), "%u,%u", min, max); len = strlen(text) + 1; if (fwrite(text, 1, len, fp) != len) { - warn(PERF_SFB_SIZE); + warn(S390_CPUMSF_BUFFERSZ); rc = EXIT_FAILURE; } if (fclose(fp)) { - warn(PERF_SFB_SIZE); + warn(S390_CPUMSF_BUFFERSZ); rc = EXIT_FAILURE; } if (verbose && rc != EXIT_FAILURE) warnx("Sampling buffer sizes:\n" - " Minimum:%7ld sample-data-blocks\n" - " Maximum:%7ld sample-data-blocks\n", + " Minimum:%7d sample-data-blocks\n" + " Maximum:%7d sample-data-blocks\n", min, max); return rc; } @@ -183,15 +158,21 @@ static int parse_args(int argc, char **argv) int main(int argc, char **argv) { - struct stat sbuf; + unsigned long my_min, my_max; util_prg_init(&prg); util_opt_init(opt_vec, NULL); parse_args(argc, argv); - if (stat(PERF_PATH PERF_SF, &sbuf)) + if (geteuid()) + errx(EXIT_FAILURE, "Must run as root"); + if (!libcpumf_have_sfb()) errx(EXIT_FAILURE, "No CPU-measurement sampling facility detected"); - read_sfb(&min_sdb, &max_sdb); + libcpumf_sfb_info(&my_min, &my_max); + if (!min_sdb) + min_sdb = my_min; + if (!max_sdb) + max_sdb = my_max; return write_sfb(min_sdb, max_sdb); } diff --git a/cpumf/lscpumf.c b/cpumf/lscpumf.c index c1aedd63..32186792 100644 --- a/cpumf/lscpumf.c +++ b/cpumf/lscpumf.c @@ -1,7 +1,7 @@ /* * lscpumf - Show CPU Measurement Facility Characteristics * - * Copyright IBM Corp. 2020 + * Copyright IBM Corp. 2020, 2022 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -28,7 +28,7 @@ #include "lib/util_opt.h" #include "lib/util_prg.h" -#include "defines.h" +#include "lib/libcpumf.h" #define ACTION_NONE 0 #define ACTION_INFO 1 @@ -45,9 +45,6 @@ static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */ #define PER_SDBT_SIZE 511 /* File names to read data from */ -#define SERVICELEVEL "/proc/service_levels" -#define CPUMF_CF_TYPE "/sys/devices/cpum_cf/type" -#define CPUMF_SF_TYPE "/sys/devices/cpum_sf/type" static struct util_opt opt_vec[] = { UTIL_OPT_SECTION("OPTIONS"), @@ -92,19 +89,18 @@ static char prefix[32]; /* Counter prefix */ static bool show_names; static struct cpumf_info { - unsigned int first_vn; /* Counter facility first version nr */ - unsigned int second_vn; /* Counter facility second version nr */ - unsigned int authorization; /* Counter facility authorization */ - float version; + int first_vn; /* Counter facility first version nr */ + int second_vn; /* Counter facility second version nr */ + int authorization; /* Counter facility authorization */ unsigned long min_rate; /* Minimum sampling rate */ unsigned long max_rate; /* Maximum sampling rate */ unsigned long cpu_speed; /* CPU Cycles per micro second */ - unsigned int basic_sample_sz; /* # of Bytes per basic sample */ - unsigned int diag_sample_sz; /* # of bytes per diagnostic sample */ - unsigned char have_counter; /* CPUM counter facility detected */ - unsigned char have_samples; /* CPUM sampling facility detected */ - unsigned int min_sfb; /* Minimum sampling buffer size */ - unsigned int max_sfb; /* Maximum sampling buffer size */ + int basic_sample_sz; /* # of Bytes per basic sample */ + int diag_sample_sz; /* # of bytes per diagnostic sample */ + bool have_counter; /* CPUM counter facility detected */ + bool have_samples; /* CPUM sampling facility detected */ + unsigned long min_sfb; /* Minimum sampling buffer size */ + unsigned long max_sfb; /* Maximum sampling buffer size */ unsigned short machine_type; /* Machine Type */ } cpumf; @@ -2565,26 +2561,12 @@ static struct counters cpumcf_z15_counters[] = { * If perf_pmu_register() kernel function assigned any other (higher) type * number, set the prefix to : */ -static int read_cpumf_type(const char *filename, const char *type) +static void set_prefix(int nr) { - int nr, rc = EXIT_FAILURE; - FILE *fp = fopen(filename, "r"); - - if (fp == NULL) { - warnx("No CPU-measurement %s facility detected", type); - return rc; - } - if (fscanf(fp, "%d", &nr) != 1) { - warnx("Can not parse file %s", filename); - } else { - rc = EXIT_SUCCESS; - if (nr == PERF_TYPE_RAW) - strcat(prefix, "r"); - else - snprintf(prefix, sizeof prefix, "%d:", nr); - } - fclose(fp); - return rc; + if (nr == PERF_TYPE_RAW) + strcat(prefix, "r"); + else + snprintf(prefix, sizeof(prefix), "%d:", nr); } /* Parse tool parameters. In case of --help or --version, print @@ -2661,8 +2643,6 @@ static unsigned long div_ceil(unsigned long a, unsigned long b) static void show_info(struct cpumf_info *p, int details) { - struct stat sbuf; - if (!p->have_counter && !p->have_samples) { warnx("No CPU-measurement facilities detected"); return; @@ -2672,7 +2652,7 @@ static void show_info(struct cpumf_info *p, int details) if (details) { printf("----------------------------------------------" "----------------------------\n"); - printf("Version: %3.1f\n\n", p->version); + printf("Version: %d.%d\n\n", p->first_vn, p->second_vn); printf("Authorized counter sets:\n"); if (!p->authorization) printf(" None\n"); @@ -2689,8 +2669,7 @@ static void show_info(struct cpumf_info *p, int details) if (0x8000 & p->authorization) printf(" Coprocessor Group counter Set\n"); printf("\nLinux perf event support: %s\n\n", - (stat(PERF_PATH PERF_CF, &sbuf)) ? "No" : - "Yes (PMU: " PERF_CF ")"); + !p->have_counter ? "No" : "Yes (PMU: cpum_cf)"); } } else @@ -2718,19 +2697,18 @@ static void show_info(struct cpumf_info *p, int details) p->diag_sample_sz); printf("\nLinux perf event support: %s\n\n", - (stat(PERF_PATH PERF_SF, &sbuf)) ? "No" : - "Yes (PMU: " PERF_SF ")"); + !p->have_samples ? "No" : "Yes (PMU: cpum_sf)"); - printf("Current sampling buffer settings for %s:\n", - PERF_SF); + printf("Current sampling buffer settings for" + " cpum_sf:\n"); printf(" Basic-sampling mode\n"); total = p->min_sfb + div_ceil(p->min_sfb, PER_SDBT_SIZE); - human(text, sizeof text, PAGE_SIZE * total); - printf(" Minimum: %6d" + human(text, sizeof(text), PAGE_SIZE * total); + printf(" Minimum: %6ld" " sample-data-blocks (%6s)\n", p->min_sfb, text); total = p->max_sfb + div_ceil(p->max_sfb, PER_SDBT_SIZE); - human(text, sizeof text, PAGE_SIZE * total); - printf(" Maximum: %6d" + human(text, sizeof(text), PAGE_SIZE * total); + printf(" Maximum: %6ld" " sample-data-blocks (%6s)\n\n", p->max_sfb, text); @@ -2739,13 +2717,13 @@ static void show_info(struct cpumf_info *p, int details) fdiag = div_ceil(p->diag_sample_sz, p->basic_sample_sz); total = fdiag * p->min_sfb + div_ceil(p->min_sfb, PER_SDBT_SIZE); - human(text, sizeof text, PAGE_SIZE * total); + human(text, sizeof(text), PAGE_SIZE * total); printf(" Minimum: %6ld" " sample-data-blocks (%6s)\n", fdiag * p->min_sfb, text); total = fdiag * p->max_sfb + div_ceil(p->max_sfb * fdiag, PER_SDBT_SIZE); - human(text, sizeof text, PAGE_SIZE * total); + human(text, sizeof(text), PAGE_SIZE * total); printf(" Maximum: %6ld" " sample-data-blocks (%6s)\n", fdiag * p->max_sfb, text); @@ -2755,27 +2733,6 @@ static void show_info(struct cpumf_info *p, int details) warnx("No CPU-measurement sampling facility detected"); } -/* Read CPU Measurement sampling facility device driver minimum and maximum - * buffer size - */ -static int read_sfb(struct cpumf_info *p) -{ - int rc = EXIT_SUCCESS; - FILE *fp; - - fp = fopen(PERF_SFB_SIZE, "r"); - if (!fp) { - warn(PERF_SFB_SIZE); - return EXIT_FAILURE; - } - if (fscanf(fp, "%d,%d", &p->min_sfb, &p->max_sfb) != 2) { - warnx("Can not parse %s", PERF_SFB_SIZE); - rc = EXIT_FAILURE; - } - fclose(fp); - return rc; -} - /* Set the counter name for z15 counter numbered 265. It is either named * DFLT_CCERROR or DFLT_CCFINISH, depending on the linux version. The * counter was renamed from CCERROR to CCFINISH in linux version 5.8. @@ -2803,81 +2760,23 @@ static void read_ccerror(struct counters *cp, size_t cp_cnt) /* Read allnecessary information from /sysfs file /proc/service_levels */ static int read_info(void) { - char *linep = NULL; - size_t line_sz; - ssize_t nbytes; - FILE *slp; - int rc; + int rc = EXIT_FAILURE; - memset(&cpumf, 0, sizeof cpumf); - slp = fopen(SERVICELEVEL, "r"); - if (!slp) { - warn(SERVICELEVEL); - return EXIT_FAILURE; - } - - while ((nbytes = getline(&linep, &line_sz, slp)) != EOF) { - if (!strncmp(linep, "CPU-MF: Counter facility:", 25)) { - rc = sscanf(linep, "CPU-MF: Counter facility:" - " version=%f authorization=%x", - &cpumf.version, &cpumf.authorization); - if (rc != 2) { - warnx("Can not parse line %s", linep); - rc = EXIT_FAILURE; - goto out; - } - cpumf.have_counter = 1; - cpumf.first_vn = (int)cpumf.version; - cpumf.second_vn = ((int)(10 * cpumf.version) % 10); - } - if (!strncmp(linep, "CPU-MF: Sampling facility: min", 30)) { - rc = sscanf(linep, "CPU-MF: Sampling facility:" - " min_rate=%ld max_rate=%ld cpu_speed=%ld", - &cpumf.min_rate, &cpumf.max_rate, - &cpumf.cpu_speed); - if (rc != 3) { - warnx("Can not parse line %s", linep); - rc = EXIT_FAILURE; - goto out; - } - cpumf.have_samples = 1; - } - if (!strncmp(linep, "CPU-MF: Sampling facility: mode=basic", 37)) { - rc = sscanf(linep, "CPU-MF: Sampling facility:" - " mode=basic sample_size=%u", - &cpumf.basic_sample_sz); - if (rc != 1) { - warnx("Can not parse line %s", linep); - rc = EXIT_FAILURE; - goto out; - } - } - if (!strncmp(linep, "CPU-MF: Sampling facility: mode=diag", 36)) { - rc = sscanf(linep, "CPU-MF: Sampling facility:" - " mode=diagnostic sample_size=%u", - &cpumf.diag_sample_sz); - if (rc != 1) { - warnx("Can not parse line %s", linep); - rc = EXIT_FAILURE; - goto out; - } - } - } - if (cpumf.have_samples) { - rc = read_sfb(&cpumf); - if (rc == EXIT_FAILURE) - goto out; - } + cpumf.have_counter = libcpumf_cpumcf_info(&cpumf.first_vn, + &cpumf.second_vn, + &cpumf.authorization); + cpumf.have_samples = libcpumf_cpumsf_info(&cpumf.min_rate, + &cpumf.max_rate, + &cpumf.cpu_speed, + &cpumf.basic_sample_sz, + &cpumf.diag_sample_sz); + if (cpumf.have_samples) + libcpumf_sfb_info(&cpumf.min_sfb, &cpumf.max_sfb); cpumf.machine_type = util_arch_machine_type(); - if (cpumf.machine_type == UTIL_ARCH_MACHINE_TYPE_UNKNOWN) { + if (cpumf.machine_type == UTIL_ARCH_MACHINE_TYPE_UNKNOWN) rc = EXIT_FAILURE; - goto out; - } - rc = EXIT_SUCCESS; -out: - fclose(slp); - free(linep); - + else + rc = EXIT_SUCCESS; return rc; } @@ -3051,14 +2950,18 @@ int main(int argc, char **argv) case ACTION_CNT: case ACTION_CNTALL: all = ret == ACTION_CNTALL; - ret = read_cpumf_type(CPUMF_CF_TYPE, "counter"); - if (ret == EXIT_SUCCESS) + ret = libcpumf_pmutype(S390_CPUMF_CF); + if (ret >= EXIT_SUCCESS) { + set_prefix(ret); show_counter(all); + } break; case ACTION_SAMPLE: - ret = read_cpumf_type(CPUMF_SF_TYPE, "sampling"); - if (ret == EXIT_SUCCESS) + ret = libcpumf_pmutype(S390_CPUMF_SF); + if (ret >= EXIT_SUCCESS) { + set_prefix(ret); show_sample(); + } break; case ACTION_NONE: case ACTION_INFO: