From a58460b5c780fd651e25e6e22eef5cda7f1ee1f4 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 28 Apr 2022 15:53:15 +0200 Subject: [PATCH] libcpumf: Function to return PMU name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return the PMU name as found in the sysfs tree given a PMU type number. Signed-off-by: Thomas Richter Reviewed-by: Jan Höppner Signed-off-by: Jan Höppner --- include/lib/libcpumf.h | 14 +++++++++++++ libcpumf/Makefile | 2 +- libcpumf/libcpumf_example.c | 9 +++++++++ libcpumf/libcpumf_pmutype.c | 39 +++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/lib/libcpumf.h b/include/lib/libcpumf.h index 299291f6..1f7468e2 100644 --- a/include/lib/libcpumf.h +++ b/include/lib/libcpumf.h @@ -30,6 +30,20 @@ */ int libcpumf_pmutype(const char *dirname); +/** + * Read out the PMU name from a given type. + * + * Return the PMU name this PMU was registered in kernel. If the PMU was + * registered without a name, it is not listed in the directory. + * The caller must free the memory returned by name. + * + * @param[in] wanted_type Type number of the PMU + * @param[out] name Name of the PMU (when retval is 0) + * @retval 0 PMU wanted_type detected and PMU name valid + * @retval -1 No PMU with wanted_type + */ +int libcpumf_pmuname(unsigned int wanted_type, char **name); + /** * Read out the CPU list from a given file name, for example from files * /sys/devices/system/cpu/online or /sys/devices/system/cpu/possible. diff --git a/libcpumf/Makefile b/libcpumf/Makefile index b7f27f48..929c3296 100644 --- a/libcpumf/Makefile +++ b/libcpumf/Makefile @@ -13,7 +13,7 @@ $(lib): $(objects) install: all -libcpumf_example: libcpumf_example.o $(lib) +libcpumf_example: libcpumf_example.o $(lib) $(rootdir)/libutil/libutil.a clean: rm -f *.o $(lib) $(examples) diff --git a/libcpumf/libcpumf_example.c b/libcpumf/libcpumf_example.c index dde13cad..57e17603 100644 --- a/libcpumf/libcpumf_example.c +++ b/libcpumf/libcpumf_example.c @@ -14,6 +14,7 @@ int main(void) { unsigned long min, max, speed, sfb_min, sfb_max; int rc, pmu, cfvn, csvn, auth; + char *pmuname; cpu_set_t set; pmu = libcpumf_pmutype(S390_CPUMF_CF); @@ -74,5 +75,13 @@ int main(void) putchar('\n'); printf("PAI crypto support %d\n", libcpumf_have_pai_crypto()); + + rc = libcpumf_pmuname(10, &pmuname); + if (rc) { + printf("PMU type 10 PMU name lookup error %d\n", rc); + } else { + printf("PMU type 10 PMU name %s\n", pmuname); + free(pmuname); + } return EXIT_SUCCESS; } diff --git a/libcpumf/libcpumf_pmutype.c b/libcpumf/libcpumf_pmutype.c index e89e3ebd..f301e74d 100644 --- a/libcpumf/libcpumf_pmutype.c +++ b/libcpumf/libcpumf_pmutype.c @@ -4,10 +4,16 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#include #include #include #include +#include +#include "lib/util_file.h" +#include "lib/util_libc.h" +#include "lib/util_path.h" +#include "lib/util_scandir.h" #include "lib/libcpumf.h" int libcpumf_pmutype(const char *dirname) @@ -31,3 +37,36 @@ int libcpumf_pmutype(const char *dirname) } return ret; } + +int libcpumf_pmuname(unsigned int wanted_type, char **name) +{ + struct dirent **de_vec; + unsigned int type; + char *dirname; + char *path; + int count; + int rc; + + path = util_path_sysfs("devices"); + count = util_scandir(&de_vec, alphasort, path, "(pai|cpum_).*"); + free(path); + + *name = NULL; + for (int i = 0; i < count; i++) { + if (de_vec[i]->d_type == DT_DIR) { + dirname = de_vec[i]->d_name; + path = util_path_sysfs("devices/%s/type", dirname); + rc = util_file_read_ui(&type, 10, path); + if (rc) + warn("Failed to open %s", path); + free(path); + if (!rc && type == wanted_type) { + *name = util_strdup(dirname); + goto out; + } + } + } +out: + util_scandir_free(de_vec, count); + return *name ? 0 : -1; +}