From 867313a94838a09f8bafc914759ba000e771f222 Mon Sep 17 00:00:00 2001 From: Thomas Gruber Date: Fri, 10 Nov 2023 01:12:52 +0100 Subject: [PATCH] Add new `sysfeatures` module as experimental (#581) * First iteration of new hwfeatures module, mainly for Intel systems * Finish Intel RAPL feature * Update hwfeatures with AMD RAPL * Limit string length in hwFeatures * Rename hwfeatures to sysfeatures as it contains more than just hardware features * Rename sysfeatures variables, move likwid_device types, exclude code when not configured, add meta info * Fix sysfeatures test and add make target * Delete empty sysFeature for transparent hugepages * Fix merge error --- Makefile | 8 + config.mk | 3 + src/access-daemon/Makefile | 6 +- src/access-daemon/accessDaemon.c | 1 + src/access-daemon/sysfsDaemon.c | 772 ++++++++++ src/applications/likwid-sysfeatures.lua | 471 ++++++ src/applications/likwid.lua | 24 +- src/hwFeatures.c | 212 --- src/includes/access_sysfs_client.h | 58 + src/includes/hwFeatures.h | 7 - src/includes/hwFeatures_common.h | 76 - src/includes/hwFeatures_types.h | 29 - src/includes/hwFeatures_x86_amd.h | 345 ----- src/includes/hwFeatures_x86_intel.h | 181 --- src/includes/likwid.h | 163 +- src/includes/likwid_device.h | 11 + src/includes/sysFeatures.h | 11 + src/includes/sysFeatures_amd.h | 365 +++++ src/includes/sysFeatures_amd_rapl.h | 63 + src/includes/sysFeatures_common.h | 12 + src/includes/sysFeatures_cpufreq.h | 79 + src/includes/sysFeatures_intel.h | 98 ++ src/includes/sysFeatures_intel_prefetcher.h | 115 ++ src/includes/sysFeatures_intel_rapl.h | 227 +++ src/includes/sysFeatures_intel_spec_ctrl.h | 62 + src/includes/sysFeatures_intel_turbo.h | 23 + src/includes/sysFeatures_intel_uncorefreq.h | 27 + .../sysFeatures_linux_numa_balancing.h | 35 + src/includes/sysFeatures_list.h | 20 + src/includes/sysFeatures_types.h | 46 + src/likwid_device.c | 139 ++ src/luawid.c | 298 ++-- src/meta.c | 9 + src/sysFeatures.c | 339 ++++ src/sysFeatures_amd_rapl.c | 1061 +++++++++++++ src/sysFeatures_common.c | 142 ++ src/sysFeatures_cpufreq.c | 259 ++++ src/sysFeatures_intel.c | 125 ++ src/sysFeatures_intel_prefetcher.c | 163 ++ src/sysFeatures_intel_rapl.c | 1360 +++++++++++++++++ src/sysFeatures_intel_spec_ctrl.c | 123 ++ src/sysFeatures_intel_uncorefreq.c | 147 ++ src/sysFeatures_linux_numa_balancing.c | 105 ++ src/sysFeatures_list.c | 272 ++++ test/Makefile | 9 + test/test_hwfeatures.c | 60 - test/test_sysFeatures.c | 96 ++ 47 files changed, 7217 insertions(+), 1040 deletions(-) create mode 100644 src/access-daemon/sysfsDaemon.c create mode 100644 src/applications/likwid-sysfeatures.lua delete mode 100644 src/hwFeatures.c create mode 100644 src/includes/access_sysfs_client.h delete mode 100644 src/includes/hwFeatures.h delete mode 100644 src/includes/hwFeatures_common.h delete mode 100644 src/includes/hwFeatures_types.h delete mode 100644 src/includes/hwFeatures_x86_amd.h delete mode 100644 src/includes/hwFeatures_x86_intel.h create mode 100644 src/includes/likwid_device.h create mode 100644 src/includes/sysFeatures.h create mode 100644 src/includes/sysFeatures_amd.h create mode 100644 src/includes/sysFeatures_amd_rapl.h create mode 100644 src/includes/sysFeatures_common.h create mode 100644 src/includes/sysFeatures_cpufreq.h create mode 100644 src/includes/sysFeatures_intel.h create mode 100644 src/includes/sysFeatures_intel_prefetcher.h create mode 100644 src/includes/sysFeatures_intel_rapl.h create mode 100644 src/includes/sysFeatures_intel_spec_ctrl.h create mode 100644 src/includes/sysFeatures_intel_turbo.h create mode 100644 src/includes/sysFeatures_intel_uncorefreq.h create mode 100644 src/includes/sysFeatures_linux_numa_balancing.h create mode 100644 src/includes/sysFeatures_list.h create mode 100644 src/includes/sysFeatures_types.h create mode 100644 src/likwid_device.c create mode 100644 src/sysFeatures.c create mode 100644 src/sysFeatures_amd_rapl.c create mode 100644 src/sysFeatures_common.c create mode 100644 src/sysFeatures_cpufreq.c create mode 100644 src/sysFeatures_intel.c create mode 100644 src/sysFeatures_intel_prefetcher.c create mode 100644 src/sysFeatures_intel_rapl.c create mode 100644 src/sysFeatures_intel_spec_ctrl.c create mode 100644 src/sysFeatures_intel_uncorefreq.c create mode 100644 src/sysFeatures_linux_numa_balancing.c create mode 100644 src/sysFeatures_list.c delete mode 100644 test/test_hwfeatures.c create mode 100644 test/test_sysFeatures.c diff --git a/Makefile b/Makefile index 47c6d8427..294c15565 100644 --- a/Makefile +++ b/Makefile @@ -176,6 +176,14 @@ L_HELPER = likwid.lua ifeq ($(BUILDFREQ),true) L_APPS += likwid-setFrequencies endif +ifeq ($(BUILD_SYSFEATURES),true) + L_APPS += likwid-sysfeatures + DEFINES += -DLIKWID_WITH_SYSFEATURES +else +SYSFEATURE_OBJ = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o,$(wildcard $(SRC_DIR)/sysFeatures*.c)) +OBJ := $(filter-out $(SYSFEATURE_OBJ), $(OBJ)) +OBJ := $(filter-out $(BUILD_DIR)/likwid_device.o,$(OBJ)) +endif CPPFLAGS := $(CPPFLAGS) $(DEFINES) $(INCLUDES) diff --git a/config.mk b/config.mk index dd3be85a9..682648687 100644 --- a/config.mk +++ b/config.mk @@ -34,6 +34,9 @@ NVIDIA_INTERFACE = false#NO SPACE # For configuring include paths, go to ROCm section ROCM_INTERFACE = false#NO SPACE +# Build experimental sysfeatures interface and Lua CLI application +BUILD_SYSFEATURES = false#NO SPACE + ################################################################# ################################################################# # Advanced configuration options # diff --git a/src/access-daemon/Makefile b/src/access-daemon/Makefile index ecd500c1a..f90bbc370 100644 --- a/src/access-daemon/Makefile +++ b/src/access-daemon/Makefile @@ -32,6 +32,7 @@ include ../../make/include_$(COMPILER).mk DAEMON_TARGET = likwid-accessD SETFREQ_TARGET = likwid-setFreq APPDAEMON_TARGET = likwid-appDaemon.so +SYSFSDAEMON_TARGET = ../../likwid-sysD GOTCHA_FOLDER = ../../ext/GOTCHA Q ?= @ @@ -65,4 +66,7 @@ $(SETFREQ_TARGET): setFreqDaemon.c $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -o ../../$(SETFREQ_TARGET) setFreqDaemon.c $(APPDAEMON_TARGET): $(GOTCHA_TARGET) appDaemon.c - $(Q)$(CC) -shared -fPIC $(CPPFLAGS) -Wl,-soname,$(APPDAEMON_TARGET).$(VERSION).$(RELEASE) -fstack-protector -I. ../bstrlib.c appDaemon.c -o ../../$(APPDAEMON_TARGET) -llikwid -L../../ + $(Q)$(CC) -shared -fPIC $(CPPFLAGS) -Wl,-soname,$(APPDAEMON_TARGET).$(VERSION).$(RELEASE) -fstack-protector -I. -I$(GOTCHA_FOLDER)/include -L$(GOTCHA_FOLDER) appDaemon.c -o ../../$(APPDAEMON_TARGET) -llikwid-gotcha + +$(SYSFSDAEMON_TARGET): sysfsDaemon.c + $(Q)$(CC) -g -fsanitize=address -fsanitize=leak -fomit-frame-pointer $(CFLAGS) $(CPPFLAGS) -o ../../sysfsD sysfsDaemon.c diff --git a/src/access-daemon/accessDaemon.c b/src/access-daemon/accessDaemon.c index d743b367e..26cb41cac 100644 --- a/src/access-daemon/accessDaemon.c +++ b/src/access-daemon/accessDaemon.c @@ -502,6 +502,7 @@ allowed_intel(uint32_t reg) ((reg & 0xF00U) == 0xD00U) || ((reg & 0xF00U) == 0xE00U) || ((reg & 0xF00U) == 0xF00U) || + (reg == 0x48) || (reg == 0x1A0) || (reg == 0x1A4) || (reg == 0x0CE) || diff --git a/src/access-daemon/sysfsDaemon.c b/src/access-daemon/sysfsDaemon.c new file mode 100644 index 000000000..8aa88e02b --- /dev/null +++ b/src/access-daemon/sysfsDaemon.c @@ -0,0 +1,772 @@ +/* + * ======================================================================================= + * + * Filename: sysfsDaemon.c + * + * Description: Implementation of access daemon for procfs and sysfs files. + * + * Version: + * Released: + * + * Authors: Michael Meier, michael.meier@rrze.fau.de + * Jan Treibig (jt), jan.treibig@gmail.com, + * Thomas Gruber (tr), thomas.roehl@googlemail.com + * Project: likwid + * + * Copyright (C) 2018 RRZE, University Erlangen-Nuremberg + * + * 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 3 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, see . + * + * ======================================================================================= + */ + +/* ##### HEADER FILE INCLUDES ######################################### */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +//#include +//#include + +/* ##### MACROS - LOCAL TO THIS SOURCE FILE ######################### */ + +#define SA struct sockaddr +#define str(x) #x + +#define CHECK_FILE_ERROR(func, msg) \ + if ((func) == 0) { syslog(LOG_ERR, "ERROR - [%s:%d] " str(msg) " - %s \n", __FILE__, __LINE__, strerror(errno)); } + +#define LOG_AND_EXIT_IF_ERROR(func, msg) \ + if ((func) < 0) { \ + syslog(LOG_ERR, "ERROR - [%s:%d] " str(msg) " - %s \n", __FILE__, __LINE__, strerror(errno)); \ + exit(EXIT_FAILURE); \ + } + +#define CHECK_ERROR(func, msg) \ + if ((func) < 0) { \ + fprintf(stderr, "ERROR - [%s:%d] " str(msg) " - %s \n", __FILE__, __LINE__, strerror(errno)); \ + } + +#define PCI_ROOT_PATH "/proc/bus/pci/" +#define CPUFREQ_DIR_FORMAT "/sys/devices/system/cpu/cpu%d/cpufreq" +#define PROCFS_SYS_KERNEL_DIR "/proc/sys/kernel" + +/* Lock file controlled from outside which prevents likwid to start. + * Can be used to synchronize access to the hardware counters + * with an external monitoring system. */ + +/* ##### TYPE DEFINITIONS ########### */ + +typedef enum { + SYSFSD_ACCESS_TYPE_ABS, + SYSFSD_ACCESS_TYPE_GLOB, +} SysfsDAccessType; + +typedef enum { + SYSFSD_ACCESS_PERM_RDONLY, + SYSFSD_ACCESS_PERM_RW, + SYSFSD_ACCESS_PERM_WRONLY, +} SysfsDAccessPermissions; + +typedef struct { + char* file; + SysfsDAccessType type; + SysfsDAccessPermissions perm; + LikwidDeviceType dev_type; +} SysfsDAccessFileDefinition; + +typedef struct { + char* dir; + LikwidDeviceType dev_type; + SysfsDAccessType type; + SysfsDAccessFileDefinition* files; + int num_files; + char* fnmatch; +} SysfsDAccessDirDefinition; + + +static SysfsDAccessFileDefinition valid_procfs_files[] = { + {"numa_balancing", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {NULL}, +}; + +static SysfsDAccessFileDefinition valid_cpufreq_files[] ={ + {"scaling_cur_freq", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"scaling_max_freq", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"scaling_min_freq", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"scaling_available_frequencies", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RDONLY}, + {"scaling_available_governors", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RDONLY}, + {"scaling_driver", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RDONLY}, + {"scaling_setspeed", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"scaling_governor", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"energy_performance_preference", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RW}, + {"energy_performance_available_preferences", SYSFSD_ACCESS_TYPE_ABS, SYSFSD_ACCESS_PERM_RDONLY}, + {NULL}, +}; + +static SysfsDAccessDirDefinition default_access_dirs[] = { + {"/proc/sys/kernel", DEVICE_TYPE_NODE, SYSFSD_ACCESS_TYPE_ABS, valid_procfs_files, 1}, + {"/sys/devices/system/cpu/cpu*/cpufreq", DEVICE_TYPE_HWTHREAD, SYSFSD_ACCESS_TYPE_GLOB, valid_cpufreq_files, 10}, + {NULL}, +}; + + + + + +/* ##### VARIABLES - LOCAL TO THIS SOURCE FILE ###################### */ + +static int sockfd = -1; +static int connfd = -1; /* temporary in to make it compile */ +static char* filepath; +static const char* ident = "sysfsD"; + +/*static OpenFiles *open_files = NULL;*/ +/*static int num_open_files = 0;*/ +static SysfsDAccessDirDefinition** access_dirs = NULL; +static int num_access_dirs = 0; + + +/* ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE ########### */ + +static int resolve_dir_glob(SysfsDAccessDirDefinition* format, int* num_out, char*** out) +{ + int err = 0; + int listlen = 0; + char** list = NULL; + + if ((!format) || (format->dev_type == DEVICE_TYPE_INVALID) || (!num_out) || (!out)) + { + return -EINVAL; + } + + glob_t globbuf; + globbuf.gl_pathc = 0; + globbuf.gl_offs = 0; + + err = glob(format->dir, GLOB_ONLYDIR, NULL, &globbuf); + switch (err) + { + case GLOB_NOSPACE: + return -ENOMEM; + break; + case GLOB_ABORTED: + return -EBADFD; + break; + case GLOB_NOMATCH: + *num_out = 0; + *out = NULL; + return 0; + break; + default: + break; + } + + list = malloc(globbuf.gl_pathc * sizeof(char*)); + if (!list) + { + globfree(&globbuf); + return -ENOMEM; + } + listlen = 0; + + for (int i = 0; i < globbuf.gl_pathc; i++) + { + list[i] = malloc((strlen(globbuf.gl_pathv[i])+2)* sizeof(char)); + if (!list[i]) + { + for (int j = 0; j < i; j++) + { + free(list[j]); + } + free(list); + globfree(&globbuf); + return -ENOMEM; + } + err = snprintf(list[i], strlen(globbuf.gl_pathv[i])+1, "%s", globbuf.gl_pathv[i]); + if (err > 0) + { + list[i][err] = '\0'; + } + listlen++; + } + globfree(&globbuf); + *num_out = listlen; + *out = list; + return 0; + +} + +static int init_access_dirs_from_file(char* configFile) +{ + return -ENOSYS; +} + + +static int _init_access_dirs_from_defaults_new(char* dir, SysfsDAccessDirDefinition* def, SysfsDAccessDirDefinition* out) +{ + + if ((!dir) || (!def) || (!out)) + { + return -EINVAL; + } + + out->dir = malloc((strlen(dir)+2) * sizeof(char)); + if (!out->dir) + { + return -ENOMEM; + } + int ret = snprintf(out->dir, strlen(dir)+1, "%s", dir); + if (ret < 0) + { + return ret; + } + out->dir[ret] = '\0'; + out->type = SYSFSD_ACCESS_TYPE_ABS; + out->dev_type = def->dev_type; + + return 0; +} + +static int _init_access_dirs_from_defaults_register(SysfsDAccessDirDefinition* def, int *index) +{ + if ((!def) || (!index) || (!def->dir)) + { + return -EINVAL; + } + + SysfsDAccessDirDefinition** tmp = realloc(access_dirs, (num_access_dirs+1)* sizeof(SysfsDAccessDirDefinition*)); + if (!tmp) + { + return -ENOMEM; + } + access_dirs = tmp; + int idx = num_access_dirs; + access_dirs[num_access_dirs++] = def; + *index = idx; + return 0; +} + +static int _init_access_dirs_from_defaults_files(SysfsDAccessDirDefinition* def, SysfsDAccessDirDefinition* out) +{ + int i = 0; + int num_files = 0; + int outidx = 0; + + while (def->files[i].file != NULL) + { + num_files++; + i++; + } + + out->files = malloc((num_files + 1) * sizeof(SysfsDAccessFileDefinition)); + if (!out->files) + { + return -ENOMEM; + } + + for (i = 0; i < num_files; i++) + { + char fname[1025]; + int ret = snprintf(fname, 1024, "%s/%s", out->dir, def->files[i].file); + if (ret < 0) + { + for (int j = 0; j < i-1; j++) + { + free(out->files[j].file); + } + free(out->files); + return -ENOMEM; + } + if (!access(fname, F_OK)) + { + out->files[i].file = malloc((strlen(def->files[i].file) + 2) * sizeof(char)); + if (!out->files[i].file) + { + for (int j = 0; j < i-1; j++) + { + free(out->files[j].file); + } + free(out->files); + return -ENOMEM; + } + ret = snprintf(out->files[i].file, strlen(def->files[i].file) + 1, "%s", def->files[i].file); + if (ret < 0) + { + free(out->files[i].file); + for (int j = 0; j < i-1; j++) + { + free(out->files[j].file); + } + free(out->files); + return -ENOMEM; + } + out->files[i].file[ret] = '\0'; + out->files[i+1].file = NULL; + } + } + out->num_files = num_files; + return 0; +} + +static int init_access_dirs_from_defaults() +{ + int i = 0, j = 0, idx = 0; + int err = 0; + int num_dirs = 0; + char** dirs = NULL; + i = 0; + while (default_access_dirs[i].dir != NULL) + { + SysfsDAccessDirDefinition* def; + switch (default_access_dirs[i].type) + { + case SYSFSD_ACCESS_TYPE_ABS: + def = malloc(sizeof(SysfsDAccessDirDefinition)); + if (!def) + { + return -ENOMEM; + } + err = _init_access_dirs_from_defaults_new(default_access_dirs[i].dir, &default_access_dirs[i], def); + if (err < 0) + { + free(def); + return err; + } + err = _init_access_dirs_from_defaults_files(&default_access_dirs[i], def); + if (err < 0) + { + free(def); + return err; + } + err = _init_access_dirs_from_defaults_register(def, &idx); + if (err < 0) + { + j = 0; + while (def->files[j].file != NULL) + { + free(def->files[j].file); + j++; + } + free(def); + return err; + } + break; + case SYSFSD_ACCESS_TYPE_GLOB: + err = resolve_dir_glob(&default_access_dirs[i], &num_dirs, &dirs); + if (err < 0) + { + return err; + } + for (j = 0; j < num_dirs; j++) + { + def = malloc(sizeof(SysfsDAccessDirDefinition)); + if (!def) + { + return -ENOMEM; + } + err = _init_access_dirs_from_defaults_new(dirs[j], &default_access_dirs[i], def); + if (err < 0) + { + free(def); + return err; + } + err = _init_access_dirs_from_defaults_files(&default_access_dirs[i], def); + if (err < 0) + { + free(def); + return err; + } + err = _init_access_dirs_from_defaults_register(def, &idx); + if (err < 0) + { + j = 0; + while (def->files[j].file != NULL) + { + free(def->files[j].file); + j++; + } + free(def); + return err; + } + } + if (dirs) + { + for (j = 0; j < num_dirs; j++) + { + free(dirs[j]); + } + free(dirs); + dirs = NULL; + num_dirs = 0; + } + } + i++; + } + return 0; +} + +static int init_access_dirs(char* configFile) +{ + return (configFile == NULL ? init_access_dirs_from_defaults() : init_access_dirs_from_file(configFile)); +} + +static void cleanup_access_dirs() +{ + if (access_dirs) + { + for (int i = 0; i < num_access_dirs; i++) + { + SysfsDAccessDirDefinition* dir = access_dirs[i]; + for (int j = 0; j < dir->num_files; j++) + { + free(dir->files[j].file); + } + free(dir->files); + free(dir->dir); + free(dir); + } + free(access_dirs); + access_dirs = NULL; + num_access_dirs = 0; + } +} + + +static int check_file_access(char* filename) +{ + for (int i = 0; i < num_access_dirs; i++) + { + SysfsDAccessDirDefinition* dir = access_dirs[i]; + if (strncmp(filename, dir->dir, strlen(dir->dir)) == 0) + { + for (int j = 0; j < dir->num_files; j++) + { + if (strncmp(&filename[strlen(dir->dir)+1], dir->files[j].file, strlen(dir->files[j].file)) == 0) + { + return 1; + } + } + } + } + return 0; +} + +static int read_sysfs_file(char* filename, int max_len, char* data) +{ + int err = check_file_access(filename); + if (!err) + { + return -ENOENT; + } + FILE* fp = fopen(filename, "r"); + if (fp) + { + int ret = fread(data, sizeof(char), max_len, fp); + if (ret >= 0) + { + data[ret] = '\0'; + } + for (int k = ret-1; k >= 0; k--) + { + if (data[k] == '\n') + { + data[k] = '\0'; + break; + } + } + fclose(fp); + } + return -0; +} + +static int write_sysfs_file(char* filename, int max_len, char* data) +{ + int err = check_file_access(filename); + if (!err) + { + return -ENOENT; + } + FILE* fp = fopen(filename, "w"); + if (fp) + { + fwrite(data, sizeof(char), max_len, fp); + fclose(fp); + } + return -0; +} + + + +/*int main(int argc, char* argv[])*/ +/*{*/ +/* char data[1025];*/ +/* char fname[] = "/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq";*/ +/* int err = init_access_dirs(NULL);*/ +/* if (err < 0)*/ +/* {*/ +/* return err;*/ +/* }*/ +/* */ +/* err = read_sysfs_file(fname, 1024, data);*/ +/* if (err < 0)*/ +/* {*/ +/* return err;*/ +/* }*/ +/* printf("Data '%s'\n", data);*/ +/* cleanup_access_dirs();*/ +/* return 0;*/ +/*}*/ + +static void +kill_client(void) +{ + if (connfd != -1) + { + CHECK_ERROR(close(connfd), socket close failed); + } + + connfd = -1; +} + +static void +stop_daemon(void) +{ + kill_client(); + + cleanup_access_dirs(); + + closelog(); + exit(EXIT_SUCCESS); +} + + + +static void +Signal_Handler(int sig) +{ + if (sig == SIGPIPE) + { + syslog(LOG_NOTICE, "SIGPIPE? client crashed?!"); + stop_daemon(); + } + + /* For SIGALRM we just return - we're just here to create a EINTR */ + if (sig == SIGTERM) + { + stop_daemon(); + } +} + +static void +daemonize(int* parentPid) +{ + pid_t pid, sid; + + *parentPid = getpid(); + + /* already a daemon */ + if ( getppid() == 1 ) return; + + /* Fork off the parent process */ + pid = fork(); + + if (pid < 0) + { + syslog(LOG_ERR, "fork failed: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* If we got a good PID, then we can exit the parent process. */ + if (pid > 0) + { + exit(EXIT_SUCCESS); + } + + /* At this point we are executing as the child process */ + + /* Create a new SID for the child process */ + sid = setsid(); + + if (sid < 0) + { + syslog(LOG_ERR, "setsid failed: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Change the current working directory. This prevents the current + directory from being locked; hence not being able to remove it. */ + if ((chdir("/")) < 0) + { + syslog(LOG_ERR, "chdir failed: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Redirect standard files to /dev/null */ + { + CHECK_FILE_ERROR(freopen( "/dev/null", "r", stdin), freopen stdin failed); + CHECK_FILE_ERROR(freopen( "/dev/null", "w", stdout), freopen stdout failed); + CHECK_FILE_ERROR(freopen( "/dev/null", "w", stderr), freopen stderr failed); + } +} + +int main(void) +{ + int ret; + pid_t pid; + SysfsDataRecord dRecord; + struct sockaddr_un addr1; + socklen_t socklen; + mode_t oldumask; + + openlog(ident, 0, LOG_USER); + + if (!lock_check()) + { + syslog(LOG_ERR,"Access to performance counters is locked.\n"); + stop_daemon(); + } + + int err = init_access_dirs(NULL); + if (err < 0) + { + stop_daemon(); + } + + daemonize(&pid); +#ifdef DEBUG_LIKWID + syslog(LOG_INFO, "SysfsDaemon runs with UID %d, eUID %d\n", getuid(), geteuid()); +#endif + + + /* setup filename for socket */ + filepath = (char*) calloc(sizeof(addr1.sun_path), 1); + snprintf(filepath, sizeof(addr1.sun_path), TOSTRING(LIKWIDSOCKETBASE) "-sysfs-%d", pid); + + /* get a socket */ + LOG_AND_EXIT_IF_ERROR(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0), socket failed); + + /* initialize socket data structure */ + bzero(&addr1, sizeof(addr1)); + addr1.sun_family = AF_LOCAL; + strncpy(addr1.sun_path, filepath, (sizeof(addr1.sun_path) - 1)); /* null terminated by the bzero() above! */ + + /* Change the file mode mask so only the calling user has access + * and switch the user/gid with which the following socket creation runs. */ + oldumask = umask(077); + CHECK_ERROR(setfsuid(getuid()), setfsuid failed); + + /* bind and listen on socket */ + LOG_AND_EXIT_IF_ERROR(bind(sockfd, (SA*) &addr1, sizeof(addr1)), bind failed); + LOG_AND_EXIT_IF_ERROR(listen(sockfd, 1), listen failed); + LOG_AND_EXIT_IF_ERROR(chmod(filepath, S_IRUSR|S_IWUSR), chmod failed); + + socklen = sizeof(addr1); + + { /* Init signal handler */ + struct sigaction sia; + sia.sa_handler = Signal_Handler; + sigemptyset(&sia.sa_mask); + sia.sa_flags = 0; + sigaction(SIGALRM, &sia, NULL); + sigaction(SIGPIPE, &sia, NULL); + sigaction(SIGTERM, &sia, NULL); + } + + /* setup an alarm to stop the daemon if there is no connect.*/ + alarm(15U); + + if ((connfd = accept(sockfd, (SA*) &addr1, &socklen)) < 0) + { + if (errno == EINTR) + { + syslog(LOG_ERR, "exiting due to timeout - no client connected after 15 seconds."); + } + else + { + syslog(LOG_ERR, "accept() failed: %s", strerror(errno)); + } + CHECK_ERROR(unlink(filepath), unlink of socket failed); + exit(EXIT_FAILURE); + } + + alarm(0); + CHECK_ERROR(unlink(filepath), unlink of socket failed); + + /* Restore the old umask and fs ids. */ + (void) umask(oldumask); + CHECK_ERROR(setfsuid(geteuid()), setfsuid failed); + + +LOOP: + //syslog(LOG_ERR, "Starting loop %d\n", avail_cpus); + while (1) + { + ret = read(connfd, (void*) &dRecord, sizeof(SysfsDataRecord)); + + if (ret < 0) + { + syslog(LOG_ERR, "ERROR - Read returns %d", ret); + stop_daemon(); + } + else if ((ret == 0) && (dRecord.type != SYSFS_EXIT)) + { + syslog(LOG_ERR, "ERROR - [%s:%d] zero read, remote socket closed before reading", __FILE__, __LINE__); + stop_daemon(); + } + + if (dRecord.type == SYSFS_READ) + { + read_sysfs_file(dRecord.filename, dRecord.datalen, (char*)&dRecord.data); + } + else if (dRecord.type == SYSFS_WRITE) + { + write_sysfs_file(dRecord.filename, dRecord.datalen, dRecord.data); + } + else if (dRecord.type == SYSFS_EXIT) + { + stop_daemon(); + } + else + { + syslog(LOG_ERR, "unknown daemon command type %d", dRecord.type); + dRecord.errorcode = SYSFS_ERR_UNKNOWN; + } + + LOG_AND_EXIT_IF_ERROR(write(connfd, (void*) &dRecord, sizeof(SysfsDataRecord)), write failed); + } + + /* never reached */ + return EXIT_SUCCESS; +} diff --git a/src/applications/likwid-sysfeatures.lua b/src/applications/likwid-sysfeatures.lua new file mode 100644 index 000000000..b527d2319 --- /dev/null +++ b/src/applications/likwid-sysfeatures.lua @@ -0,0 +1,471 @@ +#!/likwid-lua +--[[ + * ======================================================================================= + * + * Filename: likwid-features.lua + * + * Description: A application to retrieve and manipulate CPU features. + * + * Version: 4.0 + * Released: 28.04.2015 + * + * Author: Thomas Gruber (tr), thomas.roehl@gmail.com + * Project: likwid + * + * Copyright (C) 2016 RRZE, University Erlangen-Nuremberg + * + * 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 3 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, see . + * + * ======================================================================================= +]] +package.path = '/share/lua/?.lua;' .. package.path + +local likwid = require("likwid") + + +print_stdout = print +print_stderr = function(...) for k,v in pairs({...}) do io.stderr:write(v .. "\n") end end + + +function version() + print_stdout(string.format("likwid-features -- Version %d.%d.%d (commit: %s)",likwid.version,likwid.release,likwid.minor,likwid.commit)) +end + +function example() + print_stdout("Options:") +end + +function usage() + version() + print_stdout("A tool list and modify the states of CPU features.\n") + print_stdout("Options:") + print_stdout("-h, --help\t\t Help message") + print_stdout("-v, --version\t\t Version information") + print_stdout("-a, --all\t\t List all available features") + print_stdout("-l, --list\t\t List features and state for given hardware threads") + print_stdout("-c, --cpus \t Perform operations on given hardware threads") + print_stdout("-g, --get \t Get the value of the given feature(s)") + print_stdout(" \t feature format: . or just if unique") + print_stdout(" \t can be a list of features") + print_stdout("-s, --set \t Set feature(s) to the given value") + print_stdout(" \t format: .= or just = if unique") + print_stdout(" \t can be a list of modifications") + print_stdout("-O\t\t\t Output results in CSV") + print_stdout("-V, --verbose \t Set verbosity\n") +end + +if #arg == 0 then + usage() + os.exit(0) +end + +-- main variables with defaults +local listFeatures = false +local allFeatures = false +local num_hwts = 0 +local hwtlist = {} +local getList = {} +local setList = {} +local cpuinfo = likwid.getCpuInfo() +local cputopo = likwid.getCpuTopology() +local affinity = likwid.getAffinityInfo() +local verbose = 0 +local output_csv = false + +-- parse the command line +for opt,arg in likwid.getopt(arg, {"h","v","l","c:","g:","s:","a", "O","help","version","list", "set:", "get:","all", "cpus:", "V:", "verbose:"}) do + if (type(arg) == "string") then + local s,e = arg:find("-"); + if s == 1 then + print_stderr(string.format("Argument %s to option -%s starts with invalid character -.", arg, opt)) + print_stderr("Did you forget an argument to an option?") + os.exit(1) + end + end + if opt == "h" or opt == "help" then + usage() + os.exit(0) + elseif opt == "v" or opt == "version" then + version() + os.exit(0) + elseif opt == "c" or opt == "cpus"then + num_hwts, hwtlist = likwid.cpustr_to_cpulist(arg) + elseif opt == "l" or opt == "list" then + listFeatures = true + elseif opt == "O" then + output_csv = true + elseif opt == "V" or opt == "verbose" then + verbose = tonumber(arg) + elseif opt == "a" or opt == "all" then + allFeatures = true + elseif opt == "g" or opt == "get" then + getList = likwid.stringsplit(arg, ",") + elseif opt == "s" or opt == "set" then + setList = likwid.stringsplit(arg, ",") + elseif opt == "?" then + print_stderr("Invalid commandline option -"..arg) + os.exit(1) + elseif opt == "!" then + print_stderr("Option requires an argument") + os.exit(1) + end +end + + +-- validate command line input +if (not listFeatures) and (not allFeatures) and (#getList == 0) and (#setList == 0) then + print_stderr("No operations specified, exiting...") + os.exit(1) +end +if (listFeatures or allFeatures) and (#getList > 0 or #setList > 0) then + print_stderr("Cannot list features and get/set at the same time") + os.exit(1) +end +if #hwtlist == 0 then + if listFeatures then + print_stderr("HWThread selection (-c) required for listing the state of all features") + os.exit(1) + elseif #getList > 0 then + print_stderr("HWThread selection (-c) required for getting the state of given features") + os.exit(1) + elseif #setList > 0 then + print_stderr("HWThread selection (-c) required for setting the state of given features") + os.exit(1) + end +end + +--[[local access_mode = likwid.getAccessClientMode() +if access_mode < 0 or access_mode > 1 then + print_stderr("Manipulation of HW features only for access mode 'direct' or 'accessdaemon'") + os.exit(1) +end]] + +-- set verbosity +if verbose > 0 and verbose <= 3 then + likwid.setVerbosity(verbose) +end + +-- initialize the sysfeatures module +local err = likwid.initSysFeatures() +if err < 0 then + print_stderr("Cannot initialize HW features module") + os.exit(1) +end + +-- get a list of all features for the system +local list = likwid.sysFeatures_list() + +-- print the list +if allFeatures then + local all = {} + local names = {} + local types = {} + local access = {} + local descs = {} + local cats = {} + -- create a table of categories for sorting + for _,f in pairs(list) do + found = false + for _, c in pairs(cats) do + if c == f.Category then + found = true + end + end + if not found then + table.insert(cats, f.Category) + end + end + table.sort(cats) + + -- prepare table for output + -- first we create tables for the four columns + table.insert(names, "Feature") + table.insert(types, "Scope") + table.insert(access, "Access") + table.insert(descs, "Description") + for _,c in pairs(cats) do + for _,f in pairs(list) do + if f.Category == c then + table.insert(names, string.format("%s.%s", f.Category, f.Name)) + table.insert(types, f.Type) + table.insert(descs, f.Description) + if f.ReadOnly then + table.insert(access, "rdonly") + elseif f.WriteOnly then + table.insert(access, "wronly") + else + table.insert(access, "rw") + end + end + end + end + -- add all columns to the table + setmetatable(names, {align = "left"}) + table.insert(all, names) + table.insert(all, types) + table.insert(all, access) + setmetatable(descs, {align = "left"}) + table.insert(all, descs) + + -- print the table in selected format + if output_csv then + likwid.printcsv(all, #all) + else + print_stdout("Available features:") + likwid.printtable(all) + end + + -- finalize sysfeatures module and exit + likwid.finalizeSysFeatures() + os.exit(0) +end + + +-- sysfeatures requires exact specification of devices +-- some exist per hw thread others only for the whole node +-- or the socket +-- this creates all devices based on the given hw threads +local deviceTree = {} + +-- there is only a single entry for the whole node +-- the first entry in the list of hw threads is responsible +deviceTree[likwid.node] = {} +table.insert(deviceTree[likwid.node], {device = likwid.createDevice(likwid.node, hwtlist[1]), id = hwtlist[1]}) +-- create the devices for all hw threads in the list +deviceTree[likwid.hwthread] = {} +for i, c in pairs(hwtlist) do + table.insert(deviceTree[likwid.hwthread], {device = likwid.createDevice(likwid.hwthread, c), id = c}) +end +-- create the devices for all sockets which are covered by the list of given hw threads +deviceTree[likwid.socket] = {} +for sid=0, cputopo.numSockets do + local sdone = false + for _, c in pairs(hwtlist) do + for _, t in pairs(cputopo.threadPool) do + if t.apicId == c and t.packageId == sid then + table.insert(deviceTree[likwid.socket], {device = likwid.createDevice(likwid.socket, sid), id = c}) + sdone = true + break + end + end + if sdone then + break + end + end +end + +local function getDevice(level, id) + if deviceTree[level] then + for _, entry in pairs(deviceTree[level]) do + if entry.id == id then + return entry.device + end + end + end + return nil +end + +--[[deviceTree[likwid.core] = {} +for cid=0, tonumber(cputopo.numCores) do + for _, c in pairs(hwtlist) do + for _, t in pairs(cputopo.threadPool) do + if t.apicId == c and t.coreId == cid then + table.insert(deviceTree[likwid.core], {device = likwid.createDevice(likwid.core, cid), id = c}) + end + end + end +end]] + + +if listFeatures and #hwtlist > 0 then + -- prepare output table + local all = {} + -- first column contains the feature category and name + local first = {} + table.insert(first, "Feature/HWT") + for _,f in pairs(list) do + table.insert(first, string.format("%s.%s", f.Category, f.Name)) + end + setmetatable(first, {align = "left"}) + table.insert(all, first) + -- create one column per given hw thread with the current value of the feature + for i, c in pairs(hwtlist) do + local tab = {} + table.insert(tab, string.format("HWThread %d", c)) + for _,f in pairs(list) do + local dev = getDevice(f.TypeID, c) + if dev then + local v = likwid.sysFeatures_get(f.Name, dev) + if v == nil then + if f.ReadOnly then + table.insert(tab, "rdonly") + elseif f.WriteOnly then + table.insert(tab, "wronly") + else + table.insert(tab, "fail") + end + else + table.insert(tab, v) + end + else + table.insert(tab, "-") + end + end + -- add the hw thread column to the table + table.insert(all, tab) + end + + -- print the table + if output_csv then + likwid.printcsv(all, num_hwts + 1) + else + likwid.printtable(all) + end + -- cleanup device tree before exiting + print_stdout("Cleanup tree") + for l, ltab in pairs(deviceTree) do + for _, e in pairs(ltab) do + likwid.destroyDevice(e.device) + end + end + -- finalize sysfeatures module and exit + likwid.finalizeSysFeatures() + os.exit(0) +end + +if #setList > 0 and #hwtlist > 0 then + -- filter the full feature list to have only the selected ones + -- the new list entry contains all entries of the original feature entry plus + -- the user-given value + local featList = {} + for _, f in pairs(setList) do + local t = likwid.stringsplit(f, "=") + if #t == 2 then + for _, l in pairs(list) do + if t[1] == l.Name or t[1] == string.format("%s.%s", l.Category, l.Name) then + table.insert(featList, { + TypeID = l.TypeID, + Type = l.Type, + Name = l.Name, + Category = l.Category, + ReadOnly = l.ReadOnly, + WriteOnly = l.WriteOnly, + Value = t[2] + }) + end + end + else + print_stderr(string.format("Invalid format of '%s' in set list", f)) + end + end + + -- set all features in the new list + for i, c in pairs(hwtlist) do + local tab = {} + for _,f in pairs(featList) do + -- get device from the device tree + local dev = getDevice(f.TypeID, c) + if dev then + if verbose > 0 then + print_stdout(string.format("Setting '%s.%s' to '%s' (Type %s, Resp %d)", f.Category, f.Name, f.Value, f.Type, c)) + end + local v = likwid.sysFeatures_set(f.Name, dev, f.Value) + if not v then + print_stderr(string.format("Failed to set feature '%s.%s' to '%s' (Type %s, Resp %d)", f.Category, f.Name, f.Value, f.Type, c)) + end + end + end + end + -- cleanup device tree before exiting + for l, ltab in pairs(deviceTree) do + for _, e in pairs(ltab) do + likwid.destroyDevice(e.device) + end + end + -- finalize sysfeatures module and exit + likwid.finalizeSysFeatures() + os.exit(0) +end + + +--[[if (not (listFeatures or allFeatures)) or #enableList > 0 or #disableList > 0 then + -- Check whether there are similar entries in enable and distable list and remove them (first add to skip list, then remove from tables) + if #enableList > 0 and #disableList > 0 then + local skipList = {} + for i,e in pairs(enableList) do + for j, d in pairs(disableList) do + if (e == d) then + print_stderr(string.format("Feature %s is in enable and disable list, doing nothing for feature", e)) + table.insert(skipList, e) + end + end + end + for i, s in pairs(skipList) do + for j, e in pairs(enableList) do + if (s == e) then table.remove(enableList, j) end + end + for j, e in pairs(disableList) do + if (s == e) then table.remove(disableList, j) end + end + end + end + + -- Filter enable and disable lists to contain only valid and writable features + local realEnableList = {} + local realDisableList = {} + for _, f in pairs(list) do + for _, e in pairs(enableList) do + if f.Name == e and not f.ReadOnly then + table.insert(realEnableList, f.Name) + end + end + for _, e in pairs(disableList) do + if f.Name == e and not f.ReadOnly then + table.insert(realDisableList, f.Name) + end + end + end + + -- First enable all features for all selected hardware threads + if #realEnableList > 0 then + for i, c in pairs(hwtlist) do + local dev = likwid.createDevice(likwid.hwthread, c) + for j, f in pairs(realEnableList) do + local ret = likwid.sysFeatures_set(f, dev, 1) + if ret == true then + print_stdout(string.format("Enabled %s for HWThread %d", f, c)) + else + print_stdout(string.format("Failed %s for HWThread %d", f, c)) + end + end + likwid.destroyDevice(dev) + end + end + -- Next disable all features for all selected hardware threads + if #realDisableList > 0 then + for i, c in pairs(hwtlist) do + local dev = likwid.createDevice(likwid.hwthread, c) + for j, f in pairs(realDisableList) do + local ret = likwid.sysFeatures_set(f, dev, 0) + if ret == true then + print_stdout(string.format("Disabled %s for HWThread %d", f, c)) + else + print_stdout(string.format("Failed %s for HWThread %d", f, c)) + end + end + likwid.destroyDevice(dev) + end + end +end]] +likwid.finalizeSysFeatures() +os.exit(0) diff --git a/src/applications/likwid.lua b/src/applications/likwid.lua index 559e17615..c525a0f1d 100644 --- a/src/applications/likwid.lua +++ b/src/applications/likwid.lua @@ -179,11 +179,14 @@ likwid.seteuid = likwid_seteuid likwid.setresuid = likwid_setresuid likwid.setresuser = likwid_setresuser -likwid.initHWFeatures = likwid_initHWFeatures -likwid.hwFeatures_list = likwid_hwFeatures_list -likwid.hwFeatures_get = likwid_hwFeatures_get -likwid.hwFeatures_set = likwid_hwFeatures_set -likwid.finalizeHWFeatures = likwid_finalizeHWFeatures +likwid.initSysFeatures = likwid_initSysFeatures +likwid.sysFeatures_list = likwid_sysFeatures_list +likwid.sysFeatures_get = likwid_sysFeatures_get +likwid.sysFeatures_set = likwid_sysFeatures_set +likwid.finalizeSysFeatures = likwid_finalizeSysFeatures + +likwid.createDevice = likwid_createDevice +likwid.destroyDevice = likwid_destroyDevice likwid.getCudaTopology = likwid_getCudaTopology likwid.putCudaTopology = likwid_putCudaTopology @@ -256,6 +259,17 @@ likwid.signals = { [1] = "SIGHUP", [2] = "SIGINT", [3] = "SIGQUIT", [4] = "SIGIL infinity = math.huge +likwid.invalid = 0 +likwid.hwthread = likwid.invalid + 1 +likwid.core = likwid.hwthread + 1 +likwid.llc = likwid.core + 1 +likwid.numa = likwid.llc + 1 +likwid.die = likwid.numa + 1 +likwid.socket = likwid.die + 1 +likwid.node = likwid.socket + 1 +likwid.nvidia_gpu = likwid.node + 1 +likwid.amd_gpu = likwid.nvidia_gpu + 1 +likwid.intel_gpu = likwid.amd_gpu + 1 local function getopt(args, ostrlist) local arg, place,placeend = nil, 0, 0; diff --git a/src/hwFeatures.c b/src/hwFeatures.c deleted file mode 100644 index 6aea98a35..000000000 --- a/src/hwFeatures.c +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -_HWFeature *local_features = NULL; -int num_local_features = 0; - -int hwFeatures_init() -{ - int err = 0; - int num_features = 0; - _HWFeature *features = NULL; - topology_init(); - CpuInfo_t cpuinfo = get_cpuInfo(); - if (cpuinfo->isIntel) - { - err = hwFeatures_init_x86_intel(&num_features, &features); - } - else - { - err = hwFeatures_init_x86_amd(&num_features, &features); - } - if (err < 0) - { - return err; - } - - err = HPMinit(); - if (err < 0) - { - return err; - } - num_local_features = num_features; - local_features = features; - return 0; -} - -static int _hwFeatures_get_feature_index(char* name) -{ - for (int i = 0; i < num_local_features; i++) - { - if (strncmp(name, local_features[i].name, strlen(local_features[i].name)) == 0) - { - return i; - } - } - return -1; -} - - - -int hwFeatures_getByName(char* name, int hwthread, uint64_t* value) -{ - int err = 0; - _HWFeature *f = NULL; - if ((!name) || (hwthread < 0) || (!value)) - { - return -EINVAL; - } - - int idx = _hwFeatures_get_feature_index(name); - if (idx < 0) - { - return -EINVAL; - } - f = &local_features[idx]; - if ((!f) || (!f->getter)) - { - return -EINVAL; - } - err = HPMaddThread(hwthread); - if (err < 0) - { - return err; - } - uint64_t v = 0; - err = f->getter(hwthread, &v); - if (err == 0) - { - *value = v; - } - return err; -} - -int hwFeatures_get(HWFeature* feature, int hwthread, uint64_t* value) -{ - return hwFeatures_getByName(feature->name, hwthread, value); -} - -int hwFeatures_modifyByName(char* name, int hwthread, uint64_t value) -{ - _HWFeature *f = NULL; - if ((!name) || (hwthread < 0)) - { - return -EINVAL; - } - int idx = _hwFeatures_get_feature_index(name); - if (idx < 0) - { - return -EINVAL; - } - f = &local_features[idx]; - if ((!f) || (!f->setter)) - { - return -EINVAL; - } - int err = HPMaddThread(hwthread); - if (err < 0) - { - return err; - } - return f->setter(hwthread, value); -} - -int hwFeatures_modify(HWFeature* feature, int hwthread, uint64_t value) -{ - return hwFeatures_modifyByName(feature->name, hwthread, value); -} - -void hwFeatures_finalize() -{ - if (local_features != NULL) - { - free(local_features); - local_features = NULL; - num_local_features = 0; - } -} - -int hwFeatures_list(HWFeatureList* list) -{ - if (!list) - { - return -EINVAL; - } - HWFeature* features = malloc(num_local_features * sizeof(HWFeature)); - if (!features) - { - return -ENOMEM; - } - memset(features, 0, num_local_features * sizeof(HWFeature)); - - for (int i = 0; i < num_local_features; i++) - { - features[i].name = malloc((strlen(local_features[i].name)+1) * sizeof(char)); - if (features[i].name) - { - features[i].description = malloc((strlen(local_features[i].description)+1) * sizeof(char)); - if (!features[i].description) - { - free(features[i].name); - for (int j = 0; j < i; j++) - { - if (features[j].name) free(features[j].name); - if (features[j].description) free(features[j].description); - } - } - } - else - { - for (int j = 0; j < i; j++) - { - if (features[j].name) free(features[j].name); - if (features[j].description) free(features[j].description); - } - } - } - for (int i = 0; i < num_local_features; i++) - { - strcpy(features[i].name, local_features[i].name); - strcpy(features[i].description, local_features[i].description); - features[i].scope = local_features[i].scope; - features[i].readonly = 0; - if (local_features[i].getter != NULL && local_features[i].setter == NULL) - { - features[i].readonly = 1; - } - if (local_features[i].getter == NULL && local_features[i].setter != NULL) - { - features[i].writeonly = 1; - } - } - list->num_features = num_local_features; - list->features = features; - return 0; -} - -void hwFeatures_list_return(HWFeatureList* list) -{ - if (!list || !list->features) - { - return; - } - for (int i = 0; i < list->num_features; i++) - { - free(list->features[i].name); - free(list->features[i].description); - } - free(list->features); - list->features = NULL; - list->num_features = 0; -} diff --git a/src/includes/access_sysfs_client.h b/src/includes/access_sysfs_client.h new file mode 100644 index 000000000..9210d80d1 --- /dev/null +++ b/src/includes/access_sysfs_client.h @@ -0,0 +1,58 @@ +/* + * ======================================================================================= + * + * Filename: frequency_client.h + * + * Description: Header File frequency module, the interface to the frequency daemon + * + * Version: + * Released: + * + * Author: Thomas Gruber (tr), thomas.roehl@googlemail.com + * Project: likwid + * + * Copyright (C) 2016 RRZE, University Erlangen-Nuremberg + * + * 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 3 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, see . + * + * ======================================================================================= + */ + +#ifndef LIKWID_SYSFS_CLIENT_H +#define LIKWID_SYSFS_CLIENT_H + +#define LIKWID_SYSFS_MAX_DATA_LENGTH 1025 + +typedef enum { + SYSFS_READ = 0, + SYSFS_WRITE, + SYSFS_EXIT +} SysfsDataRecordType; + + +typedef enum { + SYSFS_ERR_NONE = 0, + SYSFS_ERR_NOFILE, + SYSFS_ERR_NOPERM, + SYSFS_ERR_UNKNOWN +} SysfsDataRecordError; + +typedef struct { + SysfsDataRecordType type; + SysfsDataRecordError errorcode; + char filename[LIKWID_SYSFS_MAX_DATA_LENGTH]; + int datalen; + char data[LIKWID_SYSFS_MAX_DATA_LENGTH]; +} SysfsDataRecord; + +#endif /* LIKWID_SYSFS_CLIENT_H */ diff --git a/src/includes/hwFeatures.h b/src/includes/hwFeatures.h deleted file mode 100644 index 2a6d2d7c9..000000000 --- a/src/includes/hwFeatures.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef HWFEATURES_H -#define HWFEATURES_H - -#include - - -#endif diff --git a/src/includes/hwFeatures_common.h b/src/includes/hwFeatures_common.h deleted file mode 100644 index 4458906a3..000000000 --- a/src/includes/hwFeatures_common.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef HWFEATURES_COMMON_H -#define HWFEATURES_COMMON_H - -int hwFeatures_init_generic(_HWArchFeatures* infeatures, int* num_features, _HWFeature **features) -{ - int i = 0; - int j = 0; - int c = 0; - int err = 0; - CpuInfo_t cpuinfo = NULL; - _HWFeatureList** feature_list = NULL; - _HWFeature* out = NULL; - err = topology_init(); - if (err < 0) - { - ERROR_PRINT(Failed to initialize topology module); - return err; - } - cpuinfo = get_cpuInfo(); - - c = 0; - while (infeatures[c].family >= 0 && infeatures[c].model >= 0) - { - if (infeatures[c].family == cpuinfo->family && infeatures[c].model == cpuinfo->model) - { - feature_list = infeatures[c].features; - break; - } - c++; - } - if (!feature_list) - { - ERROR_PRINT(No feature list found for current architecture); - *num_features = 0; - *features = NULL; - return 0; - } - - j = 0; - while (feature_list[j] != NULL && feature_list[j]->features != NULL) - { - c += feature_list[j]->num_features; - j++; - } - - out = malloc((c+1) * sizeof(_HWFeature)); - if (!out) - { - ERROR_PRINT(Failed to allocate space for HW feature list); - return -ENOMEM; - } - memset(out, 0, (c+1) * sizeof(_HWFeature)); - - j = 0; - c = 0; - while (feature_list[j] != NULL && feature_list[j]->features != NULL) - { - for (i = 0; i < feature_list[j]->num_features; i++) - { - //_COPY_HWFEATURE_ENTRY(out[c], feature_list[j][i]); - out[c].name = feature_list[j]->features[i].name; - out[c].description = feature_list[j]->features[i].description; - out[c].setter = feature_list[j]->features[i].setter; - out[c].getter = feature_list[j]->features[i].getter; - out[c].scope = feature_list[j]->features[i].scope; - c++; - } - j++; - } - *features = out; - *num_features = c; - return 0; -} - - -#endif diff --git a/src/includes/hwFeatures_types.h b/src/includes/hwFeatures_types.h deleted file mode 100644 index 325c9cec9..000000000 --- a/src/includes/hwFeatures_types.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HWFEATURES_TYPES_H -#define HWFEATURES_TYPES_H - -#include - - -typedef int (*hwfeature_getter_function)(int hwthread, uint64_t *value); -typedef int (*hwfeature_setter_function)(int hwthread, uint64_t value); - -typedef struct { - char* name; - char* description; - hwfeature_getter_function getter; - hwfeature_setter_function setter; - HWFeatureScope scope; -} _HWFeature; - -typedef struct { - int num_features; - _HWFeature* features; -} _HWFeatureList; - -typedef struct { - int family; - int model; - _HWFeatureList** features; -} _HWArchFeatures; - -#endif /* HWFEATURES_TYPES_H */ diff --git a/src/includes/hwFeatures_x86_amd.h b/src/includes/hwFeatures_x86_amd.h deleted file mode 100644 index 8a1db5754..000000000 --- a/src/includes/hwFeatures_x86_amd.h +++ /dev/null @@ -1,345 +0,0 @@ -#ifndef HWFEATURES_X86_AMD_H -#define HWFEATURES_X86_AMD_H - -#include -#include - - -#define MSR_AMD19_PREFETCH_CONTROL 0xC0000108 - -int amd_cpu_prefetch_control_getter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t* value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, &data); - if (err == 0) - { - if (!invert) - { - //*value = (data >> shift) & mask; - *value = (data & mask) >> shift; - } - else - { - //*value = !((data >> shift) & mask); - *value = !((data & mask) >> shift); - } - } - return err; -} - -int amd_cpu_prefetch_control_setter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, &data); - if (err == 0) - { - data &= ~(mask); - if (invert) - value = !value; - data |= ((value << shift) & mask); - err = HPMwrite(hwthread, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, data); - } - return err; -} - - -int amd_cpu_l1_stream_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_prefetch_control_getter(hwthread, 0x1, 0, 1, value); -} - -int amd_cpu_l1_stream_setter(int hwthread, uint64_t value) -{ - return amd_cpu_prefetch_control_setter(hwthread, 0x1, 0, 1, value); -} - -int amd_cpu_l1_stride_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_prefetch_control_getter(hwthread, 0x2, 1, 1, value); -} - -int amd_cpu_l1_stride_setter(int hwthread, uint64_t value) -{ - return amd_cpu_prefetch_control_setter(hwthread, 0x2, 1, 1, value); -} - -int amd_cpu_l1_region_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_prefetch_control_getter(hwthread, 0x4, 2, 1, value); -} - -int amd_cpu_l1_region_setter(int hwthread, uint64_t value) -{ - return amd_cpu_prefetch_control_setter(hwthread, 0x4, 2, 1, value); -} - -int amd_cpu_l2_stream_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_prefetch_control_getter(hwthread, 0x8, 3, 1, value); -} - -int amd_cpu_l2_stream_setter(int hwthread, uint64_t value) -{ - return amd_cpu_prefetch_control_setter(hwthread, 0x8, 3, 1, value); -} - -int amd_cpu_up_down_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_prefetch_control_getter(hwthread, 0x20, 5, 1, value); -} - -int amd_cpu_up_down_setter(int hwthread, uint64_t value) -{ - return amd_cpu_prefetch_control_setter(hwthread, 0x20, 5, 1, value); -} - -#define MAX_AMD_K19_CPU_PREFETCH_FEATURES 5 -static _HWFeature amd_k19_cpu_prefetch_features[] = { - {"L1Stream", "Stream prefetcher that uses history of memory access patterns to fetch additional sequential lines into L1 cache", amd_cpu_l1_stream_getter, amd_cpu_l1_stream_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"L1Stride", "Stride prefetcher that uses memory access history of individual instructions to fetch additional lines into L1 cache when each access is a constant distance from the previous", amd_cpu_l1_stride_getter, amd_cpu_l1_stride_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"L1Region", "Prefetcher that uses memory access history to fetch additional lines into L1 cache when the data access for a given instruction tends to be followed by a consistent pattern of other accesses within a localized region", amd_cpu_l1_region_getter, amd_cpu_l1_region_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"L2Stream", "Stream prefetcher that uses history of memory access patterns to fetch additional sequential lines into L2 cache", amd_cpu_l2_stream_getter, amd_cpu_l2_stream_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"UpDown", "Prefetcher that uses memory access history to determine whether to fetch the next or previous line into L2 cache for all memory accesses", amd_cpu_up_down_getter, amd_cpu_up_down_setter, HWFEATURE_SCOPE_HWTHREAD}, -}; - -static _HWFeatureList amd_k19_cpu_prefetch_feature_list = { - .num_features = MAX_AMD_K19_CPU_PREFETCH_FEATURES, - .features = amd_k19_cpu_prefetch_features, -}; - -#define AMD_K19_SPEC_CONTROL 0x00000048 -int amd_cpu_spec_control_getter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t* value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, AMD_K19_SPEC_CONTROL, &data); - if (err == 0) - { - if (!invert) - { - //*value = (data >> shift) & mask; - *value = (data & mask) >> shift; - } - else - { - //*value = !((data >> shift) & mask); - *value = !((data & mask) >> shift); - } - } - return err; -} -int amd_cpu_spec_control_setter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, AMD_K19_SPEC_CONTROL, &data); - if (err == 0) - { - data &= ~(mask); - if (invert) - value = !value; - data |= ((value << shift) & mask); - err = HPMwrite(hwthread, MSR_DEV, AMD_K19_SPEC_CONTROL, data); - } - return err; -} - - -int amd_cpu_spec_ibrs_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_spec_control_getter(hwthread, 0x01, 0, 0, value); -} - -int amd_cpu_spec_ibrs_setter(int hwthread, uint64_t value) -{ - return amd_cpu_spec_control_setter(hwthread, 0x01, 0, 0, value); -} - -int amd_cpu_spec_stibp_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_spec_control_getter(hwthread, 0x02, 1, 0, value); -} - -int amd_cpu_spec_stibp_setter(int hwthread, uint64_t value) -{ - return amd_cpu_spec_control_setter(hwthread, 0x02, 1, 0, value); -} - -int amd_cpu_spec_ssbd_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_spec_control_getter(hwthread, 0x04, 2, 1, value); -} - -int amd_cpu_spec_ssbd_setter(int hwthread, uint64_t value) -{ - return amd_cpu_spec_control_setter(hwthread, 0x04, 2, 1, value); -} - -int amd_cpu_spec_pfsd_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_spec_control_getter(hwthread, 0x80, 7, 1, value); -} - -int amd_cpu_spec_pfsd_setter(int hwthread, uint64_t value) -{ - return amd_cpu_spec_control_setter(hwthread, 0x80, 7, 1, value); -} - -#define MAX_AMD_K19_CPU_SPECULATION_FEATURES 4 -static _HWFeature amd_k19_cpu_speculation_features[] = { - {"IBRS", "Indirect branch restriction speculation", amd_cpu_spec_ibrs_getter, amd_cpu_spec_ibrs_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"STIBP", "Single thread indirect branch predictor", amd_cpu_spec_stibp_getter, amd_cpu_spec_stibp_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"SSBD", "Speculative Store Bypass", amd_cpu_spec_ssbd_getter, amd_cpu_spec_ssbd_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"PSFD", "Predictive Store Forwarding", amd_cpu_spec_pfsd_getter, amd_cpu_spec_pfsd_setter, HWFEATURE_SCOPE_HWTHREAD}, -}; -static _HWFeatureList amd_k19_cpu_speculation_feature_list = { - .num_features = MAX_AMD_K19_CPU_SPECULATION_FEATURES, - .features = amd_k19_cpu_speculation_features, -}; - - -#define AMD_K19_L1D_FLUSH_REGISTER 0x0000010B -int amd_cpu_flush_l1(int hwthread, uint64_t value) -{ - return HPMwrite(hwthread, MSR_DEV, AMD_K19_L1D_FLUSH_REGISTER, 0x01); -} - -#define MAX_AMD_K19_CPU_L1DFLUSH_FEATURES 1 -static _HWFeature amd_k19_cpu_l1dflush_features[] = { - {"L1DFlush", "Performs a write-back and invalidate of the L1 data cache", NULL, amd_cpu_flush_l1, HWFEATURE_SCOPE_HWTHREAD}, -}; -static _HWFeatureList amd_k19_cpu_l1dflush_feature_list = { - .num_features = MAX_AMD_K19_CPU_L1DFLUSH_FEATURES, - .features = amd_k19_cpu_l1dflush_features, -}; - -#define AMD_K19_HWCONFIG_REGISTER 0xC0010015 -int amd_cpu_hwconfig_getter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t* value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, &data); - if (err == 0) - { - if (!invert) - { - //*value = (data >> shift) & mask; - *value = (data & mask) >> shift; - } - else - { - //*value = !((data >> shift) & mask); - *value = !((data & mask) >> shift); - } - } - return err; -} -int amd_cpu_hwconfig_setter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, &data); - if (err == 0) - { - data &= ~(mask); - if (invert) - value = !value; - data |= ((value << shift) & mask); - err = HPMwrite(hwthread, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, data); - } - return err; -} - -int amd_cpu_hwconfig_cpddis_getter(int hwthread, uint64_t* value) -{ - return amd_cpu_hwconfig_getter(hwthread, (0x1<<25), 25, 1, value); -} - -int amd_cpu_hwconfig_cpddis_setter(int hwthread, uint64_t value) -{ - return amd_cpu_hwconfig_setter(hwthread, (0x1<<25), 25, 1, value); -} - - -#define MAX_AMD_K19_CPU_HWCONFIG_FEATURES 1 -static _HWFeature amd_k19_cpu_hwconfig_features[] = { - {"TurboMode", "Specifies whether core performance boost is requested to be enabled or disabled", amd_cpu_hwconfig_cpddis_getter, amd_cpu_hwconfig_cpddis_setter, HWFEATURE_SCOPE_HWTHREAD}, -}; -static _HWFeatureList amd_k19_cpu_hwconfig_feature_list = { - .num_features = MAX_AMD_K19_CPU_HWCONFIG_FEATURES, - .features = amd_k19_cpu_hwconfig_features, -}; - -static _HWFeatureList* amd_k19_cpu_feature_inputs[] = { - &amd_k19_cpu_prefetch_feature_list, - &amd_k19_cpu_speculation_feature_list, - &amd_k19_cpu_l1dflush_feature_list, - &amd_k19_cpu_hwconfig_feature_list, - NULL, -}; - -static _HWArchFeatures amd_arch_features[] = { - {ZEN3_FAMILY, ZEN4_RYZEN, amd_k19_cpu_feature_inputs}, - {ZEN3_FAMILY, ZEN4_EPYC, amd_k19_cpu_feature_inputs}, - {-1, -1, NULL}, -}; - - - -int hwFeatures_init_x86_amd(int* num_features, _HWFeature **features) -{ - return hwFeatures_init_generic(amd_arch_features, num_features, features); -} - - -#endif diff --git a/src/includes/hwFeatures_x86_intel.h b/src/includes/hwFeatures_x86_intel.h deleted file mode 100644 index 4b7e5b68c..000000000 --- a/src/includes/hwFeatures_x86_intel.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef HWFEATURES_X86_INTEL_H -#define HWFEATURES_X86_INTEL_H - -#define MSR_PREFETCH_ENABLE 0xC0000108 -int intel_cpu_prefetch_control_getter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t* value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, MSR_PREFETCH_ENABLE, &data); - if (err == 0) - { - if (!invert) - { - *value = (data & mask) >> shift; - } - else - { - *value = !((data & mask) >> shift); - } - } - return err; -} - -int intel_cpu_prefetch_control_setter(int hwthread, uint64_t mask, uint64_t shift, int invert, uint64_t value) -{ - int err = 0; - /*if ((err = request_hw_access(dev)) != 0) - { - return err; - } - if (dev->scope != DEVICE_SCOPE_HWTHREAD) - { - return -ENODEV; - }*/ - uint64_t data = 0x0; - err = HPMread(hwthread, MSR_DEV, MSR_PREFETCH_ENABLE, &data); - if (err == 0) - { - data &= ~(mask); - if (invert) - data |= (((!value) << shift) & mask); - else - data |= ((value << shift) & mask); - err = HPMwrite(hwthread, MSR_DEV, MSR_PREFETCH_ENABLE, data); - } - return err; -} - -int intel_cpu_l2_hwpf_getter(int hwthread, uint64_t* value) -{ - return intel_cpu_prefetch_control_getter(hwthread, 0x1, 0, 1, value); -} - -int intel_cpu_l2_hwpf_setter(int hwthread, uint64_t value) -{ - return intel_cpu_prefetch_control_setter(hwthread, 0x1, 0, 1, value); -} - -int intel_cpu_l2_adj_pf_getter(int hwthread, uint64_t* value) -{ - return intel_cpu_prefetch_control_getter(hwthread, 0x2, 1, 1, value); -} - -int intel_cpu_l2_adj_pf_setter(int hwthread, uint64_t value) -{ - return intel_cpu_prefetch_control_setter(hwthread, 0x2, 1, 1, value); -} - -int intel_cpu_l1_dcu_getter(int hwthread, uint64_t* value) -{ - return intel_cpu_prefetch_control_getter(hwthread, 0x4, 3, 1, value); -} - -int intel_cpu_l1_dcu_setter(int hwthread, uint64_t value) -{ - return intel_cpu_prefetch_control_setter(hwthread, 0x4, 3, 1, value); -} - -int intel_cpu_l1_dcu_ip_getter(int hwthread, uint64_t* value) -{ - return intel_cpu_prefetch_control_getter(hwthread, 0x8, 4, 1, value); -} - -int intel_cpu_l1_dcu_ip_setter(int hwthread, uint64_t value) -{ - return intel_cpu_prefetch_control_setter(hwthread, 0x8, 4, 1, value); -} - -#define MAX_INTEL_CPU_PREFETCH_FEATURES 4 -static _HWFeature intel_cpu_prefetch_features[] = { - {"l2_hwpf", "L2 Hardware Prefetcher", intel_cpu_l2_hwpf_getter, intel_cpu_l2_hwpf_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"l2_adj_pf", "L2 Adjacent Cache Line Prefetcher", intel_cpu_l2_adj_pf_getter, intel_cpu_l2_adj_pf_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"l1_dcu", "DCU Hardware Prefetcher", intel_cpu_l1_dcu_getter, intel_cpu_l1_dcu_setter, HWFEATURE_SCOPE_HWTHREAD}, - {"l1_dcu_ip", "DCU IP Prefetcher", intel_cpu_l1_dcu_ip_getter, intel_cpu_l1_dcu_ip_setter, HWFEATURE_SCOPE_HWTHREAD}, - //{"data_pf", "Data Dependent Prefetcher", DEVICE_SCOPE_HWTHREAD}, -}; -static _HWFeatureList intel_cpu_prefetch_feature_list = { - .num_features = MAX_INTEL_CPU_PREFETCH_FEATURES, - .features = intel_cpu_prefetch_features, -}; - -int intel_cpu_l2_multipath_pf_getter(int hwthread, uint64_t* value) -{ - return intel_cpu_prefetch_control_getter(hwthread, 0x20, 6, 1, value); -} - -int intel_cpu_l2_multipath_pf_setter(int hwthread, uint64_t value) -{ - return intel_cpu_prefetch_control_setter(hwthread, 0x20, 6, 1, value); -} - -#define MAX_INTEL_8F_CPU_FEATURES 1 -static _HWFeature intel_8f_cpu_features[] = { - {"l2_multipath_pf", "L2 Adaptive Multipath Probability Prefetcher", intel_cpu_l2_multipath_pf_getter, intel_cpu_l2_multipath_pf_setter, HWFEATURE_SCOPE_HWTHREAD} -}; -static _HWFeatureList intel_8f_cpu_feature_list = { - .num_features = MAX_INTEL_8F_CPU_FEATURES, - .features = intel_8f_cpu_features, -}; - -static _HWFeatureList* intel_arch_feature_inputs[] = { - &intel_cpu_prefetch_feature_list, - NULL, -}; - -static _HWFeatureList* intel_8f_arch_feature_inputs[] = { - &intel_cpu_prefetch_feature_list, - &intel_8f_cpu_feature_list, - NULL, -}; - - -static _HWArchFeatures intel_arch_features[] = { - {P6_FAMILY, SANDYBRIDGE, intel_arch_feature_inputs}, - {P6_FAMILY, SANDYBRIDGE_EP, intel_arch_feature_inputs}, - {P6_FAMILY, IVYBRIDGE, intel_arch_feature_inputs}, - {P6_FAMILY, IVYBRIDGE_EP, intel_arch_feature_inputs}, - {P6_FAMILY, HASWELL, intel_arch_feature_inputs}, - {P6_FAMILY, HASWELL_EP, intel_arch_feature_inputs}, - {P6_FAMILY, HASWELL_M1, intel_arch_feature_inputs}, - {P6_FAMILY, HASWELL_M2, intel_arch_feature_inputs}, - {P6_FAMILY, BROADWELL, intel_arch_feature_inputs}, - {P6_FAMILY, BROADWELL_E, intel_arch_feature_inputs}, - {P6_FAMILY, BROADWELL_D, intel_arch_feature_inputs}, - {P6_FAMILY, BROADWELL_E3, intel_arch_feature_inputs}, - {P6_FAMILY, SKYLAKE1, intel_arch_feature_inputs}, - {P6_FAMILY, SKYLAKE2, intel_arch_feature_inputs}, - {P6_FAMILY, SKYLAKEX, intel_arch_feature_inputs}, - {P6_FAMILY, 0x8F, intel_8f_arch_feature_inputs}, - {P6_FAMILY, KABYLAKE1, intel_arch_feature_inputs}, - {P6_FAMILY, KABYLAKE2, intel_arch_feature_inputs}, - {P6_FAMILY, CANNONLAKE, intel_arch_feature_inputs}, - {P6_FAMILY, ICELAKE1, intel_arch_feature_inputs}, - {P6_FAMILY, ICELAKE2, intel_arch_feature_inputs}, - {P6_FAMILY, ROCKETLAKE, intel_arch_feature_inputs}, - {P6_FAMILY, COMETLAKE1, intel_arch_feature_inputs}, - {P6_FAMILY, COMETLAKE2, intel_arch_feature_inputs}, - {P6_FAMILY, ICELAKEX1, intel_arch_feature_inputs}, - {P6_FAMILY, ICELAKEX2, intel_arch_feature_inputs}, - {P6_FAMILY, SNOWRIDGEX, intel_arch_feature_inputs}, - {P6_FAMILY, TIGERLAKE1, intel_arch_feature_inputs}, - {P6_FAMILY, TIGERLAKE2, intel_arch_feature_inputs}, - {-1, -1, NULL}, -}; - - - -int hwFeatures_init_x86_intel(int* num_features, _HWFeature **features) -{ - return hwFeatures_init_generic(intel_arch_features, num_features, features); -} - -#endif diff --git a/src/includes/likwid.h b/src/includes/likwid.h index 340cebc1e..52d447b82 100644 --- a/src/includes/likwid.h +++ b/src/includes/likwid.h @@ -59,6 +59,47 @@ extern "C" { #endif +/* +################################################################################ +# Library information +################################################################################ +*/ + +/** \addtogroup LibInfo Information about the library +* @{ +*/ +/*! \brief Get the major version of the LIKWID library + +@return Major version +*/ +extern int likwid_getMajorVersion(void) __attribute__ ((visibility ("default") )); +/*! \brief Get the minor version of the LIKWID library + +@return Minor version +*/ +extern int likwid_getMinorVersion(void) __attribute__ ((visibility ("default") )); +/*! \brief Get the bugfix version of the LIKWID library + +@return Bugfix version +*/ +extern int likwid_getBugfixVersion(void) __attribute__ ((visibility ("default") )); + +/*! \brief Check whether the LIKWID library was built with Nvidia GPU support */ +extern int likwid_getNvidiaSupport(void) __attribute__ ((visibility ("default") )); + +/*! \brief Check whether the LIKWID library was built with AMD GPU support */ +extern int likwid_getRocmSupport(void) __attribute__ ((visibility ("default") )); + +/*! \brief Get the maximal count of supported HW threads */ +extern int likwid_getMaxSupportedThreads(void) __attribute__ ((visibility ("default") )); + +/*! \brief Get the maximal count of supported CPU sockets */ +extern int likwid_getMaxSupportedSockets(void) __attribute__ ((visibility ("default") )); + +/*! \brief Check whether the LIKWID library was built with sysFeatures support */ +extern int likwid_getSysFeaturesSupport(void) __attribute__ ((visibility ("default") )); +/** @}*/ + /* ################################################################################ # Library information @@ -2835,46 +2876,108 @@ double rocmon_getMetricOfRegionGpu(int region, int metricId, int gpuId) #endif /* LIKWID_WITH_ROCMON */ +#ifdef LIKWID_WITH_SYSFEATURES + typedef enum { - HWFEATURE_SCOPE_INVALID = 0, - HWFEATURE_SCOPE_HWTHREAD, - MAX_HWFEATURE_SCOPE, -} HWFeatureScope; - -static char *HWFeatureScopeNames[MAX_HWFEATURE_SCOPE] = { - [HWFEATURE_SCOPE_INVALID] = "invalid", - [HWFEATURE_SCOPE_HWTHREAD] = "hwthread", + DEVICE_TYPE_INVALID, + DEVICE_TYPE_HWTHREAD, + DEVICE_TYPE_CORE, + DEVICE_TYPE_LLC, + DEVICE_TYPE_NUMA, + DEVICE_TYPE_DIE, + DEVICE_TYPE_SOCKET, + DEVICE_TYPE_NODE, +#ifdef LIKWID_WITH_NVMON + DEVICE_TYPE_NVIDIA_GPU, +#endif +#ifdef LIKWID_WITH_ROCMON + DEVICE_TYPE_AMD_GPU, +#endif + MAX_DEVICE_TYPE, +} LikwidDeviceType; +#define MIN_DEVICE_TYPE DEVICE_TYPE_HWTHREAD + + +typedef struct { + LikwidDeviceType type; + union { + struct { + int id; + } simple; + struct { + int16_t pci_domain; + int8_t pci_bus; + int8_t pci_dev; + int8_t pci_func; + } pci; + } id; + int internal_id; +} _LikwidDevice; +typedef _LikwidDevice* LikwidDevice_t; + +typedef struct { + int num_devices; + LikwidDevice_t devices; +} _LikwidDeviceList; +typedef _LikwidDeviceList* LikwidDeviceList_t; + +static char* LikwidDeviceTypeNames[MAX_DEVICE_TYPE] = { + [DEVICE_TYPE_INVALID] = "invalid", + [DEVICE_TYPE_HWTHREAD] = "hwthread", + [DEVICE_TYPE_CORE] = "core", + [DEVICE_TYPE_LLC] = "LLC", + [DEVICE_TYPE_NUMA] = "numa", + [DEVICE_TYPE_DIE] = "die", + [DEVICE_TYPE_SOCKET] = "socket", + [DEVICE_TYPE_NODE] = "node", +#ifdef LIKWID_WITH_NVMON + [DEVICE_TYPE_NVIDIA_GPU] = "nvidia_gpu", +#endif +#ifdef LIKWID_WITH_ROCMON + [DEVICE_TYPE_AMD_GPU] = "amd_gpu", +#endif }; +int likwid_device_create(LikwidDeviceType type, int id, LikwidDevice_t* device); +void likwid_device_destroy(LikwidDevice_t device); +char* device_type_name(LikwidDeviceType type); + typedef struct { - char *name; - char *description; - HWFeatureScope scope; - unsigned int readonly : 1; - unsigned int writeonly : 1; -} HWFeature; + char* name; + char* category; + char* description; + LikwidDeviceType type; + unsigned int readonly:1; + unsigned int writeonly:1; +} SysFeature; typedef struct { - int num_features; - HWFeature *features; -} HWFeatureList; + int num_features; + SysFeature* features; +} SysFeatureList; -int hwFeatures_init() __attribute__((visibility("default"))); -int hwFeatures_list(HWFeatureList *list) __attribute__((visibility("default"))); -void hwFeatures_list_return(HWFeatureList *list) - __attribute__((visibility("default"))); +#define SYSFEATURE_PCI_DEVICE_TO_ID(domain, bus, slot, func) \ + ((((uint16_t)(domain))<<16)|(((uint8_t)(bus))<<8)|(((((uint8_t)(slot)) & 0x1f) << 3) | (((uint8_t)(func)) & 0x07))) +#define SYSFEATURES_ID_TO_PCI_DOMAIN(id) (((id) >> 16) & 0xFFFF) +#define SYSFEATURES_ID_TO_PCI_BUS(id) (((id) >> 8) & 0xFF) +#define SYSFEATURES_ID_TO_PCI_SLOT(id) (((id) >> 3) & 0x1F) +#define SYSFEATURES_ID_TO_PCI_FUNC(id) ((id) & 0x07) -int hwFeatures_get(HWFeature *feature, int hwthread, uint64_t *value) - __attribute__((visibility("default"))); -int hwFeatures_getByName(char *name, int hwthread, uint64_t *value) - __attribute__((visibility("default"))); -int hwFeatures_modify(HWFeature *feature, int hwthread, uint64_t value) - __attribute__((visibility("default"))); -int hwFeatures_modifyByName(char *name, int hwthread, uint64_t value) - __attribute__((visibility("default"))); -void hwFeatures_finalize() __attribute__((visibility("default"))); + +int sysFeatures_init() __attribute__ ((visibility ("default") )); + +int sysFeatures_list(SysFeatureList* list) __attribute__ ((visibility ("default") )); +void sysFeatures_list_return(SysFeatureList* list) __attribute__ ((visibility ("default") )); + +int sysFeatures_get(SysFeature* feature, LikwidDevice_t device, char** value) __attribute__ ((visibility ("default") )); +int sysFeatures_getByName(char* name, LikwidDevice_t device, char** value) __attribute__ ((visibility ("default") )); +int sysFeatures_modify(SysFeature* feature, LikwidDevice_t device, char* value) __attribute__ ((visibility ("default") )); +int sysFeatures_modifyByName(char* name, LikwidDevice_t device, char* value) __attribute__ ((visibility ("default") )); + +void sysFeatures_finalize() __attribute__ ((visibility ("default") )); +#endif /* LIKWID_WITH_SYSFEATURES */ #ifdef __cplusplus } diff --git a/src/includes/likwid_device.h b/src/includes/likwid_device.h new file mode 100644 index 000000000..b39f8c209 --- /dev/null +++ b/src/includes/likwid_device.h @@ -0,0 +1,11 @@ +#ifndef LIKWID_DEVICE_H +#define LIKWID_DEVICE_H + +#include + +int likwid_device_create(LikwidDeviceType scope, int id, LikwidDevice_t* device) __attribute__ ((visibility ("default") )); +void likwid_device_destroy(LikwidDevice_t device) __attribute__ ((visibility ("default") )); + +char* device_type_name(LikwidDeviceType type) __attribute__ ((visibility ("default") )); + +#endif /* LIKWID_DEVICE_H */ diff --git a/src/includes/sysFeatures.h b/src/includes/sysFeatures.h new file mode 100644 index 000000000..feea190b0 --- /dev/null +++ b/src/includes/sysFeatures.h @@ -0,0 +1,11 @@ +#ifndef HWFEATURES_H +#define HWFEATURES_H + +#include +#include + +#define HWFEATURES_MAX_STR_LENGTH 100 +#define HWFEATURES_MIN_STRLEN(a, b) ((a) > (b) ? (b) : (a)) + + +#endif diff --git a/src/includes/sysFeatures_amd.h b/src/includes/sysFeatures_amd.h new file mode 100644 index 000000000..742a86629 --- /dev/null +++ b/src/includes/sysFeatures_amd.h @@ -0,0 +1,365 @@ +#ifndef HWFEATURES_X86_AMD_H +#define HWFEATURES_X86_AMD_H + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define MSR_AMD19_PREFETCH_CONTROL 0xC0000108 + +int amd_cpu_prefetch_control_getter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char** value) +{ + int err = 0; + /*if ((err = request_hw_access(dev)) != 0) + { + return err; + } + if (dev->scope != DEVICE_SCOPE_device) + { + return -ENODEV; + }*/ + uint64_t data = 0x0; + uint64_t _val = 0x0; + err = HPMread(device->id.simple.id, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, &data); + if (err == 0) + { + if (!invert) + { + //*value = (data >> shift) & mask; + _val = (data & mask) >> shift; + } + else + { + //*value = !((data >> shift) & mask); + _val = !((data & mask) >> shift); + } + return _uint64_to_string(_val, value); + } + return err; +} + +int amd_cpu_prefetch_control_setter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char* value) +{ + int err = 0; + /*if ((err = request_hw_access(dev)) != 0) + { + return err; + } + if (dev->scope != DEVICE_SCOPE_device) + { + return -ENODEV; + }*/ + uint64_t data = 0x0; + uint64_t _val = 0x0ULL; + err = _string_to_uint64(value, &_val); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, &data); + if (err == 0) + { + data &= ~(mask); + if (invert) + _val = !_val; + data |= ((_val << shift) & mask); + err = HPMwrite(device->id.simple.id, MSR_DEV, MSR_AMD19_PREFETCH_CONTROL, data); + } + return err; +} + + +int amd_cpu_l1_stream_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_prefetch_control_getter(device, 0x1, 0, 1, value); +} + +int amd_cpu_l1_stream_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_prefetch_control_setter(device, 0x1, 0, 1, value); +} + +int amd_cpu_l1_stride_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_prefetch_control_getter(device, 0x2, 1, 1, value); +} + +int amd_cpu_l1_stride_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_prefetch_control_setter(device, 0x2, 1, 1, value); +} + +int amd_cpu_l1_region_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_prefetch_control_getter(device, 0x4, 2, 1, value); +} + +int amd_cpu_l1_region_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_prefetch_control_setter(device, 0x4, 2, 1, value); +} + +int amd_cpu_l2_stream_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_prefetch_control_getter(device, 0x8, 3, 1, value); +} + +int amd_cpu_l2_stream_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_prefetch_control_setter(device, 0x8, 3, 1, value); +} + +int amd_cpu_up_down_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_prefetch_control_getter(device, 0x20, 5, 1, value); +} + +int amd_cpu_up_down_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_prefetch_control_setter(device, 0x20, 5, 1, value); +} + +#define MAX_AMD_K19_CPU_PREFETCH_FEATURES 5 +static _SysFeature amd_k19_cpu_prefetch_features[] = { + {"l1_stream", "prefetch", "Stream prefetcher that uses history of memory access patterns to fetch additional sequential lines into L1 cache", amd_cpu_l1_stream_getter, amd_cpu_l1_stream_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_stride", "prefetch", "Stride prefetcher that uses memory access history of individual instructions to fetch additional lines into L1 cache when each access is a constant distance from the previous", amd_cpu_l1_stride_getter, amd_cpu_l1_stride_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_region", "prefetch", "Prefetcher that uses memory access history to fetch additional lines into L1 cache when the data access for a given instruction tends to be followed by a consistent pattern of other accesses within a localized region", amd_cpu_l1_region_getter, amd_cpu_l1_region_setter, DEVICE_TYPE_HWTHREAD}, + {"L2_stream", "prefetch", "Stream prefetcher that uses history of memory access patterns to fetch additional sequential lines into L2 cache", amd_cpu_l2_stream_getter, amd_cpu_l2_stream_setter, DEVICE_TYPE_HWTHREAD}, + {"up_down", "prefetch", "Prefetcher that uses memory access history to determine whether to fetch the next or previous line into L2 cache for all memory accesses", amd_cpu_up_down_getter, amd_cpu_up_down_setter, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList amd_k19_cpu_prefetch_feature_list = { + .num_features = MAX_AMD_K19_CPU_PREFETCH_FEATURES, + .features = amd_k19_cpu_prefetch_features, +}; + +#define AMD_K19_SPEC_CONTROL 0x00000048 +int amd_cpu_spec_control_getter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char** value) +{ + int err = 0; + uint64_t data = 0x0; + uint64_t _val = 0x0; + err = HPMread(device->id.simple.id, MSR_DEV, AMD_K19_SPEC_CONTROL, &data); + if (err == 0) + { + if (!invert) + { + _val = (data & mask) >> shift; + } + else + { + _val = !((data & mask) >> shift); + } + } + return _uint64_to_string(_val, value); +} +int amd_cpu_spec_control_setter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char* value) +{ + int err = 0; + /*if ((err = request_hw_access(dev)) != 0) + { + return err; + } + if (dev->scope != DEVICE_SCOPE_device) + { + return -ENODEV; + }*/ + uint64_t data = 0x0; + uint64_t _val = 0x0; + err = _string_to_uint64(value, &_val); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, AMD_K19_SPEC_CONTROL, &data); + if (err == 0) + { + data &= ~(mask); + if (invert) + _val = !_val; + data |= ((_val << shift) & mask); + err = HPMwrite(device->id.simple.id, MSR_DEV, AMD_K19_SPEC_CONTROL, data); + } + return err; +} + + +int amd_cpu_spec_ibrs_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_spec_control_getter(device, 0x01, 0, 0, value); +} + +int amd_cpu_spec_ibrs_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_spec_control_setter(device, 0x01, 0, 0, value); +} + +int amd_cpu_spec_stibp_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_spec_control_getter(device, 0x02, 1, 0, value); +} + +int amd_cpu_spec_stibp_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_spec_control_setter(device, 0x02, 1, 0, value); +} + +int amd_cpu_spec_ssbd_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_spec_control_getter(device, 0x04, 2, 1, value); +} + +int amd_cpu_spec_ssbd_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_spec_control_setter(device, 0x04, 2, 1, value); +} + +int amd_cpu_spec_pfsd_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_spec_control_getter(device, 0x80, 7, 1, value); +} + +int amd_cpu_spec_pfsd_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_spec_control_setter(device, 0x80, 7, 1, value); +} + +#define MAX_AMD_K19_CPU_SPECULATION_FEATURES 4 +static _SysFeature amd_k19_cpu_speculation_features[] = { + {"ibrs", "spec_ctrl", "Indirect branch restriction speculation", amd_cpu_spec_ibrs_getter, amd_cpu_spec_ibrs_setter, DEVICE_TYPE_HWTHREAD}, + {"stibp", "spec_ctrl", "Single thread indirect branch predictor", amd_cpu_spec_stibp_getter, amd_cpu_spec_stibp_setter, DEVICE_TYPE_HWTHREAD}, + {"ssbd", "spec_ctrl", "Speculative Store Bypass", amd_cpu_spec_ssbd_getter, amd_cpu_spec_ssbd_setter, DEVICE_TYPE_HWTHREAD}, + {"psfd", "spec_ctrl", "Predictive Store Forwarding", amd_cpu_spec_pfsd_getter, amd_cpu_spec_pfsd_setter, DEVICE_TYPE_HWTHREAD}, +}; +static _SysFeatureList amd_k19_cpu_speculation_feature_list = { + .num_features = MAX_AMD_K19_CPU_SPECULATION_FEATURES, + .features = amd_k19_cpu_speculation_features, +}; + + +#define AMD_K19_L1D_FLUSH_REGISTER 0x0000010B +int amd_cpu_flush_l1(LikwidDevice_t device, char* value) +{ + return HPMwrite(device->id.simple.id, MSR_DEV, AMD_K19_L1D_FLUSH_REGISTER, 0x01); +} + +#define MAX_AMD_K19_CPU_L1DFLUSH_FEATURES 1 +static _SysFeature amd_k19_cpu_l1dflush_features[] = { + {"l1dflush", "cache", "Performs a write-back and invalidate of the L1 data cache", NULL, amd_cpu_flush_l1, DEVICE_TYPE_HWTHREAD}, +}; +static _SysFeatureList amd_k19_cpu_l1dflush_feature_list = { + .num_features = MAX_AMD_K19_CPU_L1DFLUSH_FEATURES, + .features = amd_k19_cpu_l1dflush_features, +}; + +#define AMD_K19_HWCONFIG_REGISTER 0xC0010015 +int amd_cpu_hwconfig_getter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char** value) +{ + int err = 0; + /*if ((err = request_hw_access(dev)) != 0) + { + return err; + } + if (dev->scope != DEVICE_SCOPE_device) + { + return -ENODEV; + }*/ + uint64_t data = 0x0; + uint64_t _val = 0x0; + err = HPMread(device->id.simple.id, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, &data); + if (err == 0) + { + if (!invert) + { + _val = (data & mask) >> shift; + } + else + { + _val = !((data & mask) >> shift); + } + } + return _uint64_to_string(_val, value); +} +int amd_cpu_hwconfig_setter(LikwidDevice_t device, uint64_t mask, uint64_t shift, int invert, char* value) +{ + int err = 0; + /*if ((err = request_hw_access(dev)) != 0) + { + return err; + } + if (dev->scope != DEVICE_SCOPE_device) + { + return -ENODEV; + }*/ + uint64_t data = 0x0; + uint64_t _val = 0x0; + err = _string_to_uint64(value, &_val); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, &data); + if (err == 0) + { + data &= ~(mask); + if (invert) + _val = !_val; + data |= ((_val << shift) & mask); + err = HPMwrite(device->id.simple.id, MSR_DEV, AMD_K19_HWCONFIG_REGISTER, data); + } + return err; +} + +int amd_cpu_hwconfig_cpddis_getter(LikwidDevice_t device, char** value) +{ + return amd_cpu_hwconfig_getter(device, (0x1<<25), 25, 1, value); +} + +int amd_cpu_hwconfig_cpddis_setter(LikwidDevice_t device, char* value) +{ + return amd_cpu_hwconfig_setter(device, (0x1<<25), 25, 1, value); +} + + +#define MAX_AMD_K19_CPU_HWCONFIG_FEATURES 1 +static _SysFeature amd_k19_cpu_hwconfig_features[] = { + {"TurboMode", "cpufreq", "Specifies whether core performance boost is requested to be enabled or disabled", amd_cpu_hwconfig_cpddis_getter, amd_cpu_hwconfig_cpddis_setter, DEVICE_TYPE_HWTHREAD}, +}; +static _SysFeatureList amd_k19_cpu_hwconfig_feature_list = { + .num_features = MAX_AMD_K19_CPU_HWCONFIG_FEATURES, + .features = amd_k19_cpu_hwconfig_features, +}; + +static _SysFeatureList* amd_k19_cpu_feature_inputs[] = { + &amd_k19_cpu_prefetch_feature_list, + &amd_k19_cpu_speculation_feature_list, + &amd_k19_cpu_l1dflush_feature_list, + &amd_k19_cpu_hwconfig_feature_list, + &amd_rapl_core_feature_list, + &amd_rapl_pkg_feature_list, + &amd_rapl_l3_feature_list, + NULL, +}; + +static _HWArchFeatures amd_arch_features[] = { + {ZEN3_FAMILY, ZEN4_RYZEN, amd_k19_cpu_feature_inputs}, + {ZEN3_FAMILY, ZEN4_EPYC, amd_k19_cpu_feature_inputs}, + {-1, -1, NULL}, +}; + + + +int sysFeatures_init_x86_amd(_SysFeatureList* out) +{ + return sysFeatures_init_generic(amd_arch_features, out); +} + + +#endif diff --git a/src/includes/sysFeatures_amd_rapl.h b/src/includes/sysFeatures_amd_rapl.h new file mode 100644 index 000000000..ceb25368d --- /dev/null +++ b/src/includes/sysFeatures_amd_rapl.h @@ -0,0 +1,63 @@ +#ifndef HWFEATURES_X86_AMD_RAPL_H +#define HWFEATURES_X86_AMD_RAPL_H + + +int amd_rapl_pkg_test(); + +int sysFeatures_amd_pkg_energy_status_test(); +int sysFeatures_amd_pkg_energy_status_getter(LikwidDevice_t device, char** value); + + + +#define MAX_AMD_RAPL_PKG_FEATURES 1 +static _SysFeature amd_rapl_pkg_features[] = { + {"pkg_energy", "rapl", "Current energy consumtion (PKG domain)", sysFeatures_amd_pkg_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_amd_pkg_energy_status_test, "uJ"}, +}; + +static _SysFeatureList amd_rapl_pkg_feature_list = { + .num_features = MAX_AMD_RAPL_PKG_FEATURES, + .tester = amd_rapl_pkg_test, + .features = amd_rapl_pkg_features, +}; + +int amd_rapl_core_test(); + +int sysFeatures_amd_core_energy_status_test(); +int sysFeatures_amd_core_energy_status_getter(LikwidDevice_t device, char** value); + + +#define MAX_AMD_RAPL_CORE_FEATURES 1 +static _SysFeature amd_rapl_core_features[] = { + {"core_energy", "rapl", "Current energy consumtion (DRAM domain)", sysFeatures_amd_core_energy_status_getter, NULL, DEVICE_TYPE_CORE, sysFeatures_amd_core_energy_status_test, "uJ"}, +}; + +static _SysFeatureList amd_rapl_core_feature_list = { + .num_features = MAX_AMD_RAPL_CORE_FEATURES, + .tester = amd_rapl_core_test, + .features = amd_rapl_core_features, +}; + +int amd_rapl_l3_test(); + +int sysFeatures_amd_l3_energy_status_test(); +int sysFeatures_amd_l3_energy_status_getter(LikwidDevice_t device, char** value); + + + +#define MAX_AMD_RAPL_L3_FEATURES 1 +static _SysFeature amd_rapl_l3_features[] = { + {"l3_energy", "rapl", "Current energy consumtion (L3 domain)", sysFeatures_amd_l3_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_amd_l3_energy_status_test, "uJ"}, +}; + +static _SysFeatureList amd_rapl_l3_feature_list = { + .num_features = MAX_AMD_RAPL_L3_FEATURES, + .tester = amd_rapl_l3_test, + .features = amd_rapl_l3_features, +}; + + + +int sysFeatures_init_amd_rapl(_SysFeatureList* out); + + +#endif /* HWFEATURES_X86_AMD_RAPL_H */ diff --git a/src/includes/sysFeatures_common.h b/src/includes/sysFeatures_common.h new file mode 100644 index 000000000..d328ea089 --- /dev/null +++ b/src/includes/sysFeatures_common.h @@ -0,0 +1,12 @@ +#ifndef HWFEATURES_COMMON_H +#define HWFEATURES_COMMON_H + +#include + +int register_features(_SysFeatureList *features, _SysFeatureList* in); +int sysFeatures_init_generic(_HWArchFeatures* infeatures, _SysFeatureList *list); + +int _uint64_to_string(uint64_t value, char** str); +int _string_to_uint64(char* str, uint64_t* value); + +#endif diff --git a/src/includes/sysFeatures_cpufreq.h b/src/includes/sysFeatures_cpufreq.h new file mode 100644 index 000000000..dda1722f9 --- /dev/null +++ b/src/includes/sysFeatures_cpufreq.h @@ -0,0 +1,79 @@ +#ifndef HWFEATURES_CPUFREQ_H +#define HWFEATURES_CPUFREQ_H + +int sysFeatures_init_cpufreq(_SysFeatureList* out); + + +int cpufreq_acpi_test(); +int cpufreq_acpi_cur_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_acpi_min_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_acpi_max_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_acpi_avail_cpu_freqs_getter(LikwidDevice_t device, char** value); +int cpufreq_acpi_governor_getter(LikwidDevice_t device, char** value); +int cpufreq_acpi_governor_setter(LikwidDevice_t device, char* value); +int cpufreq_acpi_avail_governors_getter(LikwidDevice_t device, char** value); + + + +#define MAX_CPUFREQ_ACPI_CPU_FEATURES 6 +static _SysFeature cpufreq_acpi_features[] = { + {"cur_cpu_freq", "cpu_freq", "Current CPU frequency", cpufreq_acpi_cur_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"min_cpu_freq", "cpu_freq", "Minimal CPU frequency", cpufreq_acpi_min_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"max_cpu_freq", "cpu_freq", "Maximal CPU frequency", cpufreq_acpi_max_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"avail_freqs", "cpu_freq", "Available CPU frequencies", cpufreq_acpi_cur_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"governor", "cpu_freq", "CPU frequency governor", cpufreq_acpi_governor_getter, cpufreq_acpi_governor_setter, DEVICE_TYPE_HWTHREAD}, + {"avail_governors", "cpu_freq", "Available CPU frequency governor", cpufreq_acpi_avail_governors_getter, NULL, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList cpufreq_acpi_feature_list = { + .num_features = MAX_CPUFREQ_ACPI_CPU_FEATURES, + .tester = cpufreq_acpi_test, + .features = cpufreq_acpi_features, +}; + +int cpufreq_intel_pstate_test(); +int cpufreq_intel_pstate_base_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_cur_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_min_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_max_cpu_freq_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_governor_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_governor_setter(LikwidDevice_t device, char* value); +int cpufreq_intel_pstate_avail_governors_getter(LikwidDevice_t device, char** value); + + +#define MAX_CPUFREQ_PSTATE_CPU_FEATURES 6 +static _SysFeature cpufreq_pstate_features[] = { + {"base_freq", "cpu_freq", "Base CPU frequency", cpufreq_intel_pstate_base_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"cur_cpu_freq", "cpu_freq", "Current CPU frequency", cpufreq_intel_pstate_cur_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"min_cpu_freq", "cpu_freq", "Minimal CPU frequency", cpufreq_intel_pstate_min_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"max_cpu_freq", "cpu_freq", "Maximal CPU frequency", cpufreq_intel_pstate_max_cpu_freq_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"governor", "cpu_freq", "CPU frequency governor", cpufreq_intel_pstate_governor_getter, cpufreq_intel_pstate_governor_setter, DEVICE_TYPE_HWTHREAD}, + {"avail_freqs", "cpu_freq", "Available CPU frequencies", cpufreq_intel_pstate_avail_governors_getter, NULL, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList cpufreq_pstate_feature_list = { + .num_features = MAX_CPUFREQ_PSTATE_CPU_FEATURES, + .tester = cpufreq_intel_pstate_test, + .features = cpufreq_pstate_features, +}; + +int cpufreq_epp_test(); +int cpufreq_intel_pstate_epp_getter(LikwidDevice_t device, char** value); +int cpufreq_intel_pstate_avail_epps_getter(LikwidDevice_t device, char** value); + + +#define MAX_CPUFREQ_EPP_FEATURES 2 +static _SysFeature cpufreq_epp_features[] = { + {"epp", "cpu_freq", "Current energy performance preference", cpufreq_intel_pstate_epp_getter, NULL, DEVICE_TYPE_HWTHREAD}, + {"avail_epps", "cpu_freq", "Available energy performance preferences", cpufreq_intel_pstate_epp_getter, NULL, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList cpufreq_epp_feature_list = { + .num_features = MAX_CPUFREQ_EPP_FEATURES, + .tester = cpufreq_epp_test, + .features = cpufreq_epp_features, +}; + + +#endif /* HWFEATURES_CPUFREQ_H */ + diff --git a/src/includes/sysFeatures_intel.h b/src/includes/sysFeatures_intel.h new file mode 100644 index 000000000..152402d90 --- /dev/null +++ b/src/includes/sysFeatures_intel.h @@ -0,0 +1,98 @@ +#ifndef HWFEATURES_X86_INTEL_H +#define HWFEATURES_X86_INTEL_H + +#include +#include +#include +#include +#include + + +int intel_cpu_msr_register_getter(LikwidDevice_t device, uint32_t reg, uint64_t mask, uint64_t shift, int invert, char** value); + +int intel_cpu_msr_register_setter(LikwidDevice_t device, uint32_t reg, uint64_t mask, uint64_t shift, int invert, char* value); + +#include +#include +#include +#include +#include + +static _SysFeatureList* intel_arch_feature_inputs[] = { + &intel_cpu_prefetch_feature_list, + &intel_cpu_ida_feature_list, + &intel_cpu_turbo_feature_list, + &intel_uncorefreq_feature_list, + &intel_cpu_spec_ctrl_feature_list, + NULL, +}; + +static _SysFeatureList* intel_8f_arch_feature_inputs[] = { + &intel_cpu_prefetch_feature_list, + &intel_8f_cpu_feature_list, + &intel_cpu_ida_feature_list, + &intel_cpu_turbo_feature_list, + &intel_cpu_spec_ctrl_feature_list, + NULL, +}; + +static _SysFeatureList* intel_knl_arch_feature_inputs[] = { + &intel_knl_cpu_feature_list, + &intel_cpu_ida_feature_list, + &intel_cpu_turbo_feature_list, + &intel_cpu_spec_ctrl_feature_list, + NULL, +}; + +static _SysFeatureList* intel_core2_arch_feature_inputs[] = { + &intel_core2_cpu_feature_list, + &intel_cpu_ida_feature_list, + &intel_cpu_turbo_feature_list, + &intel_cpu_spec_ctrl_feature_list, + NULL, +}; + + +static _HWArchFeatures intel_arch_features[] = { + {P6_FAMILY, SANDYBRIDGE, intel_arch_feature_inputs}, + {P6_FAMILY, SANDYBRIDGE_EP, intel_arch_feature_inputs}, + {P6_FAMILY, IVYBRIDGE, intel_arch_feature_inputs}, + {P6_FAMILY, IVYBRIDGE_EP, intel_arch_feature_inputs}, + {P6_FAMILY, HASWELL, intel_arch_feature_inputs}, + {P6_FAMILY, HASWELL_EP, intel_arch_feature_inputs}, + {P6_FAMILY, HASWELL_M1, intel_arch_feature_inputs}, + {P6_FAMILY, HASWELL_M2, intel_arch_feature_inputs}, + {P6_FAMILY, BROADWELL, intel_arch_feature_inputs}, + {P6_FAMILY, BROADWELL_E, intel_arch_feature_inputs}, + {P6_FAMILY, BROADWELL_D, intel_arch_feature_inputs}, + {P6_FAMILY, BROADWELL_E3, intel_arch_feature_inputs}, + {P6_FAMILY, SKYLAKE1, intel_arch_feature_inputs}, + {P6_FAMILY, SKYLAKE2, intel_arch_feature_inputs}, + {P6_FAMILY, SKYLAKEX, intel_arch_feature_inputs}, + {P6_FAMILY, 0x8F, intel_8f_arch_feature_inputs}, + {P6_FAMILY, KABYLAKE1, intel_arch_feature_inputs}, + {P6_FAMILY, KABYLAKE2, intel_arch_feature_inputs}, + {P6_FAMILY, CANNONLAKE, intel_arch_feature_inputs}, + {P6_FAMILY, ICELAKE1, intel_arch_feature_inputs}, + {P6_FAMILY, ICELAKE2, intel_arch_feature_inputs}, + {P6_FAMILY, ROCKETLAKE, intel_arch_feature_inputs}, + {P6_FAMILY, COMETLAKE1, intel_arch_feature_inputs}, + {P6_FAMILY, COMETLAKE2, intel_arch_feature_inputs}, + {P6_FAMILY, ICELAKEX1, intel_arch_feature_inputs}, + {P6_FAMILY, ICELAKEX2, intel_arch_feature_inputs}, + {P6_FAMILY, SAPPHIRERAPIDS, intel_arch_feature_inputs}, + {P6_FAMILY, SNOWRIDGEX, intel_arch_feature_inputs}, + {P6_FAMILY, TIGERLAKE1, intel_arch_feature_inputs}, + {P6_FAMILY, TIGERLAKE2, intel_arch_feature_inputs}, + {P6_FAMILY, XEON_PHI_KNL, intel_knl_arch_feature_inputs}, + {P6_FAMILY, XEON_PHI_KML, intel_knl_arch_feature_inputs}, + {P6_FAMILY, CORE2_45, intel_core2_arch_feature_inputs}, + {P6_FAMILY, CORE2_65, intel_core2_arch_feature_inputs}, + {-1, -1, NULL}, +}; + + + +int sysFeatures_init_x86_intel(_SysFeatureList* list); + +#endif diff --git a/src/includes/sysFeatures_intel_prefetcher.h b/src/includes/sysFeatures_intel_prefetcher.h new file mode 100644 index 000000000..e97fedd18 --- /dev/null +++ b/src/includes/sysFeatures_intel_prefetcher.h @@ -0,0 +1,115 @@ +#ifndef HWFEATURES_X86_INTEL_PREFETCHER_H +#define HWFEATURES_X86_INTEL_PREFETCHER_H + +/*********************************************************************************************************************/ +/* Intel prefetchers */ +/*********************************************************************************************************************/ + +int intel_cpu_l2_hwpf_getter(LikwidDevice_t device, char** value); +int intel_cpu_l2_hwpf_setter(LikwidDevice_t device, char* value); +int intel_cpu_l2_adj_pf_getter(LikwidDevice_t device, char** value); +int intel_cpu_l2_adj_pf_setter(LikwidDevice_t device, char* value); +int intel_cpu_l1_dcu_getter(LikwidDevice_t device, char** value); +int intel_cpu_l1_dcu_setter(LikwidDevice_t device, char* value); +int intel_cpu_l1_dcu_ip_getter(LikwidDevice_t device, char** value); +int intel_cpu_l1_dcu_ip_setter(LikwidDevice_t device, char* value); + +#define MAX_INTEL_CPU_PREFETCH_FEATURES 4 +static _SysFeature intel_cpu_prefetch_features[] = { + {"l2_hwpf", "prefetch", "L2 Hardware Prefetcher", intel_cpu_l2_hwpf_getter, intel_cpu_l2_hwpf_setter, DEVICE_TYPE_HWTHREAD}, + {"l2_adj_pf", "prefetch", "L2 Adjacent Cache Line Prefetcher", intel_cpu_l2_adj_pf_getter, intel_cpu_l2_adj_pf_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_dcu", "prefetch", "DCU Hardware Prefetcher", intel_cpu_l1_dcu_getter, intel_cpu_l1_dcu_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_dcu_ip", "prefetch", "DCU IP Prefetcher", intel_cpu_l1_dcu_ip_getter, intel_cpu_l1_dcu_ip_setter, DEVICE_TYPE_HWTHREAD}, + //{"data_pf", "Data Dependent Prefetcher", DEVICE_TYPE_HWTHREAD}, +}; +static _SysFeatureList intel_cpu_prefetch_feature_list = { + .num_features = MAX_INTEL_CPU_PREFETCH_FEATURES, + .features = intel_cpu_prefetch_features, +}; + + +/*********************************************************************************************************************/ +/* Intel 0x8F prefetchers */ +/*********************************************************************************************************************/ + +int intel_cpu_l2_multipath_pf_getter(LikwidDevice_t device, char** value); +int intel_cpu_l2_multipath_pf_setter(LikwidDevice_t device, char* value); + +#define MAX_INTEL_8F_CPU_FEATURES 1 +static _SysFeature intel_8f_cpu_features[] = { + {"l2_multipath_pf", "prefetch", "L2 Adaptive Multipath Probability Prefetcher", intel_cpu_l2_multipath_pf_getter, intel_cpu_l2_multipath_pf_setter, DEVICE_TYPE_HWTHREAD} +}; + +static _SysFeatureList intel_8f_cpu_feature_list = { + .num_features = MAX_INTEL_8F_CPU_FEATURES, + .features = intel_8f_cpu_features, +}; + + +/*********************************************************************************************************************/ +/* Intel Knights Landing prefetchers */ +/*********************************************************************************************************************/ +int intel_knl_l1_dcu_getter(LikwidDevice_t device, char** value); +int intel_knl_l1_dcu_setter(LikwidDevice_t device, char* value); +int intel_knl_l2_hwpf_getter(LikwidDevice_t device, char** value); +int intel_knl_l2_hwpf_setter(LikwidDevice_t device, char* value); + + +#define MAX_INTEL_KNL_CPU_FEATURES 2 +static _SysFeature intel_knl_cpu_prefetch_features[] = { + {"l2_hwpf", "prefetch", "L2 Hardware Prefetcher", intel_knl_l2_hwpf_getter, intel_knl_l2_hwpf_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_dcu", "prefetch", "DCU Hardware Prefetcher", intel_knl_l1_dcu_getter, intel_knl_l1_dcu_setter, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList intel_knl_cpu_feature_list = { + .num_features = MAX_INTEL_KNL_CPU_FEATURES, + .features = intel_knl_cpu_prefetch_features, +}; + +/*********************************************************************************************************************/ +/* Intel Core2 prefetchers */ +/*********************************************************************************************************************/ + +int intel_core2_l2_hwpf_getter(LikwidDevice_t device, char** value); +int intel_core2_l2_hwpf_setter(LikwidDevice_t device, char* value); +int intel_core2_l2_adjpf_getter(LikwidDevice_t device, char** value); +int intel_core2_l2_adjpf_setter(LikwidDevice_t device, char* value); +int intel_core2_l1_dcu_getter(LikwidDevice_t device, char** value); +int intel_core2_l1_dcu_setter(LikwidDevice_t device, char* value); +int intel_core2_l1_dcu_ip_getter(LikwidDevice_t device, char** value); +int intel_core2_l1_dcu_ip_setter(LikwidDevice_t device, char* value); + +#define MAX_INTEL_CORE2_CPU_FEATURES 4 +static _SysFeature intel_core2_cpu_prefetch_features[] = { + {"hwpf", "prefetch", "Hardware prefetcher operation on streams of data", intel_core2_l2_hwpf_getter, intel_knl_l2_hwpf_setter, DEVICE_TYPE_HWTHREAD}, + {"adj_pf", "prefetch", "Adjacent Cache Line Prefetcher", intel_core2_l2_adjpf_getter, intel_core2_l2_adjpf_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_dcu", "prefetch", "DCU L1 data cache prefetcher", intel_core2_l1_dcu_getter, intel_core2_l1_dcu_setter, DEVICE_TYPE_HWTHREAD}, + {"l1_dcu_ip", "prefetch", "DCU IP Prefetcher", intel_core2_l1_dcu_ip_getter, intel_core2_l1_dcu_ip_setter, DEVICE_TYPE_HWTHREAD}, +}; + +static _SysFeatureList intel_core2_cpu_feature_list = { + .num_features = MAX_INTEL_CORE2_CPU_FEATURES, + .features = intel_core2_cpu_prefetch_features, +}; + + +/*********************************************************************************************************************/ +/* Intel Dynamic Acceleration */ +/*********************************************************************************************************************/ + +int intel_core2_ida_tester(); +int intel_core2_ida_getter(LikwidDevice_t device, char** value); +int intel_core2_ida_setter(LikwidDevice_t device, char* value); + +#define MAX_INTEL_CPU_IDA_FEATURES 1 +static _SysFeature intel_cpu_ida_features[] = { + {"ida", "prefetch", "Intel Dynamic Acceleration", intel_core2_ida_getter, intel_core2_ida_setter, DEVICE_TYPE_HWTHREAD, intel_core2_ida_tester}, +}; + +static _SysFeatureList intel_cpu_ida_feature_list = { + .num_features = MAX_INTEL_CPU_IDA_FEATURES, + .tester = intel_core2_ida_tester, + .features = intel_cpu_ida_features, +}; + +#endif /* HWFEATURES_X86_INTEL_PREFETCHER_H */ diff --git a/src/includes/sysFeatures_intel_rapl.h b/src/includes/sysFeatures_intel_rapl.h new file mode 100644 index 000000000..d71cb36cc --- /dev/null +++ b/src/includes/sysFeatures_intel_rapl.h @@ -0,0 +1,227 @@ +#ifndef HWFEATURES_X86_INTEL_RAPL_H +#define HWFEATURES_X86_INTEL_RAPL_H + + +int intel_rapl_pkg_test(); + +int sysFeatures_intel_pkg_energy_status_test(); +int sysFeatures_intel_pkg_energy_status_getter(LikwidDevice_t device, char** value); + +int sysFeatures_intel_pkg_energy_limit_test(); + +int sysFeatures_intel_pkg_energy_limit_1_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_1_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_1_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_1_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_1_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_1_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_pkg_energy_limit_2_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_2_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_2_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_2_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_2_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_2_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pkg_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_pkg_info_test(); +int sysFeatures_intel_pkg_info_tdp(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_info_min_power(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_info_max_power(LikwidDevice_t device, char** value); +int sysFeatures_intel_pkg_info_max_time(LikwidDevice_t device, char** value); + + +#define MAX_INTEL_RAPL_PKG_FEATURES 13 +static _SysFeature intel_rapl_pkg_features[] = { + {"pkg_energy", "rapl", "Current energy consumtion (PKG domain)", sysFeatures_intel_pkg_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_status_test, "uJ"}, + {"pkg_tdp", "rapl", "Thermal Spec Power", sysFeatures_intel_pkg_info_tdp, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_info_test, "mW"}, + {"pkg_min_limit", "rapl", "Minimum Power", sysFeatures_intel_pkg_info_min_power, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_info_test, "mW"}, + {"pkg_max_limit", "rapl", "Maximum Power", sysFeatures_intel_pkg_info_max_power, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_info_test, "mW"}, + {"pkg_max_time", "rapl", "Maximum Time", sysFeatures_intel_pkg_info_max_time, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_info_test, "ms"}, + {"pkg_limit_1", "rapl", "Long-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_1_getter, sysFeatures_intel_pkg_energy_limit_1_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test, "mW"}, + {"pkg_limit_1_time", "rapl", "Long-term time window (PKG domain)", sysFeatures_intel_pkg_energy_limit_1_time_getter, sysFeatures_intel_pkg_energy_limit_1_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test, "ms"}, + {"pkg_limit_1_enable", "rapl", "Status of long-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_1_enable_getter, sysFeatures_intel_pkg_energy_limit_1_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test}, + {"pkg_limit_1_clamp", "rapl", "Clamping status of long-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_1_clamp_getter, sysFeatures_intel_pkg_energy_limit_1_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test}, + {"pkg_limit_2", "rapl", "Short-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_2_getter, sysFeatures_intel_pkg_energy_limit_2_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test, "mW"}, + {"pkg_limit_2_time", "rapl", "Short-term time window (PKG domain)", sysFeatures_intel_pkg_energy_limit_2_time_getter, sysFeatures_intel_pkg_energy_limit_2_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test, "ms"}, + {"pkg_limit_2_enable", "rapl", "Status of short-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_2_enable_getter, sysFeatures_intel_pkg_energy_limit_2_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test}, + {"pkg_limit_2_clamp", "rapl", "Clamping status of short-term energy limit (PKG domain)", sysFeatures_intel_pkg_energy_limit_2_clamp_getter, sysFeatures_intel_pkg_energy_limit_2_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pkg_energy_limit_test}, +}; + +static _SysFeatureList intel_rapl_pkg_feature_list = { + .num_features = MAX_INTEL_RAPL_PKG_FEATURES, + .tester = intel_rapl_pkg_test, + .features = intel_rapl_pkg_features, +}; + +int intel_rapl_dram_test(); + +int sysFeatures_intel_dram_energy_status_test(); +int sysFeatures_intel_dram_energy_status_getter(LikwidDevice_t device, char** value); + +int sysFeatures_intel_dram_energy_limit_test(); +int sysFeatures_intel_dram_energy_limit_1_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_energy_limit_1_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_dram_energy_limit_1_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_energy_limit_1_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_dram_energy_limit_1_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_energy_limit_1_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_dram_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_dram_info_test(); +int sysFeatures_intel_dram_info_tdp(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_info_min_power(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_info_max_power(LikwidDevice_t device, char** value); +int sysFeatures_intel_dram_info_max_time(LikwidDevice_t device, char** value); + + +#define MAX_INTEL_RAPL_DRAM_FEATURES 9 +static _SysFeature intel_rapl_dram_features[] = { + {"dram_energy", "rapl", "Current energy consumtion (DRAM domain)", sysFeatures_intel_dram_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_energy_status_test, "uJ"}, + {"dram_tdp", "rapl", "Thermal Spec Power", sysFeatures_intel_dram_info_tdp, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_info_test, "mW"}, + {"dram_min_limit", "rapl", "Minimum Power", sysFeatures_intel_dram_info_min_power, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_info_test, "mW"}, + {"dram_max_limit", "rapl", "Maximum Power", sysFeatures_intel_dram_info_max_power, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_info_test, "mW"}, + {"dram_max_time", "rapl", "Maximum Time", sysFeatures_intel_dram_info_max_time, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_info_test, "ms"}, + {"dram_limit", "rapl", "Long-term energy limit (DRAM domain)", sysFeatures_intel_dram_energy_limit_1_getter, sysFeatures_intel_dram_energy_limit_1_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_energy_limit_test, "mW"}, + {"dram_limit_time", "rapl", "Long-term time window (DRAM domain)", sysFeatures_intel_dram_energy_limit_1_time_getter, sysFeatures_intel_dram_energy_limit_1_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_energy_limit_test, "ms"}, + {"dram_limit_enable", "rapl", "Status of long-term energy limit (DRAM domain)", sysFeatures_intel_dram_energy_limit_1_enable_getter, sysFeatures_intel_dram_energy_limit_1_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_energy_limit_test}, + {"dram_limit_clamp", "rapl", "Clamping status of long-term energy limit (DRAM domain)", sysFeatures_intel_dram_energy_limit_1_clamp_getter, sysFeatures_intel_dram_energy_limit_1_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_dram_energy_limit_test}, +}; + +static _SysFeatureList intel_rapl_dram_feature_list = { + .num_features = MAX_INTEL_RAPL_DRAM_FEATURES, + .tester = intel_rapl_dram_test, + .features = intel_rapl_dram_features, +}; + + +int intel_rapl_pp0_test(); + +int sysFeatures_intel_pp0_energy_status_test(); +int sysFeatures_intel_pp0_energy_status_getter(LikwidDevice_t device, char** value); + +int sysFeatures_intel_pp0_energy_limit_test(); +int sysFeatures_intel_pp0_energy_limit_1_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp0_energy_limit_1_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp0_energy_limit_1_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp0_energy_limit_1_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp0_energy_limit_1_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp0_energy_limit_1_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp0_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp0_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_pp0_policy_test(); +int sysFeatures_intel_pp0_policy_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp0_policy_setter(LikwidDevice_t device, char* value); + + +#define MAX_INTEL_RAPL_PP0_FEATURES 6 +static _SysFeature intel_rapl_pp0_features[] = { + {"pp0_energy", "rapl", "Current energy consumtion (PP0 domain)", sysFeatures_intel_pp0_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_energy_status_test, "uJ"}, + {"pp0_limit", "rapl", "Long-term energy limit (PP0 domain)", sysFeatures_intel_pp0_energy_limit_1_getter, sysFeatures_intel_pp0_energy_limit_1_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_energy_limit_test, "mW"}, + {"pp0_limit_time", "rapl", "Long-term time window (PP0 domain)", sysFeatures_intel_pp0_energy_limit_1_time_getter, sysFeatures_intel_pp0_energy_limit_1_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_energy_limit_test, "ms"}, + {"pp0_limit_enable", "rapl", "Status of long-term energy limit (PP0 domain)", sysFeatures_intel_pp0_energy_limit_1_enable_getter, sysFeatures_intel_pp0_energy_limit_1_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_energy_limit_test}, + {"pp0_limit_clamp", "rapl", "Clamping status of long-term energy limit (PP0 domain)", sysFeatures_intel_pp0_energy_limit_1_clamp_getter, sysFeatures_intel_pp0_energy_limit_1_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_energy_limit_test}, + {"pp0_policy", "rapl", "Balance Power Policy (PP0 domain)", sysFeatures_intel_pp0_policy_getter, sysFeatures_intel_pp0_policy_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp0_policy_test}, +}; + +static _SysFeatureList intel_rapl_pp0_feature_list = { + .num_features = MAX_INTEL_RAPL_PP0_FEATURES, + .tester = intel_rapl_pp0_test, + .features = intel_rapl_pp0_features, +}; + + +int intel_rapl_pp1_test(); + +int sysFeatures_intel_pp1_energy_status_test(); +int sysFeatures_intel_pp1_energy_status_getter(LikwidDevice_t device, char** value); + +int sysFeatures_intel_pp1_energy_limit_test(); +int sysFeatures_intel_pp1_energy_limit_1_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp1_energy_limit_1_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp1_energy_limit_1_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp1_energy_limit_1_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp1_energy_limit_1_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp1_energy_limit_1_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_pp1_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp1_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_pp1_policy_test(); +int sysFeatures_intel_pp1_policy_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_pp1_policy_setter(LikwidDevice_t device, char* value); + + + +#define MAX_INTEL_RAPL_PP1_FEATURES 6 +static _SysFeature intel_rapl_pp1_features[] = { + {"pp1_energy", "rapl", "Current energy consumtion (PP1 domain)", sysFeatures_intel_pp1_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_energy_status_test, "uJ"}, + {"pp1_limit", "rapl", "Long-term energy limit (PP1 domain)", sysFeatures_intel_pp1_energy_limit_1_getter, sysFeatures_intel_pp1_energy_limit_1_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_energy_limit_test, "mW"}, + {"pp1_limit_time", "rapl", "Long-term time window (PP1 domain)", sysFeatures_intel_pp1_energy_limit_1_time_getter, sysFeatures_intel_pp1_energy_limit_1_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_energy_limit_test, "ms"}, + {"pp1_limit_enable", "rapl", "Status of long-term energy limit (PP1 domain)", sysFeatures_intel_pp1_energy_limit_1_enable_getter, sysFeatures_intel_pp1_energy_limit_1_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_energy_limit_test}, + {"pp1_limit_clamp", "rapl", "Clamping status of long-term energy limit (PP1 domain)", sysFeatures_intel_pp1_energy_limit_1_clamp_getter, sysFeatures_intel_pp1_energy_limit_1_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_energy_limit_test}, + {"pp1_policy", "rapl", "Balance Power Policy (PP1 domain)", sysFeatures_intel_pp1_policy_getter, sysFeatures_intel_pp1_policy_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_pp1_policy_test}, +}; + +static _SysFeatureList intel_rapl_pp1_feature_list = { + .num_features = MAX_INTEL_RAPL_PP1_FEATURES, + .tester = intel_rapl_pp1_test, + .features = intel_rapl_pp1_features, +}; + + +int intel_rapl_psys_test(); + +int sysFeatures_intel_psys_energy_status_test(); +int sysFeatures_intel_psys_energy_status_getter(LikwidDevice_t device, char** value); + +int sysFeatures_intel_psys_energy_limit_test(); +int sysFeatures_intel_psys_energy_limit_1_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_1_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_1_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_1_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_1_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_1_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value); + +int sysFeatures_intel_psys_energy_limit_2_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_2_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_2_time_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_2_time_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_2_enable_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_2_enable_setter(LikwidDevice_t device, char* value); +int sysFeatures_intel_psys_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value); +int sysFeatures_intel_psys_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value); + + + +#define MAX_INTEL_RAPL_PSYS_FEATURES 9 +static _SysFeature intel_rapl_psys_features[] = { + {"psys_energy", "rapl", "Current energy consumtion (PSYS domain)", sysFeatures_intel_psys_energy_status_getter, NULL, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_status_test, "uJ"}, + {"psys_limit_1", "rapl", "Long-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_1_getter, sysFeatures_intel_psys_energy_limit_1_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test, "mW"}, + {"psys_limit_1_time", "rapl", "Long-term time window (PSYS domain)", sysFeatures_intel_psys_energy_limit_1_time_getter, sysFeatures_intel_psys_energy_limit_1_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test, "ms"}, + {"psys_limit_1_enable", "rapl", "Status of long-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_1_enable_getter, sysFeatures_intel_psys_energy_limit_1_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test}, + {"psys_limit_1_clamp", "rapl", "Clamping status of long-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_1_clamp_getter, sysFeatures_intel_psys_energy_limit_1_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test}, + {"psys_limit_2", "rapl", "Short-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_2_getter, sysFeatures_intel_psys_energy_limit_2_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test, "mW"}, + {"psys_limit_2_time", "rapl", "Short-term time window (PSYS domain)", sysFeatures_intel_psys_energy_limit_2_time_getter, sysFeatures_intel_psys_energy_limit_2_time_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test, "ms"}, + {"psys_limit_2_enable", "rapl", "Status of short-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_2_enable_getter, sysFeatures_intel_psys_energy_limit_2_enable_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test}, + {"psys_limit_2_clamp", "rapl", "Clamping status of short-term energy limit (PSYS domain)", sysFeatures_intel_psys_energy_limit_2_clamp_getter, sysFeatures_intel_psys_energy_limit_2_clamp_setter, DEVICE_TYPE_SOCKET, sysFeatures_intel_psys_energy_limit_test}, +}; + + +static _SysFeatureList intel_rapl_psys_feature_list = { + .num_features = MAX_INTEL_RAPL_PSYS_FEATURES, + .tester = intel_rapl_psys_test, + .features = intel_rapl_psys_features, +}; + + +int sysFeatures_init_intel_rapl(_SysFeatureList* out); + + +#endif /* HWFEATURES_X86_INTEL_UNCOREFREQ_H */ diff --git a/src/includes/sysFeatures_intel_spec_ctrl.h b/src/includes/sysFeatures_intel_spec_ctrl.h new file mode 100644 index 000000000..378d299d1 --- /dev/null +++ b/src/includes/sysFeatures_intel_spec_ctrl.h @@ -0,0 +1,62 @@ +#ifndef HWFEATURES_X86_INTEL_SPEC_CTRL_H +#define HWFEATURES_X86_INTEL_SPEC_CTRL_H + +/*********************************************************************************************************************/ +/* Intel speculation control */ +/*********************************************************************************************************************/ + +int intel_cpu_spec_ibrs_tester(); +int intel_cpu_spec_ibrs_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_ibrs_setter(LikwidDevice_t device, char** value);*/ + + +int intel_cpu_spec_stibp_tester(); +int intel_cpu_spec_stibp_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_stibp_setter(LikwidDevice_t device, char** value);*/ + +int intel_cpu_spec_ssbd_tester(); +int intel_cpu_spec_ssbd_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_ssbd_setter(LikwidDevice_t device, char** value);*/ + +int intel_cpu_spec_ipred_dis_tester(); +int intel_cpu_spec_ipred_dis_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_ipred_dis_setter(LikwidDevice_t device, char** value);*/ + + +int intel_cpu_spec_rrsba_dis_tester(); +int intel_cpu_spec_rrsba_dis_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_rrsba_dis_setter(LikwidDevice_t device, char** value);*/ + + +int intel_cpu_spec_psfd_tester(); +int intel_cpu_spec_psfd_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_psfd_setter(LikwidDevice_t device, char** value);*/ + + +int intel_cpu_spec_ddpd_tester(); +int intel_cpu_spec_ddpd_getter(LikwidDevice_t device, char** value); +/*int intel_cpu_spec_ddpd_setter(LikwidDevice_t device, char** value);*/ + + +int intel_cpu_spec_ctrl(); + +#define MAX_INTEL_CPU_SPEC_CTRL_FEATURES 7 +static _SysFeature intel_cpu_spec_ctrl_features[] = { + {"ibrs", "spec_ctrl", "Indirect Branch Restricted Speculation", intel_cpu_spec_ibrs_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_ibrs_tester}, + {"stibp", "spec_ctrl", "Single Thread Indirect Branch Predictors", intel_cpu_spec_stibp_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_stibp_tester}, + {"ssbd", "spec_ctrl", "Speculative Store Bypass Disable", intel_cpu_spec_ssbd_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_ssbd_tester}, + {"ipred_dis", "spec_ctrl", "", intel_cpu_spec_ipred_dis_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_ipred_dis_tester}, + {"rrsba_dis", "spec_ctrl", "", intel_cpu_spec_rrsba_dis_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_rrsba_dis_tester}, + {"psfd", "spec_ctrl", "Fast Store Forwarding Predictor", intel_cpu_spec_psfd_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_psfd_tester}, + {"ddpd", "spec_ctrl", "Data Dependent Prefetcher", intel_cpu_spec_ddpd_getter, NULL, DEVICE_TYPE_HWTHREAD, intel_cpu_spec_ddpd_tester}, +}; +static _SysFeatureList intel_cpu_spec_ctrl_feature_list = { + .num_features = MAX_INTEL_CPU_SPEC_CTRL_FEATURES, + .tester = intel_cpu_spec_ctrl, + .features = intel_cpu_spec_ctrl_features, +}; + + +int sysFeatures_init_intel_spec_ctrl(_SysFeatureList* out); + +#endif /* HWFEATURES_X86_INTEL_SPEC_CTRL_H */ diff --git a/src/includes/sysFeatures_intel_turbo.h b/src/includes/sysFeatures_intel_turbo.h new file mode 100644 index 000000000..f518a7d0d --- /dev/null +++ b/src/includes/sysFeatures_intel_turbo.h @@ -0,0 +1,23 @@ +#ifndef HWFEATURES_X86_INTEL_TURBO_H +#define HWFEATURES_X86_INTEL_TURBO_H + + +int intel_cpu_turbo_test(); +int intel_cpu_turbo_getter(LikwidDevice_t device, char** value); +int intel_cpu_turbo_setter(LikwidDevice_t device, char* value); + +#define MAX_INTEL_TURBO_CPU_FEATURES 1 +static _SysFeature intel_cpu_turbo_features[] = { + {"turbo", "cpu_freq", "Turbo mode", intel_cpu_turbo_getter, intel_cpu_turbo_setter, DEVICE_TYPE_HWTHREAD, intel_cpu_turbo_test}, +}; + +static _SysFeatureList intel_cpu_turbo_feature_list = { + .num_features = MAX_INTEL_TURBO_CPU_FEATURES, + .tester = intel_cpu_turbo_test, + .features = intel_cpu_turbo_features, +}; + + + + +#endif /* HWFEATURES_X86_INTEL_TURBO_H */ diff --git a/src/includes/sysFeatures_intel_uncorefreq.h b/src/includes/sysFeatures_intel_uncorefreq.h new file mode 100644 index 000000000..d5f3d95a6 --- /dev/null +++ b/src/includes/sysFeatures_intel_uncorefreq.h @@ -0,0 +1,27 @@ +#ifndef HWFEATURES_X86_INTEL_UNCOREFREQ_H +#define HWFEATURES_X86_INTEL_UNCOREFREQ_H + + +int intel_uncorefreq_test(); +int intel_uncore_cur_freq_getter(LikwidDevice_t device, char** value); +int intel_uncore_min_freq_getter(LikwidDevice_t device, char** value); +int intel_uncore_max_freq_getter(LikwidDevice_t device, char** value); + + +#define MAX_INTEL_UNCOREFREQ_FEATURES 3 +static _SysFeature intel_uncorefreq_features[] = { + {"cur_uncore_freq", "uncore_freq", "Current Uncore frequency", intel_uncore_cur_freq_getter, NULL, DEVICE_TYPE_SOCKET}, + {"min_uncore_freq", "uncore_freq", "Minimum Uncore frequency", intel_uncore_min_freq_getter, NULL, DEVICE_TYPE_SOCKET}, + {"max_uncore_freq", "uncore_freq", "Maximal Uncore frequency", intel_uncore_max_freq_getter, NULL, DEVICE_TYPE_SOCKET}, +}; + +static _SysFeatureList intel_uncorefreq_feature_list = { + .num_features = MAX_INTEL_UNCOREFREQ_FEATURES, + .tester = intel_uncorefreq_test, + .features = intel_uncorefreq_features, +}; + + + + +#endif /* HWFEATURES_X86_INTEL_UNCOREFREQ_H */ diff --git a/src/includes/sysFeatures_linux_numa_balancing.h b/src/includes/sysFeatures_linux_numa_balancing.h new file mode 100644 index 000000000..ae3830778 --- /dev/null +++ b/src/includes/sysFeatures_linux_numa_balancing.h @@ -0,0 +1,35 @@ +#ifndef HWFEATURES_NUMABALANCING_H +#define HWFEATURES_NUMABALANCING_H + + + +int numa_balancing_procfs_getter(LikwidDevice_t device, char** value, char* sysfsfile); + +int numa_balancing_test(); +int numa_balancing_state_getter(LikwidDevice_t device, char** value); +int numa_balancing_scan_delay_getter(LikwidDevice_t device, char** value); +int numa_balancing_scan_period_min_getter(LikwidDevice_t device, char** value); +int numa_balancing_scan_period_max_getter(LikwidDevice_t device, char** value); +int numa_balancing_scan_size_getter(LikwidDevice_t device, char** value); + +#define MAX_NUMA_BALANCING_FEATURES 5 +static _SysFeature numa_balancing_features[] = { + {"numa_balancing", "os", "Current state of NUMA balancing", numa_balancing_state_getter, NULL, DEVICE_TYPE_NODE}, + {"numa_balancing_scan_delay_ms", "os", "Time between page scans", numa_balancing_scan_delay_getter, NULL, DEVICE_TYPE_NODE}, + {"numa_balancing_scan_period_min_ms", "os", "Minimal time for scan period", numa_balancing_scan_period_min_getter, NULL, DEVICE_TYPE_NODE}, + {"numa_balancing_scan_period_max_ms", "os", "Maximal time for scan period", numa_balancing_scan_period_max_getter, NULL, DEVICE_TYPE_NODE}, + {"numa_balancing_scan_size_mb", "os", "Scan size for NUMA balancing", numa_balancing_scan_size_getter, NULL, DEVICE_TYPE_NODE}, +}; + +static _SysFeatureList numa_balancing_feature_list = { + .num_features = MAX_NUMA_BALANCING_FEATURES, + .tester = numa_balancing_test, + .features = numa_balancing_features, +}; + + +int sysFeatures_init_linux_numa_balancing(_SysFeatureList* out); + + +#endif /* HWFEATURES_NUMABALANCING_H */ + diff --git a/src/includes/sysFeatures_list.h b/src/includes/sysFeatures_list.h new file mode 100644 index 000000000..d34e67056 --- /dev/null +++ b/src/includes/sysFeatures_list.h @@ -0,0 +1,20 @@ +#ifndef HWFEATURES_LIST_H +#define HWFEATURES_LIST_H + +#include +#include + +/* External lists with flags etc. */ +int add_to_feature_list(SysFeatureList *list, SysFeature* feature); +int merge_feature_lists(SysFeatureList *inout, SysFeatureList *in); +void free_feature_list(SysFeatureList *list); + +/* Internal lists with function pointers etc. */ +int _add_to_feature_list(_SysFeatureList *list, _SysFeature* feature); +int _merge_feature_lists(_SysFeatureList *inout, _SysFeatureList *in); +void _free_feature_list(_SysFeatureList *list); + +/* Get an external list from an internal one */ +int internal_to_external_feature_list(_SysFeatureList *inlist, SysFeatureList* outlist); + +#endif /* HWFEATURES_LIST_H */ diff --git a/src/includes/sysFeatures_types.h b/src/includes/sysFeatures_types.h new file mode 100644 index 000000000..8eeaa03d1 --- /dev/null +++ b/src/includes/sysFeatures_types.h @@ -0,0 +1,46 @@ +#ifndef HWFEATURES_TYPES_H +#define HWFEATURES_TYPES_H + +#include +#include +#include + +typedef enum { + HWFEATURES_TYPE_UINT64 = 0, + HWFEATURES_TYPE_DOUBLE, + HWFEATURES_TYPE_STRING +} HWFEATURES_VALUE_TYPES; + + +typedef int (*hwfeature_getter_function)(LikwidDevice_t device, char** value); +typedef int (*hwfeature_setter_function)(LikwidDevice_t device, char* value); +typedef int (*hwfeature_test_function)(); + +typedef struct { + char* name; + char* category; + char* description; + hwfeature_getter_function getter; + hwfeature_setter_function setter; + LikwidDeviceType type; + hwfeature_test_function tester; + char* unit; +} _SysFeature; + +typedef struct { + int num_features; + _SysFeature* features; + hwfeature_test_function tester; +} _SysFeatureList; + +typedef struct { + int family; + int model; + _SysFeatureList** features; + int max_stepping; +} _HWArchFeatures; + +#define IS_VALID_DEVICE_TYPE(scope) (((scope) >= MIN_DEVICE_TYPE) && ((scope) < MAX_DEVICE_TYPE)) + + +#endif /* HWFEATURES_TYPES_H */ diff --git a/src/likwid_device.c b/src/likwid_device.c new file mode 100644 index 000000000..be0d92665 --- /dev/null +++ b/src/likwid_device.c @@ -0,0 +1,139 @@ +#include +#include +#include + +#include +#include +#include +#include + + + +static int likwid_device_create_simple(LikwidDeviceType type, int id, LikwidDevice_t* device) +{ + LikwidDevice_t dev = malloc(sizeof(_LikwidDevice)); + if (!dev) + { + return -ENOMEM; + } + dev->type = type; + dev->id.simple.id = id; + dev->internal_id = id; + *device = dev; + return 0; +} + +int likwid_device_create(LikwidDeviceType type, int id, LikwidDevice_t* device) +{ + if ((type <= DEVICE_TYPE_INVALID) || (type >= MAX_DEVICE_TYPE) || (id < 0) || (!device)) + { + return -EINVAL; + } + CpuTopology_t topo = NULL; + int err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + int maxHWThreadNum = 0; + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = & topo->threadPool[i]; + if (t->apicId > maxHWThreadNum) + { + maxHWThreadNum = t->apicId; + } + } + + switch (type) { + case DEVICE_TYPE_HWTHREAD: + if (id >= 0 && id < maxHWThreadNum) + { + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = & topo->threadPool[i]; + if (t->apicId == id && t->inCpuSet) + { + return likwid_device_create_simple(type, id, device); + } + } + } + break; + case DEVICE_TYPE_NODE: + return likwid_device_create_simple(type, 0, device); + break; + case DEVICE_TYPE_CORE: + if (id > 0 && id < maxHWThreadNum) + { + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = & topo->threadPool[i]; + if (t->coreId == id && t->inCpuSet) + { + return likwid_device_create_simple(type, id, device); + } + } + } + break; + case DEVICE_TYPE_SOCKET: + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = & topo->threadPool[i]; + if (t->packageId == id && t->inCpuSet) + { + return likwid_device_create_simple(type, id, device); + } + } + break; + case DEVICE_TYPE_LLC: + ERROR_PRINT(Not implemented); + break; + case DEVICE_TYPE_NUMA: + err = numa_init(); + if (err == 0) + { + NumaTopology_t numatopo = get_numaTopology(); + for (int i = 0; i < numatopo->numberOfNodes; i++) + { + NumaNode* node = &numatopo->nodes[i]; + if (node->id == id) + { + return likwid_device_create_simple(type, id, device); + } + } + } + break; + case DEVICE_TYPE_DIE: + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = & topo->threadPool[i]; + if (t->dieId == id && t->inCpuSet) + { + return likwid_device_create_simple(type, id, device); + } + } + break; + default: + break; + } + return -ENODEV; +} + +void likwid_device_destroy(LikwidDevice_t device) +{ + if (device) + { + free(device); + device = NULL; + } +} + +char* device_type_name(LikwidDeviceType type) +{ + if ((type < DEVICE_TYPE_INVALID) || (type >= MAX_DEVICE_TYPE)) + { + return "unsupported"; + } + return LikwidDeviceTypeNames[type]; +} diff --git a/src/luawid.c b/src/luawid.c index 57aedfa1d..c08e496dd 100644 --- a/src/luawid.c +++ b/src/luawid.c @@ -3019,98 +3019,15 @@ static int lua_likwid_nvFinalize(lua_State *L) { return 0; } -static int lua_likwid_nvSupported(lua_State *L) { - lua_pushboolean(L, 1); - return 1; -} -#else -static int lua_likwid_nvSupported(lua_State *L) { - lua_pushboolean(L, 0); - return 0; -} #endif /* LIKWID_WITH_NVMON */ -static int hwfeatures_inititalized = 0; -static int lua_likwid_initHWFeatures(lua_State *L) { - int err = 0; - if (!hwfeatures_inititalized) { - err = hwFeatures_init(); - if (err == 0) { - hwfeatures_inititalized = 1; - } - } - lua_pushnumber(L, err); - return 1; -} - -static int lua_likwid_finalizeHWFeatures(lua_State *L) { - if (hwfeatures_inititalized) { - hwFeatures_finalize(); - hwfeatures_inititalized = 0; - } - return 0; -} -static int lua_likwid_getHwFeatureList(lua_State *L) { - if (!hwfeatures_inititalized) { - lua_newtable(L); +static int +lua_likwid_nvSupported(lua_State *L) +{ + lua_pushboolean(L, likwid_getNvidiaSupport()); return 1; - } - HWFeatureList list = {0, NULL}; - hwFeatures_list(&list); - lua_newtable(L); - for (int i = 0; i < list.num_features; i++) { - lua_pushinteger(L, (lua_Integer)(i + 1)); - lua_newtable(L); - lua_pushstring(L, "Name"); - lua_pushstring(L, list.features[i].name); - lua_settable(L, -3); - lua_pushstring(L, "Description"); - lua_pushstring(L, list.features[i].description); - lua_settable(L, -3); - lua_pushstring(L, "ReadOnly"); - lua_pushboolean(L, list.features[i].readonly); - lua_settable(L, -3); - lua_pushstring(L, "WriteOnly"); - lua_pushboolean(L, list.features[i].writeonly); - lua_settable(L, -3); - lua_pushstring(L, "Scope"); - lua_pushstring(L, HWFeatureScopeNames[list.features[i].scope]); - lua_settable(L, -3); - lua_settable(L, -3); - } - hwFeatures_list_return(&list); - return 1; -} - -static int lua_likwid_getHwFeature(lua_State *L) { - if (hwfeatures_inititalized) { - char *feature = (char *)luaL_checkstring(L, 1); - int hwt = luaL_checknumber(L, 2); - uint64_t value = 0; - int err = hwFeatures_getByName(feature, hwt, &value); - if (err == 0) { - lua_pushinteger(L, value); - return 1; - } - } - lua_pushnil(L); - return 1; } -static int lua_likwid_setHwFeature(lua_State *L) { - if (hwfeatures_inititalized) { - char *feature = (char *)luaL_checkstring(L, 1); - int hwt = luaL_checknumber(L, 2); - int value = luaL_checknumber(L, 3); - int err = hwFeatures_modifyByName(feature, hwt, value); - if (err == 0) { - lua_pushboolean(L, 1); - return 1; - } - } - lua_pushboolean(L, 0); - return 1; -} #ifdef LIKWID_WITH_ROCMON @@ -3778,12 +3695,199 @@ static int lua_likwid_finalize_rocm(lua_State *L) { #else + +#endif /* LIKWID_WITH_ROCMON */ + static int lua_likwid_rocmSupported(lua_State *L) { - lua_pushboolean(L, FALSE); + lua_pushboolean(L, likwid_getRocmSupport()); return 1; } -#endif /* LIKWID_WITH_ROCMON */ + +#ifdef LIKWID_WITH_SYSFEATURES +static int sysfeatures_inititalized = 0; +static int +lua_likwid_initSysFeatures(lua_State *L) +{ + int err = 0; + if (!sysfeatures_inititalized) + { + err = sysFeatures_init(); + if (err == 0) + { + sysfeatures_inititalized = 1; + } + } + lua_pushnumber(L, err); + return 1; +} + +static int +lua_likwid_finalizeSysFeatures(lua_State *L) +{ + if (sysfeatures_inititalized) + { + sysFeatures_finalize(); + sysfeatures_inititalized = 0; + } +} + +static int +lua_likwid_getSysFeatureList(lua_State *L) +{ + if (!sysfeatures_inititalized) + { + lua_newtable(L); + return 1; + } + SysFeatureList list = {0, NULL}; + sysFeatures_list(&list); + lua_newtable(L); + for (int i = 0; i < list.num_features; i++) + { + lua_pushinteger(L, (lua_Integer)( i+1)); + lua_newtable(L); + lua_pushstring(L, "Name"); + lua_pushstring(L, list.features[i].name); + lua_settable(L,-3); + lua_pushstring(L, "Category"); + lua_pushstring(L, list.features[i].category); + lua_settable(L,-3); + lua_pushstring(L, "Description"); + lua_pushstring(L, list.features[i].description); + lua_settable(L,-3); + lua_pushstring(L, "ReadOnly"); + lua_pushboolean(L, list.features[i].readonly); + lua_settable(L,-3); + lua_pushstring(L, "WriteOnly"); + lua_pushboolean(L, list.features[i].writeonly); + lua_settable(L,-3); + lua_pushstring(L, "Type"); + lua_pushstring(L, LikwidDeviceTypeNames[list.features[i].type]); + lua_settable(L,-3); + lua_pushstring(L, "TypeID"); + lua_pushinteger(L, list.features[i].type); + lua_settable(L,-3); + lua_settable(L,-3); + } + sysFeatures_list_return(&list); + return 1; +} + +static int +lua_likwid_getSysFeature(lua_State *L) +{ + if (sysfeatures_inititalized) + { + char* feature = (char *)luaL_checkstring(L, 1); + LikwidDevice_t dev = lua_touserdata(L, 2); + char* value = NULL; + int err = sysFeatures_getByName(feature, dev, &value); + if (err == 0) + { + lua_pushstring(L, value); + return 1; + } + } + lua_pushnil(L); + return 1; +} + +static int +lua_likwid_setSysFeature(lua_State *L) +{ + if (sysfeatures_inititalized) + { + char* feature = (char *)luaL_checkstring(L, 1); + LikwidDevice_t dev = lua_touserdata(L, 2); + char* value = (char *)luaL_checkstring(L,3); + int err = sysFeatures_modifyByName(feature, dev, value); + if (err == 0) + { + lua_pushboolean(L, 1); + return 1; + } + } + lua_pushboolean(L, 0); + return 1; +} + +static int +lua_likwid_createDevice(lua_State *L) +{ + LikwidDevice_t dev = NULL; + int err = 0; + int type = luaL_checknumber(L,1); + int id = luaL_checknumber(L,2); + LikwidDeviceType _type = DEVICE_TYPE_INVALID; + if ((!(((type) >= MIN_DEVICE_TYPE) && ((type) < MAX_DEVICE_TYPE))) || (id < 0)) + { + lua_pushnil(L); + } + else + { + err = likwid_device_create(type, id, &dev); + if (err < 0) + { + lua_pushnil(L); + } + else + { + dev = lua_newuserdata (L, sizeof(_LikwidDevice)); + dev->type = type; + dev->internal_id = id; + switch (dev->type) + { + case DEVICE_TYPE_HWTHREAD: + case DEVICE_TYPE_CORE: + case DEVICE_TYPE_DIE: + case DEVICE_TYPE_LLC: + case DEVICE_TYPE_NUMA: + case DEVICE_TYPE_SOCKET: + dev->id.simple.id = id; + break; +#ifdef LIKWID_WITH_NVMON + case DEVICE_TYPE_NVIDIA_GPU: +#endif +#ifdef LIKWID_WITH_ROCMON + case DEVICE_TYPE_AMD_GPU: +#endif +#if defined(LIKWID_WITH_NVMON)||defined(LIKWID_WITH_ROCMON) + dev->id.pci.pci_domain = SYSFEATURES_ID_TO_PCI_DOMAIN(id); + dev->id.pci.pci_bus = SYSFEATURES_ID_TO_PCI_BUS(id); + dev->id.pci.pci_dev = SYSFEATURES_ID_TO_PCI_SLOT(id); + dev->id.pci.pci_func = SYSFEATURES_ID_TO_PCI_FUNC(id); + break; +#endif + default: + lua_pushnil(L); + break; + } + } + } + return 1; +} + +static int +lua_likwid_destroyDevice(lua_State *L) +{ + LikwidDevice_t dev = lua_touserdata(L, 1); + if (dev) + { + dev->type = DEVICE_TYPE_INVALID; + dev->id.simple.id = -1; + dev->internal_id = -1; + } + return 0; +} +#endif /* LIKWID_WITH_SYSFEATURES */ + +static int +lua_likwid_sysFeaturesSupported(lua_State *L) +{ + lua_pushnumber(L, likwid_getSysFeaturesSupport()); + return 1; +} /* ##### FUNCTION DEFINITIONS - EXPORTED FUNCTIONS ################## */ @@ -4021,11 +4125,17 @@ int __attribute__((visibility("default"))) luaopen_liblikwid(lua_State *L) { lua_register(L, "likwid_markerRegionMetric_rocm", lua_likwid_markerRegionMetric_rocm); #endif /* LIKWID_WITH_ROCMON */ - lua_register(L, "likwid_initHWFeatures", lua_likwid_initHWFeatures); - lua_register(L, "likwid_finalizeHWFeatures", lua_likwid_finalizeHWFeatures); - lua_register(L, "likwid_hwFeatures_list", lua_likwid_getHwFeatureList); - lua_register(L, "likwid_hwFeatures_get", lua_likwid_getHwFeature); - lua_register(L, "likwid_hwFeatures_set", lua_likwid_setHwFeature); + // sysFeatures functions (experimental) + lua_register(L, "likwid_sysFeaturesSupported",lua_likwid_sysFeaturesSupported); +#ifdef LIKWID_WITH_SYSFEATURES + lua_register(L, "likwid_initSysFeatures", lua_likwid_initSysFeatures); + lua_register(L, "likwid_finalizeSysFeatures", lua_likwid_finalizeSysFeatures); + lua_register(L, "likwid_sysFeatures_list",lua_likwid_getSysFeatureList); + lua_register(L, "likwid_sysFeatures_get",lua_likwid_getSysFeature); + lua_register(L, "likwid_sysFeatures_set",lua_likwid_setSysFeature); + lua_register(L, "likwid_createDevice",lua_likwid_createDevice); + lua_register(L, "likwid_destroyDevice",lua_likwid_destroyDevice); +#endif /* LIKWID_WITH_SYSFEATURES */ #ifdef __MIC__ setuid(0); seteuid(0); diff --git a/src/meta.c b/src/meta.c index ff81d2778..31db62afa 100644 --- a/src/meta.c +++ b/src/meta.c @@ -45,3 +45,12 @@ int likwid_getMaxSupportedSockets(void) { return (int) MAX_NUM_NODES; } + +int likwid_getSysFeaturesSupport(void) +{ +#ifdef LIKWID_WITH_SYSFEATURES + return 1; +#else + return 0; +#endif +} diff --git a/src/sysFeatures.c b/src/sysFeatures.c new file mode 100644 index 000000000..9f2234eaf --- /dev/null +++ b/src/sysFeatures.c @@ -0,0 +1,339 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//#include + +_SysFeature *local_features = NULL; +int num_local_features = 0; + +_SysFeatureList _feature_list = {0, NULL, NULL}; + + +static int get_device_access(LikwidDevice_t device) +{ + int hwt = -1; + CpuTopology_t topo = NULL; + int err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + + if (device->type == DEVICE_TYPE_INVALID) + { + return -EINVAL; + } + switch (device->type) { + case DEVICE_TYPE_HWTHREAD: + if (device->id.simple.id >= 0 && device->id.simple.id < topo->numHWThreads) + { + hwt = device->id.simple.id; + } + break; + case DEVICE_TYPE_NODE: + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->inCpuSet == 1) + { + hwt = t->apicId; + break; + } + } + break; + case DEVICE_TYPE_SOCKET: + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->inCpuSet == 1 && device->id.simple.id == t->packageId) + { + hwt = t->apicId; + break; + } + } + break; + } + if (hwt >= 0) + { + return HPMaddThread(hwt); + } + return -EINVAL; +} + + +int sysFeatures_init() +{ + int err = 0; + + topology_init(); + CpuInfo_t cpuinfo = get_cpuInfo(); + if (!HPMinitialized()) + { + err = HPMinit(); + if (err < 0) + { + ERROR_PRINT(Failed to initialize access to hardware registers); + return err; + } + } + if (cpuinfo->isIntel) + { + err = sysFeatures_init_x86_intel(&_feature_list); + if (err < 0) + { + ERROR_PRINT(Failed to initialize SysFeatures for Intel architecture); + return err; + } + } + else + { + //err = sysFeatures_init_x86_amd(&num_features, &features); + if (err < 0) + { + ERROR_PRINT(Failed to initialize SysFeatures for AMD architecture); + return err; + } + } + + err = sysFeatures_init_cpufreq(&_feature_list); + if (err < 0) + { + ERROR_PRINT(Failed to initialize SysFeatures cpufreq module); + return err; + } + + err = sysFeatures_init_linux_numa_balancing(&_feature_list); + if (err < 0) + { + ERROR_PRINT(Failed to initialize SysFeatures numa_balancing module); + return err; + } + + err = sysFeatures_init_linux_numa_balancing(&_feature_list); + if (err < 0) + { + ERROR_PRINT(Failed to initialize SysFeatures numa_balancing module); + return err; + } + + DEBUG_PRINT(DEBUGLEV_DEVELOP, Initialized %d features, _feature_list.num_features); + return 0; +} + +static int _sysFeatures_get_feature_index(char* name) +{ + int dot = -1; + if (!name) + { + return -EINVAL; + } + int namelen = strlen(name); + for (int i = 0; i < namelen; i++) + { + if (name[i] == '.') + { + dot = i; + break; + } + } + if (dot < 0) + { + int out = -1; + DEBUG_PRINT(DEBUGLEV_DEVELOP, Features name has no dot -> compare with name, dot); + for (int i = 0; i < _feature_list.num_features; i++) + { + int featlen = strlen(_feature_list.features[i].name); + int checklen = (namelen < featlen ? featlen : namelen); + if (strncmp(name, _feature_list.features[i].name, checklen) == 0) + { + if (out < 0) + { + out = i; + } + else + { + ERROR_PRINT(Feature name '%s' matches multiple features, name); + return -EINVAL; + } + } + } + if (out >= 0) + { + return out; + } + } + else + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Features name contains dot at offset %d -> compare with category.name, dot); + for (int i = 0; i < _feature_list.num_features; i++) + { + int featlen = strlen(_feature_list.features[i].name) + strlen(_feature_list.features[i].category) + 2; + char real[featlen]; + int ret = snprintf(real, featlen, "%s.%s", _feature_list.features[i].category, _feature_list.features[i].name); + if (ret > 0) + { + real[ret] = '\0'; + int checklen = (namelen < featlen ? featlen : namelen); + DEBUG_PRINT(DEBUGLEV_DEVELOP, Comparing '%s' to '%s': %d, name, real, strncmp(name, real, checklen)); + if (strncmp(name, real, checklen) == 0) + { + return i; + } + } + } + } + ERROR_PRINT(SysFeatures modules does not provide a feature called %s, name); + return -ENOTSUP; +} + + + +int sysFeatures_getByName(char* name, LikwidDevice_t device, char** value) +{ + int err = 0; + _SysFeature *f = NULL; + if ((!name) || (!device) || (!value)) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Invalid inputs to sysFeatures_getByName); + return -EINVAL; + } + if (device->type == DEVICE_TYPE_INVALID) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Invalid device type); + return -EINVAL; + } + int idx = _sysFeatures_get_feature_index(name); + if (idx < 0) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Failed to get index for %s, name); + return -EINVAL; + } + f = &_feature_list.features[idx]; + if ((!f) || (!f->getter)) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, No feature %s or no support to read current state, name); + return -EINVAL; + } + if (f->type != device->type) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Feature %s has a different type than device, name); + return -EINVAL; + } + err = get_device_access(device); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Failed to get access to device); + return err; + } + err = f->getter(device, value); + return err; +} + +int sysFeatures_get(SysFeature* feature, LikwidDevice_t device, char** value) +{ + int len = strlen(feature->name) + strlen(feature->category) + 2; + char real[len]; + int ret = snprintf(real, len, "%s.%s", feature->category, feature->name); + return sysFeatures_getByName(real, device, value); +} + +int sysFeatures_modifyByName(char* name, LikwidDevice_t device, char* value) +{ + int err = 0; + int dev_id = -1; + _SysFeature *f = NULL; + if ((!name) || (!device) || (!value)) + { + return -EINVAL; + } + if (device->type == DEVICE_TYPE_INVALID) + { + return -EINVAL; + } + int idx = _sysFeatures_get_feature_index(name); + if (idx < 0) + { + return -EINVAL; + } + f = &_feature_list.features[idx]; + if ((!f) || (!f->setter)) + { + return -EPERM; + } + if (f->type != device->type) + { + return -ENODEV; + } + + err = get_device_access(device); + if (err < 0) + { + return err; + } + return f->setter(device, value); +} + +int sysFeatures_modify(SysFeature* feature, LikwidDevice_t device, char* value) +{ + int len = strlen(feature->name) + strlen(feature->category) + 2; + char real[len]; + int ret = snprintf(real, len, "%s.%s", feature->category, feature->name); + return sysFeatures_modifyByName(feature->name, device, value); +} + +void sysFeatures_finalize() +{ + if (local_features != NULL) + { + free(local_features); + local_features = NULL; + num_local_features = 0; + } + if (_feature_list.num_features > 0) + { + _free_feature_list(&_feature_list); + } + +} + +int sysFeatures_list(SysFeatureList* list) +{ + if (!list) + { + return -EINVAL; + } + return internal_to_external_feature_list(&_feature_list, list); +} + +void sysFeatures_list_return(SysFeatureList* list) +{ + if (!list || !list->features) + { + return; + } + free_feature_list(list); +/* for (int i = 0; i < list->num_features; i++)*/ +/* {*/ +/* SysFeature* f = &(list->features[i]);*/ +/* if (f->name) free(f->name);*/ +/* if (f->category) free(f->category);*/ +/* if (f->description) free(f->description);*/ +/* }*/ +/* free(list->features);*/ + list->features = NULL; + list->num_features = 0; +} diff --git a/src/sysFeatures_amd_rapl.c b/src/sysFeatures_amd_rapl.c new file mode 100644 index 000000000..009b552aa --- /dev/null +++ b/src/sysFeatures_amd_rapl.c @@ -0,0 +1,1061 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct { + double powerUnit; + double energyUnit; + double timeUnit; +} AmdRaplDomainInfo; + +AmdRaplDomainInfo amd_rapl_pkg_info = {0, 0, 0}; +AmdRaplDomainInfo amd_rapl_core_info = {0, 0, 0}; +AmdRaplDomainInfo amd_rapl_l3_info = {0, 0, 0}; + +static int amd_rapl_register_test(uint32_t reg) +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, reg, &data); + if (err == 0) valid++; + break; + } + } + } + return valid == topo->numSockets; +} + +static int amd_rapl_register_test_bit(uint32_t reg, int bitoffset) +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, reg, &data); + if (err == 0 && (data & (1ULL<numSockets; +} + +static int sysFeatures_amd_rapl_energy_status_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 32, 0); + data = (uint64_t)(((double)data) * info->energyUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_1_enable_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t newdata = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + newdata = (data >> 15) & 0x1; + return _uint64_to_string(newdata, value); +} + +static int sysFeatures_amd_rapl_energy_limit_1_enable_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 15); + data |= ((limit & 0x1ULL) << 15); + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 16) & 0x1ULL; + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 16); + data |= ((limit & 0x1ULL) << 16); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_energy_limit_1_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 0); + data = (uint64_t)(((double)data) * info->powerUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_1_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (reg == 0x0) || (!info) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x7FFF); + limit = (uint64_t)(((double)limit) / info->powerUnit); + data |= (limit & 0x7FFF); + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + + return 0; +} + +static int sysFeatures_amd_rapl_energy_limit_1_time_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + uint64_t y = extractBitField(data, 5, 17); + uint64_t z = extractBitField(data, 2, 22); + data = 0x0ULL; + data = (1 << y) * info->timeUnit; + data *= (uint64_t)((1.0 + (((double)z) / 4.0))); + //data = (uint64_t)(((double)data) * amd_rapl_pkg_info.timeUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_1_time_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t time = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = _string_to_uint64(value, &time); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + time = (uint64_t)(((double)time) / info->timeUnit); + uint64_t y = (uint64_t)(log2(((double)time))); + if (y > 0x1F) + y = 0x7F; + uint64_t o = (1 << y); + uint64_t z = (4 * (time - o)) / o; + time = (y & 0x1F) | ((z & 0x3) << 5); + + data &= ~(0x7F << 17); + data |= (time << 17); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_energy_limit_2_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 32); + data = (uint64_t)(((double)data) * info->powerUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_2_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (reg == 0x0) || (!info) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x7FFF << 15); + limit = (uint64_t)(((double)limit) / info->powerUnit); + data |= (limit << 15); + + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + + return 0; +} + +static int sysFeatures_amd_rapl_energy_limit_2_time_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + uint64_t y = extractBitField(data, 5, 49); + uint64_t z = extractBitField(data, 2, 54); + data = 0x0ULL; + data = (1 << y) * info->timeUnit; + data *= (uint64_t)((1.0 + (((double)z) / 4.0))); + //data = (uint64_t)(((double)data) * amd_rapl_pkg_info.timeUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_2_time_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t time = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = _string_to_uint64(value, &time); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + time = (uint64_t)(((double)time) / info->timeUnit); + uint64_t y = (uint64_t)(log2(((double)time))); + if (y > 0x1F) + y = 0x7F; + uint64_t o = (1 << y); + uint64_t z = (4 * (time - o)) / o; + time = (y & 0x1F) | ((z & 0x3) << 5); + + data &= ~(0x7FULL << 49); + data |= (time << 49); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_energy_limit_2_enable_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 47) & 0x1ULL; + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_2_enable_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 47); + data |= ((limit & 0x1ULL) << 47); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 48) & 0x1; + + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value, uint32_t reg, AmdRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 48); + data |= ((limit & 0x1) << 48); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_amd_rapl_info_tdp(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 0); + data = (uint64_t)(((double)data) * amd_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_info_min_power(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 16); + data = (uint64_t)(((double)data) * amd_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_info_max_power(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 32); + data = (uint64_t)(((double)data) * 100000 * amd_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_info_max_time(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 7, 48); + data = (uint64_t)(((double)data) * amd_rapl_pkg_info.timeUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_policy_getter(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 5, 0); + return _uint64_to_string(data, value); +} + +static int sysFeatures_amd_rapl_policy_setter(LikwidDevice_t device, char* value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t policy = 0x0ULL; + err = _string_to_uint64(value, &policy); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x1F); + data |= policy; + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + return 0; +} + + +/*********************************************************************************************************************/ +/* Amd RAPL (PKG domain) */ +/*********************************************************************************************************************/ + +int amd_rapl_pkg_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_AMD17_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (amd_rapl_pkg_info.powerUnit == 0 && amd_rapl_pkg_info.energyUnit == 0 && amd_rapl_pkg_info.timeUnit == 0) + { + amd_rapl_pkg_info.powerUnit = 1000000 / (1 << (data & 0xF)); + amd_rapl_pkg_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + amd_rapl_pkg_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + return valid == topo->numSockets; +} + +/*int amd_rapl_pkg_limit_test_lock()*/ +/*{*/ +/* return amd_rapl_register_test_bit(MSR_PKG_RAPL_POWER_LIMIT, 63);*/ +/*}*/ + + +int sysFeatures_amd_pkg_energy_status_test() +{ + return amd_rapl_register_test(MSR_AMD17_RAPL_PKG_STATUS); +} + + +int sysFeatures_amd_pkg_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_amd_rapl_energy_status_getter(device, value, MSR_AMD17_RAPL_PKG_STATUS, &amd_rapl_pkg_info); +} + +/*int sysFeatures_amd_pkg_energy_limit_test()*/ +/*{*/ +/* return amd_rapl_register_test(MSR_PKG_RAPL_POWER_LIMIT);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_energy_limit_1_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_time_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_time_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_enable_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_enable_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ + + + +/*int sysFeatures_amd_pkg_energy_limit_2_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_time_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_time_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_time_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_time_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_enable_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_enable_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_enable_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_enable_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_clamp_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ +/*int sysFeatures_amd_pkg_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_clamp_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &amd_rapl_pkg_info);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_info_test()*/ +/*{*/ +/* return amd_rapl_register_test(MSR_PKG_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_info_tdp(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_tdp(device, value, MSR_PKG_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_info_min_power(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_min_power(device, value, MSR_PKG_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_info_max_power(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_max_power(device, value, MSR_PKG_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_pkg_info_max_time(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_max_time(device, value, MSR_PKG_POWER_INFO);*/ +/*}*/ + + +/*********************************************************************************************************************/ +/* AMD RAPL (CORE domain) */ +/*********************************************************************************************************************/ + +int amd_rapl_core_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0x0; + HWThread* t = &topo->threadPool[j]; + err = HPMread(t->apicId, MSR_DEV, MSR_AMD17_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (amd_rapl_core_info.powerUnit == 0 && amd_rapl_core_info.energyUnit == 0 && amd_rapl_core_info.timeUnit == 0) + { + amd_rapl_core_info.powerUnit = 1000000 / (1 << (data & 0xF)); + amd_rapl_core_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + amd_rapl_core_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + return valid == topo->numHWThreads; +} + + +int sysFeatures_amd_core_energy_status_test() +{ + return amd_rapl_register_test(MSR_AMD17_RAPL_CORE_STATUS); +} + +int sysFeatures_amd_core_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_amd_rapl_energy_status_getter(device, value, MSR_AMD17_RAPL_CORE_STATUS, &amd_rapl_core_info); +} + +/*int sysFeatures_amd_core_energy_limit_test()*/ +/*{*/ +/* return amd_rapl_register_test(MSR_DRAM_RAPL_POWER_LIMIT);*/ +/*}*/ +/*int amd_rapl_core_limit_test_lock()*/ +/*{*/ +/* return amd_rapl_register_test_bit(MSR_DRAM_RAPL_POWER_LIMIT, 31);*/ +/*}*/ + + +/*int sysFeatures_amd_core_energy_limit_1_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_time_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_time_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_enable_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_enable_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ +/*int sysFeatures_amd_core_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &amd_rapl_core_info);*/ +/*}*/ + +/*int sysFeatures_amd_core_info_test()*/ +/*{*/ +/* return amd_rapl_register_test(MSR_DRAM_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_core_info_tdp(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_tdp(device, value, MSR_DRAM_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_core_info_min_power(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_min_power(device, value, MSR_DRAM_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_core_info_max_power(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_max_power(device, value, MSR_DRAM_POWER_INFO);*/ +/*}*/ + +/*int sysFeatures_amd_core_info_max_time(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_info_max_time(device, value, MSR_DRAM_POWER_INFO);*/ +/*}*/ + + +/*********************************************************************************************************************/ +/* AMD RAPL (L3 domain) */ +/*********************************************************************************************************************/ + +int amd_rapl_l3_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + if (info->family == ZEN3_FAMILY && (info->model == ZEN4_RYZEN || info->model == ZEN4_EPYC)) + { + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_AMD19_RAPL_L3_UNIT, &data); + if (err == 0) valid++; + if (amd_rapl_l3_info.powerUnit == 0 && amd_rapl_l3_info.energyUnit == 0 && amd_rapl_l3_info.timeUnit == 0) + { + amd_rapl_l3_info.powerUnit = 1000000 / (1 << (data & 0xF)); + amd_rapl_l3_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + amd_rapl_l3_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + } + return valid == topo->numSockets; +} + + +int sysFeatures_amd_l3_energy_status_test() +{ + return amd_rapl_register_test(MSR_AMD19_RAPL_L3_STATUS); +} + + +int sysFeatures_amd_l3_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_amd_rapl_energy_status_getter(device, value, MSR_AMD19_RAPL_L3_STATUS, &amd_rapl_l3_info); +} + +/*int sysFeatures_amd_l3_energy_limit_test()*/ +/*{*/ +/* return amd_rapl_register_test(MSR_PLATFORM_POWER_LIMIT);*/ +/*}*/ +/*int amd_rapl_l3_limit_test_lock()*/ +/*{*/ +/* return amd_rapl_register_test_bit(MSR_PLATFORM_POWER_LIMIT, 63);*/ +/*}*/ + +/*int sysFeatures_amd_l3_energy_limit_1_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_time_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_time_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_time_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_enable_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_enable_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_enable_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_1_clamp_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ + + +/*int sysFeatures_amd_l3_energy_limit_2_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_time_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_time_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_time_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_time_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_enable_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_enable_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_enable_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_enable_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_clamp_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ +/*int sysFeatures_amd_l3_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value)*/ +/*{*/ +/* return sysFeatures_amd_rapl_energy_limit_2_clamp_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &amd_rapl_l3_info);*/ +/*}*/ + + +/* Init function */ + +int sysFeatures_init_amd_rapl(_SysFeatureList* out) +{ + int err = 0; + if (amd_rapl_pkg_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Amd RAPL PKG domain); + err = register_features(out, &amd_rapl_pkg_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain PKG not supported); + } + } + if (amd_rapl_core_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Amd RAPL CORE domain); + err = register_features(out, &amd_rapl_core_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain CORE not supported); + } + } + if (amd_rapl_l3_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Amd RAPL L3 domain); + err = register_features(out, &amd_rapl_l3_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain L3 not supported); + } + } + return 0; +} diff --git a/src/sysFeatures_common.c b/src/sysFeatures_common.c new file mode 100644 index 000000000..b25e51752 --- /dev/null +++ b/src/sysFeatures_common.c @@ -0,0 +1,142 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int register_features(_SysFeatureList *features, _SysFeatureList* in) +{ + int err = 0; + if (in->tester) + { + if (!in->tester()) + { + return -ENOTSUP; + } + } + for (int i = 0; i < in->num_features; i++) + { + _SysFeature *f = &in->features[i]; + DEBUG_PRINT(DEBUGLEV_DEVELOP, Registering feature %s.%s, f->category, f->name); + if (f->tester) + { + if (f->tester()) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Running test for feature %s.%s, f->category, f->name); + err = _add_to_feature_list(features, f); + if (err < 0) + { + ERROR_PRINT(Failed to add HW feature %s.%s to feature list, f->category, f->name); + } + } + else + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Test function for feature %s.%s failed, f->category, f->name); + } + } + else + { + err = _add_to_feature_list(features, f); + if (err < 0) + { + ERROR_PRINT(Failed to add HW feature %s.%s to feature list, f->category, f->name); + } + } + } + return 0; +} + +int sysFeatures_init_generic(_HWArchFeatures* infeatures, _SysFeatureList *list) +{ + int i = 0; + int j = 0; + int c = 0; + int err = 0; + CpuInfo_t cpuinfo = NULL; + _SysFeatureList** feature_list = NULL; + _SysFeature* out = NULL; + err = topology_init(); + if (err < 0) + { + ERROR_PRINT(Failed to initialize topology module); + return err; + } + cpuinfo = get_cpuInfo(); + + c = 0; + while (infeatures[c].family >= 0 && infeatures[c].model >= 0) + { + if (infeatures[c].family == cpuinfo->family && infeatures[c].model == cpuinfo->model) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Using feature list for CPU family 0x%X and model 0x%X, cpuinfo->family, cpuinfo->model); + feature_list = infeatures[c].features; + break; + } + c++; + } + if (!feature_list) + { + ERROR_PRINT(No feature list found for current architecture); + return -ENOTSUP; + } + + j = 0; + //_SysFeatureList newlist = {0, NULL, NULL}; + while (feature_list[j] != NULL) + { + register_features(list, feature_list[j]); + j++; + } + return 0; +} + + + + +int _uint64_to_string(uint64_t value, char** str) +{ + char* s = malloc(HWFEATURES_MAX_STR_LENGTH * sizeof(char)); + if (!s) + { + return -ENOMEM; + } + int len = snprintf(s, HWFEATURES_MAX_STR_LENGTH-1, "%lld", (uint64_t) value); + if (len >= 0) + { + s[len] = '\0'; + *str = s; + return 0; + } + ERROR_PRINT(Conversion of uint64_t %lld failed: %s, value, strerror(errno)); + return len; +} + +int _string_to_uint64(char* str, uint64_t* value) +{ + char* ptr = NULL; + if ((strncmp(str, "true", 4) == 0) || (strncmp(str, "TRUE", 4) == 0)) + { + *value = 0x1ULL; + return 0; + } + else if ((strncmp(str, "false", 5) == 0) || (strncmp(str, "FALSE", 5) == 0)) + { + *value = 0x0ULL; + return 0; + } + errno = 0; + uint64_t v = strtoull(str, &ptr, 10); + if (v == 0 && errno != 0) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Conversion of string '%s' to uint64_t failed %d: %s, str, v, strerror(errno)); + return -errno; + } + *value = v; + return 0; +} diff --git a/src/sysFeatures_cpufreq.c b/src/sysFeatures_cpufreq.c new file mode 100644 index 000000000..465770e86 --- /dev/null +++ b/src/sysFeatures_cpufreq.c @@ -0,0 +1,259 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +static int cpufreq_sysfs_getter(LikwidDevice_t device, char** value, char* sysfs_filename) +{ + int err = 0; + if ((!device) || (!value) || (!sysfs_filename) || (device->type != DEVICE_TYPE_HWTHREAD)) + { + return -EINVAL; + } + bstring filename = bformat("/sys/devices/system/cpu/cpu%d/cpufreq/%s", device->id.simple.id, sysfs_filename); + if (!access(bdata(filename), R_OK)) + { + bstring content = read_file(bdata(filename)); + if (blength(content) > 0) + { + btrimws(content); + char* v = malloc((blength(content)+1) * sizeof(char)); + if (v) + { + strncpy(v, bdata(content), blength(content)); + v[blength(content)] = '\0'; + *value = v; + } + else + { + err = -ENOMEM; + } + bdestroy(content); + } + } + else + { + err = errno; + } + bdestroy(filename); + return err; +} + +static int cpufreq_sysfs_setter(LikwidDevice_t device, char* value, char* sysfs_filename) +{ + int err = 0; + if ((!device) || (!value) || (!sysfs_filename) || (device->type != DEVICE_TYPE_HWTHREAD)) + { + return -EINVAL; + } + int vallen = strlen(value); + bstring filename = bformat("/sys/devices/system/cpu/cpu%d/cpufreq/%s", device->id.simple.id, sysfs_filename); + errno = 0; + if (!access(bdata(filename), R_OK)) + { + FILE* fp = NULL; + errno = 0; + fp = fopen(bdata(filename), "w"); + if (fp == NULL) { + err = -errno; + ERROR_PRINT("Failed to open file '%s' for writing: %s", bdata(filename), strerror(errno)) + } + else + { + int ret = fwrite(value, sizeof(char), vallen, fp); + if (ret != (sizeof(char) * vallen)) + { + ERROR_PRINT("Failed to open file '%s' for writing: %s", bdata(filename), strerror(errno)) + } + fclose(fp); + } + } + else + { + err = -errno; + } + bdestroy(filename); + return err; +} + + +static int cpufreq_driver_test(char* testgovernor) +{ + int err = 0; + bstring btest = bfromcstr(testgovernor); + topology_init(); + CpuTopology_t topo = get_cpuTopology(); + + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->inCpuSet) + { + bstring filename = bformat("/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", t->apicId); + if (!access(bdata(filename), R_OK)) + { + bstring content = read_file(bdata(filename)); + btrimws(content); + err = (bstrncmp(content, btest, blength(btest)) == BSTR_OK); + bdestroy(content); + } + bdestroy(filename); + break; + } + } + return err; +} + +/* ACPI CPUfreq driver */ + +int cpufreq_acpi_cur_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_cur_freq"); +} + +int cpufreq_acpi_min_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_min_freq"); +} + +int cpufreq_acpi_max_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_max_freq"); +} + +int cpufreq_acpi_avail_cpu_freqs_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_available_frequencies"); +} + +int cpufreq_acpi_governor_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_governor"); +} + +int cpufreq_acpi_governor_setter(LikwidDevice_t device, char* value) +{ + return cpufreq_sysfs_setter(device, value, "scaling_governor"); +} + +int cpufreq_acpi_avail_governors_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_available_governors"); +} + +int cpufreq_acpi_test() +{ + return cpufreq_driver_test("acpi_cpufreq"); +} + + +/* Intel Pstate driver */ + +int cpufreq_intel_pstate_base_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "base_frequency"); +} + +int cpufreq_intel_pstate_cur_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_cur_freq"); +} + +int cpufreq_intel_pstate_min_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_min_freq"); +} + +int cpufreq_intel_pstate_max_cpu_freq_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_max_freq"); +} + +int cpufreq_intel_pstate_governor_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_governor"); +} + +int cpufreq_intel_pstate_governor_setter(LikwidDevice_t device, char* value) +{ + return cpufreq_sysfs_setter(device, value, "scaling_governor"); +} + +int cpufreq_intel_pstate_avail_governors_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "scaling_available_governors"); +} + +int cpufreq_intel_pstate_test() +{ + return cpufreq_driver_test("intel_pstate"); +} + + +/* Energy Performance Preference */ + +int cpufreq_epp_test() +{ + if ((!access("/sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference", R_OK)) && + (!access("/sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences", R_OK))) + { + return 1; + } + return 0; +} + +int cpufreq_intel_pstate_epp_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "energy_performance_preference"); +} + +int cpufreq_intel_pstate_avail_epps_getter(LikwidDevice_t device, char** value) +{ + return cpufreq_sysfs_getter(device, value, "energy_performance_available_preferences"); +} + +/* Init function */ + +int sysFeatures_init_cpufreq(_SysFeatureList* out) +{ + int err = 0; + if (cpufreq_intel_pstate_test()) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Registering Intel Pstate knobs for cpufreq) + err = register_features(out, &cpufreq_pstate_feature_list); + if (err < 0) + { + return err; + } + } + else if (cpufreq_acpi_test()) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Registering ACPI cpufreq knobs for cpufreq) + register_features(out, &cpufreq_acpi_feature_list); + if (err < 0) + { + return err; + } + } + + if (cpufreq_epp_test()) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Registering Energy Performance Preference knobs for cpufreq) + err = register_features(out, &cpufreq_epp_feature_list); + if (err < 0) + { + return err; + } + } + return 0; +} diff --git a/src/sysFeatures_intel.c b/src/sysFeatures_intel.c new file mode 100644 index 000000000..07067d9ed --- /dev/null +++ b/src/sysFeatures_intel.c @@ -0,0 +1,125 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +int sysFeatures_init_x86_intel(_SysFeatureList* out) +{ + int err = 0; + err = sysFeatures_init_generic(intel_arch_features, out); + if (err < 0) + { + ERROR_PRINT(Failed to init general Intel HWFetures); + return err; + } + err = sysFeatures_init_intel_rapl(out); + if (err < 0) + { + ERROR_PRINT(Failed to init Intel RAPL HWFetures); + return err; + } + + return 0; +} + +int intel_cpu_msr_register_getter(LikwidDevice_t device, uint32_t reg, uint64_t mask, uint64_t shift, int invert, char** value) +{ + int err = 0; + if (device->type != DEVICE_TYPE_HWTHREAD) + { + return -ENODEV; + } + uint64_t data = 0x0; + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err == 0) + { + uint64_t _val = 0x0; + if (!invert) + { + _val = (data & mask) >> shift; + } + else + { + _val = !((data & mask) >> shift); + } + return _uint64_to_string(_val, value); + } + return err; +} + +int intel_cpu_msr_register_setter(LikwidDevice_t device, uint32_t reg, uint64_t mask, uint64_t shift, int invert, char* value) +{ + int err = 0; + if (device->type != DEVICE_TYPE_HWTHREAD) + { + return -ENODEV; + } + uint64_t data = 0x0ULL; + uint64_t _val = 0x0ULL; + err = _string_to_uint64(value, &_val); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err == 0) + { + data &= ~(mask); + if (invert) + { + data |= (((!_val) << shift) & mask); + } + else + { + data |= ((_val << shift) & mask); + } + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + } + return err; +} + + + +/* Intel Turbo */ +int intel_cpu_turbo_test() +{ + unsigned eax = 0x01, ebx, ecx, edx; + CPUID(eax, ebx, ecx, edx); + if (((ecx >> 7) & 0x1) == 0) + { + DEBUG_PRINT(DEBUGLEV_DEVELOP, Intel SpeedStep not supported by architecture); + return 0; + } + return 1; +} + +int intel_cpu_turbo_getter(LikwidDevice_t device, char** value) +{ + if (intel_cpu_turbo_test()) + { + return intel_cpu_msr_register_getter(device, MSR_IA32_MISC_ENABLE, (1ULL<<36), 36, 1, value); + } + return -ENOTSUP; +} + +int intel_cpu_turbo_setter(LikwidDevice_t device, char* value) +{ + if (intel_cpu_turbo_test()) + { + return intel_cpu_msr_register_setter(device, MSR_IA32_MISC_ENABLE, (1ULL<<36), 36, 1, value); + } + return -ENOTSUP; +} diff --git a/src/sysFeatures_intel_prefetcher.c b/src/sysFeatures_intel_prefetcher.c new file mode 100644 index 000000000..1a8569229 --- /dev/null +++ b/src/sysFeatures_intel_prefetcher.c @@ -0,0 +1,163 @@ +#include +#include +#include + +#include +#include +#include +#include + +/*********************************************************************************************************************/ +/* Intel prefetchers */ +/*********************************************************************************************************************/ +int intel_cpu_l2_hwpf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x1, 0, 1, value); +} + +int intel_cpu_l2_hwpf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x1, 0, 1, value); +} + +int intel_cpu_l2_adj_pf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x2, 1, 1, value); +} + +int intel_cpu_l2_adj_pf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x2, 1, 1, value); +} + +int intel_cpu_l1_dcu_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x4, 3, 1, value); +} + +int intel_cpu_l1_dcu_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x4, 3, 1, value); +} + +int intel_cpu_l1_dcu_ip_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x8, 4, 1, value); +} + +int intel_cpu_l1_dcu_ip_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x8, 4, 1, value); +} + + +/*********************************************************************************************************************/ +/* Intel 0x8F prefetchers */ +/*********************************************************************************************************************/ + +int intel_cpu_l2_multipath_pf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x20, 6, 1, value); +} + +int intel_cpu_l2_multipath_pf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x20, 6, 1, value); +} + + +/*********************************************************************************************************************/ +/* Intel Knights Landing prefetchers */ +/*********************************************************************************************************************/ +int intel_knl_l1_dcu_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x1, 0, 1, value); +} + +int intel_knl_l1_dcu_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x1, 0, 1, value); +} + +int intel_knl_l2_hwpf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, 0x2, 1, 1, value); +} + +int intel_knl_l2_hwpf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, 0x2, 1, 1, value); +} + + +/*********************************************************************************************************************/ +/* Intel Core2 prefetchers */ +/*********************************************************************************************************************/ + +int intel_core2_l2_hwpf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_MISC_ENABLE, (1ULL<<9), 9, 1, value); +} + +int intel_core2_l2_hwpf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_IA32_MISC_ENABLE, (1ULL<<9), 9, 1, value); +} + +int intel_core2_l2_adjpf_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_MISC_ENABLE, (1ULL<<19), 19, 1, value); +} + +int intel_core2_l2_adjpf_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_IA32_MISC_ENABLE, (1ULL<<19), 19, 1, value); +} + +int intel_core2_l1_dcu_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, (1ULL<<37), 37, 1, value); +} + +int intel_core2_l1_dcu_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, (1ULL<<37), 37, 1, value); +} + +int intel_core2_l1_dcu_ip_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, (1ULL<<39), 39, 1, value); +} + +int intel_core2_l1_dcu_ip_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, (1ULL<<39), 39, 1, value); +} + +/*********************************************************************************************************************/ +/* Intel Dynamic Acceleration */ +/*********************************************************************************************************************/ + +int intel_core2_ida_tester() +{ + unsigned eax = 0x06, ebx, ecx, edx; + CPUID(eax, ebx, ecx, edx); + return ((eax >> 1) & 0x1); +} + +int intel_core2_ida_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_PREFETCH_ENABLE, (1ULL<<38), 38, 1, value); +} + +int intel_core2_ida_setter(LikwidDevice_t device, char* value) +{ + return intel_cpu_msr_register_setter(device, MSR_PREFETCH_ENABLE, (1ULL<<38), 38, 1, value); +} + +/* Init function */ + +int sysFeatures_init_intel_prefetchers(_SysFeatureList* out) +{ + return 0; +} diff --git a/src/sysFeatures_intel_rapl.c b/src/sysFeatures_intel_rapl.c new file mode 100644 index 000000000..586f340ed --- /dev/null +++ b/src/sysFeatures_intel_rapl.c @@ -0,0 +1,1360 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct { + double powerUnit; + double energyUnit; + double timeUnit; +} IntelRaplDomainInfo; + +IntelRaplDomainInfo intel_rapl_pkg_info = {0, 0, 0}; +IntelRaplDomainInfo intel_rapl_dram_info = {0, 0, 0}; +IntelRaplDomainInfo intel_rapl_psys_info = {0, 0, 0}; +IntelRaplDomainInfo intel_rapl_pp0_info = {0, 0, 0}; +IntelRaplDomainInfo intel_rapl_pp1_info = {0, 0, 0}; + +static int intel_rapl_register_test(uint32_t reg) +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, reg, &data); + if (err == 0) valid++; + break; + } + } + } + return valid == topo->numSockets; +} + +static int intel_rapl_register_test_bit(uint32_t reg, int bitoffset) +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, reg, &data); + if (err == 0 && (data & (1ULL<numSockets; +} + +static int sysFeatures_intel_rapl_energy_status_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 32, 0); + data = (uint64_t)(((double)data) * info->energyUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_1_enable_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t newdata = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + newdata = (data >> 15) & 0x1; + return _uint64_to_string(newdata, value); +} + +static int sysFeatures_intel_rapl_energy_limit_1_enable_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 15); + data |= ((limit & 0x1ULL) << 15); + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 16) & 0x1ULL; + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 16); + data |= ((limit & 0x1ULL) << 16); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_energy_limit_1_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 0); + data = (uint64_t)(((double)data) * info->powerUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_1_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (reg == 0x0) || (!info) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x7FFF); + limit = (uint64_t)(((double)limit) / info->powerUnit); + data |= (limit & 0x7FFF); + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + + return 0; +} + +static int sysFeatures_intel_rapl_energy_limit_1_time_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + uint64_t y = extractBitField(data, 5, 17); + uint64_t z = extractBitField(data, 2, 22); + data = 0x0ULL; + data = (1 << y) * info->timeUnit; + data *= (uint64_t)((1.0 + (((double)z) / 4.0))); + //data = (uint64_t)(((double)data) * intel_rapl_pkg_info.timeUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_1_time_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t time = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = _string_to_uint64(value, &time); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + time = (uint64_t)(((double)time) / info->timeUnit); + uint64_t y = (uint64_t)(log2(((double)time))); + if (y > 0x1F) + y = 0x7F; + uint64_t o = (1 << y); + uint64_t z = (4 * (time - o)) / o; + time = (y & 0x1F) | ((z & 0x3) << 5); + + data &= ~(0x7F << 17); + data |= (time << 17); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_energy_limit_2_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 32); + data = (uint64_t)(((double)data) * info->powerUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_2_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (reg == 0x0) || (!info) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x7FFF << 15); + limit = (uint64_t)(((double)limit) / info->powerUnit); + data |= (limit << 15); + + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + + return 0; +} + +static int sysFeatures_intel_rapl_energy_limit_2_time_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + uint64_t y = extractBitField(data, 5, 49); + uint64_t z = extractBitField(data, 2, 54); + data = 0x0ULL; + data = (1 << y) * info->timeUnit; + data *= (uint64_t)((1.0 + (((double)z) / 4.0))); + //data = (uint64_t)(((double)data) * intel_rapl_pkg_info.timeUnit); + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_2_time_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t time = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = _string_to_uint64(value, &time); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + time = (uint64_t)(((double)time) / info->timeUnit); + uint64_t y = (uint64_t)(log2(((double)time))); + if (y > 0x1F) + y = 0x7F; + uint64_t o = (1 << y); + uint64_t z = (4 * (time - o)) / o; + time = (y & 0x1F) | ((z & 0x3) << 5); + + data &= ~(0x7FULL << 49); + data |= (time << 49); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_energy_limit_2_enable_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 47) & 0x1ULL; + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_2_enable_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 47); + data |= ((limit & 0x1ULL) << 47); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = (data >> 48) & 0x1; + + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value, uint32_t reg, IntelRaplDomainInfo* info) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t limit = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = _string_to_uint64(value, &limit); + if (err < 0) + { + return err; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(1ULL << 48); + data |= ((limit & 0x1) << 48); + + return HPMwrite(device->id.simple.id, MSR_DEV, reg, data); +} + +static int sysFeatures_intel_rapl_info_tdp(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 0); + data = (uint64_t)(((double)data) * intel_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_info_min_power(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 16); + data = (uint64_t)(((double)data) * intel_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_info_max_power(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 15, 32); + data = (uint64_t)(((double)data) * 100000 * intel_rapl_pkg_info.powerUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_info_max_time(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 7, 48); + data = (uint64_t)(((double)data) * intel_rapl_pkg_info.timeUnit); + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_policy_getter(LikwidDevice_t device, char** value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data = extractBitField(data, 5, 0); + return _uint64_to_string(data, value); +} + +static int sysFeatures_intel_rapl_policy_setter(LikwidDevice_t device, char* value, uint32_t reg) +{ + int err = 0; + uint64_t data = 0x0ULL; + uint64_t policy = 0x0ULL; + err = _string_to_uint64(value, &policy); + if (err < 0) + { + return err; + } + err = HPMread(device->id.simple.id, MSR_DEV, reg, &data); + if (err < 0) + { + return err; + } + data &= ~(0x1F); + data |= policy; + err = HPMwrite(device->id.simple.id, MSR_DEV, reg, data); + if (err < 0) + { + return err; + } + return 0; +} + + +/*********************************************************************************************************************/ +/* Intel RAPL (PKG domain) */ +/*********************************************************************************************************************/ + +int intel_rapl_pkg_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (intel_rapl_pkg_info.powerUnit == 0 && intel_rapl_pkg_info.energyUnit == 0 && intel_rapl_pkg_info.timeUnit == 0) + { + intel_rapl_pkg_info.powerUnit = 1000000 / (1 << (data & 0xF)); + intel_rapl_pkg_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + intel_rapl_pkg_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + return valid == topo->numSockets; +} + +int intel_rapl_pkg_limit_test_lock() +{ + return intel_rapl_register_test_bit(MSR_PKG_RAPL_POWER_LIMIT, 63); +} + + +int sysFeatures_intel_pkg_energy_status_test() +{ + return intel_rapl_register_test(MSR_PKG_ENERGY_STATUS); +} + + +int sysFeatures_intel_pkg_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_status_getter(device, value, MSR_PKG_ENERGY_STATUS, &intel_rapl_pkg_info); +} + +int sysFeatures_intel_pkg_energy_limit_test() +{ + return intel_rapl_register_test(MSR_PKG_RAPL_POWER_LIMIT); +} + +int sysFeatures_intel_pkg_energy_limit_1_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} + + + +int sysFeatures_intel_pkg_energy_limit_2_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_time_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_time_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_enable_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_enable_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_clamp_getter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} +int sysFeatures_intel_pkg_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_clamp_setter(device, value, MSR_PKG_RAPL_POWER_LIMIT, &intel_rapl_pkg_info); +} + +int sysFeatures_intel_pkg_info_test() +{ + return intel_rapl_register_test(MSR_PKG_POWER_INFO); +} + +int sysFeatures_intel_pkg_info_tdp(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_tdp(device, value, MSR_PKG_POWER_INFO); +} + +int sysFeatures_intel_pkg_info_min_power(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_min_power(device, value, MSR_PKG_POWER_INFO); +} + +int sysFeatures_intel_pkg_info_max_power(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_max_power(device, value, MSR_PKG_POWER_INFO); +} + +int sysFeatures_intel_pkg_info_max_time(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_max_time(device, value, MSR_PKG_POWER_INFO); +} + + +/*********************************************************************************************************************/ +/* Intel RAPL (DRAM domain) */ +/*********************************************************************************************************************/ + +int intel_rapl_dram_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (intel_rapl_dram_info.powerUnit == 0 && intel_rapl_dram_info.energyUnit == 0 && intel_rapl_dram_info.timeUnit == 0) + { + intel_rapl_dram_info.powerUnit = 1000000 / (1 << (data & 0xF)); + intel_rapl_dram_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + intel_rapl_dram_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + if ((info->model == HASWELL_EP) || + (info->model == HASWELL_M1) || + (info->model == HASWELL_M2) || + (info->model == BROADWELL_D) || + (info->model == BROADWELL_E) || + (info->model == SKYLAKEX) || + (info->model == ICELAKEX1) || + (info->model == ICELAKEX2) || + (info->model == SAPPHIRERAPIDS) || + (info->model == XEON_PHI_KNL) || + (info->model == XEON_PHI_KML)) + { + intel_rapl_dram_info.energyUnit = 15.3E-6; + } + } + break; + } + } + } + return valid == topo->numSockets; +} + + +int sysFeatures_intel_dram_energy_status_test() +{ + return intel_rapl_register_test(MSR_DRAM_ENERGY_STATUS); +} + +int sysFeatures_intel_dram_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_status_getter(device, value, MSR_DRAM_ENERGY_STATUS, &intel_rapl_dram_info); +} + +int sysFeatures_intel_dram_energy_limit_test() +{ + return intel_rapl_register_test(MSR_DRAM_RAPL_POWER_LIMIT); +} +int intel_rapl_dram_limit_test_lock() +{ + return intel_rapl_register_test_bit(MSR_DRAM_RAPL_POWER_LIMIT, 31); +} + + +int sysFeatures_intel_dram_energy_limit_1_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_getter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} +int sysFeatures_intel_dram_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_setter(device, value, MSR_DRAM_RAPL_POWER_LIMIT, &intel_rapl_dram_info); +} + +int sysFeatures_intel_dram_info_test() +{ + return intel_rapl_register_test(MSR_DRAM_POWER_INFO); +} + +int sysFeatures_intel_dram_info_tdp(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_tdp(device, value, MSR_DRAM_POWER_INFO); +} + +int sysFeatures_intel_dram_info_min_power(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_min_power(device, value, MSR_DRAM_POWER_INFO); +} + +int sysFeatures_intel_dram_info_max_power(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_max_power(device, value, MSR_DRAM_POWER_INFO); +} + +int sysFeatures_intel_dram_info_max_time(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_info_max_time(device, value, MSR_DRAM_POWER_INFO); +} + + +/*********************************************************************************************************************/ +/* Intel RAPL (PSYS or PLATFORM domain) */ +/*********************************************************************************************************************/ + +int intel_rapl_psys_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (intel_rapl_psys_info.powerUnit == 0 && intel_rapl_psys_info.energyUnit == 0 && intel_rapl_psys_info.timeUnit == 0) + { + intel_rapl_psys_info.powerUnit = 1000000 / (1 << (data & 0xF)); + intel_rapl_psys_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + if (info->model == SAPPHIRERAPIDS) + { + intel_rapl_psys_info.energyUnit = 1000000000; + } + intel_rapl_psys_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + return valid == topo->numSockets; +} + + +int sysFeatures_intel_psys_energy_status_test() +{ + return intel_rapl_register_test(MSR_PLATFORM_ENERGY_STATUS); +} + + +int sysFeatures_intel_psys_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_status_getter(device, value, MSR_PLATFORM_ENERGY_STATUS, &intel_rapl_psys_info); +} + +int sysFeatures_intel_psys_energy_limit_test() +{ + return intel_rapl_register_test(MSR_PLATFORM_POWER_LIMIT); +} +int intel_rapl_psys_limit_test_lock() +{ + return intel_rapl_register_test_bit(MSR_PLATFORM_POWER_LIMIT, 63); +} + +int sysFeatures_intel_psys_energy_limit_1_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} + + +int sysFeatures_intel_psys_energy_limit_2_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_time_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_time_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_enable_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_enable_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_2_clamp_getter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} +int sysFeatures_intel_psys_energy_limit_2_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_2_clamp_setter(device, value, MSR_PLATFORM_POWER_LIMIT, &intel_rapl_psys_info); +} + +/*********************************************************************************************************************/ +/* Intel RAPL (PP0 domain) */ +/*********************************************************************************************************************/ + +int intel_rapl_pp0_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (intel_rapl_pp0_info.powerUnit == 0 && intel_rapl_pp0_info.energyUnit == 0 && intel_rapl_pp0_info.timeUnit == 0) + { + intel_rapl_pp0_info.powerUnit = 1000000 / (1 << (data & 0xF)); + intel_rapl_pp0_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + intel_rapl_pp0_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + return valid == topo->numSockets; +} + + +int sysFeatures_intel_pp0_energy_status_test() +{ + return intel_rapl_register_test(MSR_PP0_ENERGY_STATUS); +} + + +int sysFeatures_intel_pp0_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_status_getter(device, value, MSR_PP0_ENERGY_STATUS, &intel_rapl_pp0_info); +} + +int sysFeatures_intel_pp0_energy_limit_test() +{ + return intel_rapl_register_test(MSR_PP0_RAPL_POWER_LIMIT); +} +int intel_rapl_pp0_limit_test_lock() +{ + return intel_rapl_register_test_bit(MSR_PP0_RAPL_POWER_LIMIT, 31); +} + +int sysFeatures_intel_pp0_energy_limit_1_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_getter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_setter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_getter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_setter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_getter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_setter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_getter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} +int sysFeatures_intel_pp0_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_setter(device, value, MSR_PP0_RAPL_POWER_LIMIT, &intel_rapl_pp0_info); +} + + +int sysFeatures_intel_pp0_policy_test() +{ + return intel_rapl_register_test(MSR_PP0_ENERGY_POLICY); +} +int sysFeatures_intel_pp0_policy_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_policy_getter(device, value, MSR_PP0_ENERGY_POLICY); +} +int sysFeatures_intel_pp0_policy_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_policy_setter(device, value, MSR_PP0_ENERGY_POLICY); +} + + +/*********************************************************************************************************************/ +/* Intel RAPL (PP1 domain) */ +/*********************************************************************************************************************/ + +int intel_rapl_pp1_test() +{ + int err = 0; + int valid = 0; + CpuTopology_t topo = NULL; + CpuInfo_t info = NULL; + + err = topology_init(); + if (err < 0) + { + return 0; + } + topo = get_cpuTopology(); + info = get_cpuInfo(); + for (int i = 0; i < topo->numSockets; i++) + { + for (int j = 0; j < topo->numHWThreads; j++) + { + uint64_t data = 0; + HWThread* t = &topo->threadPool[j]; + if (t->packageId == i) + { + err = HPMread(t->apicId, MSR_DEV, MSR_RAPL_POWER_UNIT, &data); + if (err == 0) valid++; + if (intel_rapl_pp1_info.powerUnit == 0 && intel_rapl_pp1_info.energyUnit == 0 && intel_rapl_pp1_info.timeUnit == 0) + { + intel_rapl_pp1_info.powerUnit = 1000000 / (1 << (data & 0xF)); + intel_rapl_pp1_info.energyUnit = 1.0 / (1 << ((data >> 8) & 0x1F)); + intel_rapl_pp1_info.timeUnit = 1000000 / (1 << ((data >> 16) & 0xF)); + } + break; + } + } + } + return valid == topo->numSockets; +} + + +int sysFeatures_intel_pp1_energy_status_test() +{ + return intel_rapl_register_test(MSR_PP1_ENERGY_STATUS); +} + +int sysFeatures_intel_pp1_energy_status_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_status_getter(device, value, MSR_PP1_ENERGY_STATUS, &intel_rapl_pp1_info); +} + +int sysFeatures_intel_pp1_energy_limit_test() +{ + return intel_rapl_register_test(MSR_PP1_RAPL_POWER_LIMIT); +} +int intel_rapl_pp1_limit_test_lock() +{ + return intel_rapl_register_test_bit(MSR_PP1_RAPL_POWER_LIMIT, 31); +} + +int sysFeatures_intel_pp1_energy_limit_1_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_getter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_setter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_time_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_getter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_time_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_time_setter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_enable_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_getter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_enable_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_enable_setter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_clamp_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_getter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} +int sysFeatures_intel_pp1_energy_limit_1_clamp_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_energy_limit_1_clamp_setter(device, value, MSR_PP1_RAPL_POWER_LIMIT, &intel_rapl_pp1_info); +} + + +int sysFeatures_intel_pp1_policy_test() +{ + return intel_rapl_register_test(MSR_PP1_ENERGY_POLICY); +} +int sysFeatures_intel_pp1_policy_getter(LikwidDevice_t device, char** value) +{ + return sysFeatures_intel_rapl_policy_getter(device, value, MSR_PP1_ENERGY_POLICY); +} +int sysFeatures_intel_pp1_policy_setter(LikwidDevice_t device, char* value) +{ + return sysFeatures_intel_rapl_policy_setter(device, value, MSR_PP1_ENERGY_POLICY); +} + + +/* Init function */ + +int sysFeatures_init_intel_rapl(_SysFeatureList* out) +{ + int err = 0; + if (intel_rapl_pkg_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Intel RAPL PKG domain); + if (intel_rapl_pkg_limit_test_lock() > 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, Intel RAPL PKG domain locked); + for (int i = 0; i < intel_rapl_pkg_feature_list.num_features; i++) + { + intel_rapl_pkg_feature_list.features[i].setter = NULL; + } + } + err = register_features(out, &intel_rapl_pkg_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain PKG not supported); + } + } + if (intel_rapl_dram_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Intel RAPL DRAM domain); + if (intel_rapl_dram_limit_test_lock() > 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, Intel RAPL DRAM domain locked); + for (int i = 0; i < intel_rapl_dram_feature_list.num_features; i++) + { + intel_rapl_dram_feature_list.features[i].setter = NULL; + } + } + err = register_features(out, &intel_rapl_dram_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain DRAM not supported); + } + } + if (intel_rapl_pp0_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Intel RAPL PP0 domain); + if (intel_rapl_pp0_limit_test_lock() > 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, Intel RAPL PP0 domain locked); + for (int i = 0; i < intel_rapl_pp0_feature_list.num_features; i++) + { + intel_rapl_pp0_feature_list.features[i].setter = NULL; + } + } + err = register_features(out, &intel_rapl_pp0_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain PP0 not supported); + } + } + if (intel_rapl_pp1_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Intel RAPL PP1 domain); + if (intel_rapl_pp1_limit_test_lock() > 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, Intel RAPL PP1 domain locked); + for (int i = 0; i < intel_rapl_pp1_feature_list.num_features; i++) + { + intel_rapl_pp1_feature_list.features[i].setter = NULL; + } + } + err = register_features(out, &intel_rapl_pp1_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain PP1 not supported); + } + } + if (intel_rapl_psys_test()) + { + DEBUG_PRINT(DEBUGLEV_INFO, Register Intel RAPL PSYS domain); + if (intel_rapl_psys_limit_test_lock() > 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, Intel RAPL PSYS domain locked); + for (int i = 0; i < intel_rapl_psys_feature_list.num_features; i++) + { + intel_rapl_psys_feature_list.features[i].setter = NULL; + } + } + err = register_features(out, &intel_rapl_psys_feature_list); + if (err < 0) + { + DEBUG_PRINT(DEBUGLEV_INFO, RAPL domain PSYS not supported); + } + } + return 0; +} diff --git a/src/sysFeatures_intel_spec_ctrl.c b/src/sysFeatures_intel_spec_ctrl.c new file mode 100644 index 000000000..880bae5b4 --- /dev/null +++ b/src/sysFeatures_intel_spec_ctrl.c @@ -0,0 +1,123 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + + +int intel_cpu_spec_ibrs_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 26); +} + +int intel_cpu_spec_ibrs_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x1, 0, 0, value); +} + + +int intel_cpu_spec_stibp_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 27); +} + +int intel_cpu_spec_stibp_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x2, 1, 0, value); +} + +int intel_cpu_spec_ssbd_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 31); +} + +int intel_cpu_spec_ssbd_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x4, 2, 1, value); +} + + +int intel_cpu_spec_ipred_dis_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0x02, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 1); +} + +int intel_cpu_spec_ipred_dis_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x8, 3, 0, value); +} + +int intel_cpu_spec_rrsba_dis_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0x02, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 2); +} + +int intel_cpu_spec_rrsba_dis_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x20, 5, 1, value); +} + +int intel_cpu_spec_psfd_tester() +{ + unsigned eax = 0x07, ebx = 0, edx = 0x02, ecx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 0); +} + +int intel_cpu_spec_psfd_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x80, 7, 1, value); +} + +int intel_cpu_spec_ddpd_tester() +{ + unsigned eax = 0x07, ebx = 0, ecx = 0x02, edx = 0; + CPUID(eax, ebx, ecx, edx); + return testBit(edx, 0); +} + +int intel_cpu_spec_ddpd_getter(LikwidDevice_t device, char** value) +{ + return intel_cpu_msr_register_getter(device, MSR_IA32_SPEC_CTRL, 0x100, 8, 1, value); +} + + +int intel_cpu_spec_ctrl() +{ + int valid = 0; + if (intel_cpu_spec_ibrs_tester()) valid++; + if (intel_cpu_spec_stibp_tester()) valid++; + if (intel_cpu_spec_ssbd_tester()) valid++; + if (intel_cpu_spec_ipred_dis_tester()) valid++; + if (intel_cpu_spec_rrsba_dis_tester()) valid++; + if (intel_cpu_spec_psfd_tester()) valid++; + if (intel_cpu_spec_ddpd_tester()) valid++; + if (valid == 0) + { + printf("Speculation control not available\n"); + } + return valid > 0; +} + +/* Init function */ + +int sysFeatures_init_intel_spec_ctrl(_SysFeatureList* out) +{ + return 0; +} diff --git a/src/sysFeatures_intel_uncorefreq.c b/src/sysFeatures_intel_uncorefreq.c new file mode 100644 index 000000000..3e0e5a651 --- /dev/null +++ b/src/sysFeatures_intel_uncorefreq.c @@ -0,0 +1,147 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int intel_uncorefreq_test() +{ + int err = 0; + CpuTopology_t topo = NULL; + + err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->inCpuSet) + { + uint64_t tmp = 0; + HPMaddThread(t->apicId); + err = HPMread(t->apicId, MSR_DEV, MSR_UNCORE_FREQ, &tmp); + if (err == 0) + { + err = HPMread(t->apicId, MSR_DEV, MSR_UNCORE_FREQ_READ, &tmp); + if (err == 0) + { + return 1; + } + else + { + ERROR_PRINT(Failed to access Uncore frequency current register); + } + } + else + { + ERROR_PRINT(Failed to access Uncore frequency min/max register); + } + break; + } + } + ERROR_PRINT(Failed to access Uncore frequency registers); + return 0; +} + +int intel_uncore_cur_freq_getter(LikwidDevice_t device, char** value) +{ + int err = 0; + CpuTopology_t topo = NULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->packageId == device->id.simple.id && t->inCpuSet) + { + uint64_t tmp = 0; + err = HPMread(t->apicId, MSR_DEV, MSR_UNCORE_FREQ_READ, &tmp); + if (err == 0) + { + tmp = (tmp & 0xFFULL) * 100; + return _uint64_to_string(tmp, value); + } + } + } + return -ENODEV; +} + +int intel_uncore_min_freq_getter(LikwidDevice_t device, char** value) +{ + int err = 0; + CpuTopology_t topo = NULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->packageId == device->id.simple.id && t->inCpuSet) + { + uint64_t tmp = 0; + err = HPMread(t->apicId, MSR_DEV, MSR_UNCORE_FREQ, &tmp); + if (err == 0) + { + tmp = ((tmp>>8) & 0xFFULL) * 100; + return _uint64_to_string(tmp, value); + } + } + } + return -ENODEV; +} + +int intel_uncore_max_freq_getter(LikwidDevice_t device, char** value) +{ + int err = 0; + CpuTopology_t topo = NULL; + if ((!device) || (!value) || (device->type != DEVICE_TYPE_SOCKET)) + { + return -EINVAL; + } + err = topology_init(); + if (err < 0) + { + return err; + } + topo = get_cpuTopology(); + for (int i = 0; i < topo->numHWThreads; i++) + { + HWThread* t = &topo->threadPool[i]; + if (t->packageId == device->id.simple.id && t->inCpuSet) + { + uint64_t tmp = 0; + err = HPMread(t->apicId, MSR_DEV, MSR_UNCORE_FREQ, &tmp); + if (err == 0) + { + tmp = (tmp & 0xFFULL) * 100;; + return _uint64_to_string(tmp, value); + } + } + } + return -ENODEV; +} + diff --git a/src/sysFeatures_linux_numa_balancing.c b/src/sysFeatures_linux_numa_balancing.c new file mode 100644 index 000000000..fc7a6c82d --- /dev/null +++ b/src/sysFeatures_linux_numa_balancing.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +int numa_balancing_procfs_getter(LikwidDevice_t device, char** value, char* sysfsfile) +{ + int err = 0; + if ((!device) || (!value) || (!sysfsfile) || (device->type != DEVICE_TYPE_NODE)) + { + return -EINVAL; + } + bstring filename = bformat("/proc/sys/kernel/%s", sysfsfile); + if (!access(bdata(filename), R_OK)) + { + bstring content = read_file(bdata(filename)); + if (blength(content) > 0) + { + btrimws(content); + char* v = malloc((blength(content)+1) * sizeof(char)); + if (v) + { + strncpy(v, bdata(content), blength(content)); + v[blength(content)] = '\0'; + *value = v; + } + else + { + err = -ENOMEM; + } + bdestroy(content); + } + } + else + { + err = errno; + } + bdestroy(filename); + return err; +} + +int numa_balancing_test() +{ + int err = access("/proc/sys/kernel/numa_balancing", F_OK); + if (err < 0) + { + return -errno; + } + if (err == 0) + { + topology_init(); + numa_init(); + NumaTopology_t topo = get_numaTopology(); + if (topo->numberOfNodes > 1) + { + return 1; + } + else + { + DEBUG_PRINT(DEBUGLEV_INFO, NUMA balancing not available. System has only a single NUMA domain); + } + } + return 0; +} + +int numa_balancing_state_getter(LikwidDevice_t device, char** value) +{ + return numa_balancing_procfs_getter(device, value, "numa_balancing"); +} +int numa_balancing_scan_delay_getter(LikwidDevice_t device, char** value) +{ + return numa_balancing_procfs_getter(device, value, "numa_balancing_scan_delay_ms"); +} +int numa_balancing_scan_period_min_getter(LikwidDevice_t device, char** value) +{ + return numa_balancing_procfs_getter(device, value, "numa_balancing_scan_period_min_ms"); +} +int numa_balancing_scan_period_max_getter(LikwidDevice_t device, char** value) +{ + return numa_balancing_procfs_getter(device, value, "numa_balancing_scan_period_max_ms"); +} +int numa_balancing_scan_size_getter(LikwidDevice_t device, char** value) +{ + return numa_balancing_procfs_getter(device, value, "numa_balancing_scan_size_mb"); +} + + +int sysFeatures_init_linux_numa_balancing(_SysFeatureList* out) +{ + if (numa_balancing_test()) + { + return register_features(out, &numa_balancing_feature_list); + } + return 0; +} diff --git a/src/sysFeatures_list.c b/src/sysFeatures_list.c new file mode 100644 index 000000000..ad04557fa --- /dev/null +++ b/src/sysFeatures_list.c @@ -0,0 +1,272 @@ +#include +#include + +#include +#include +#include +#include + +int add_to_feature_list(SysFeatureList *list, SysFeature* feature) +{ + if ((!list) || (!feature)) + { + ERROR_PRINT(Invalid arguments for add_to_feature_list); + return -EINVAL; + } + + SysFeature* flist = realloc(list->features, (list->num_features + 1) * sizeof(SysFeature)); + if (!flist) + { + ERROR_PRINT(Cannot allocate space for extended feature list); + return -ENOMEM; + } + list->features = flist; + + SysFeature* iof = &(list->features[list->num_features]); + iof->name = malloc((strlen(feature->name) + 1) * sizeof(char)); + if (!iof->name) + { + return -ENOMEM; + } + iof->category = malloc((strlen(feature->category) + 1) * sizeof(char)); + if (!iof->category) + { + free(iof->name); + return -ENOMEM; + } + iof->description = malloc((strlen(feature->description) + 1) * sizeof(char)); + if (!iof->description) + { + free(iof->name); + free(iof->category); + return -ENOMEM; + } + int slen = HWFEATURES_MIN_STRLEN(strlen(feature->name) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(iof->name, feature->name, slen); + slen = HWFEATURES_MIN_STRLEN(strlen(feature->category) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(iof->category, feature->category, slen); + slen = HWFEATURES_MIN_STRLEN(strlen(feature->description) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(iof->description, feature->description, slen); + + iof->readonly = feature->readonly; + iof->type = feature->type; + iof->writeonly = feature->writeonly; + + list->num_features++; + + return 0; +} + + +int merge_feature_lists(SysFeatureList *inout, SysFeatureList *in) +{ + if ((!inout) || (!in)) + { + ERROR_PRINT(Invalid arguments for merge_feature_lists); + return -EINVAL; + } + + SysFeature* flist = realloc(inout->features, (inout->num_features + in->num_features) * sizeof(SysFeature)); + if (!flist) + { + ERROR_PRINT(Cannot allocate space for extended feature list); + return -ENOMEM; + } + inout->features = flist; + + for (int i = 0; i < in->num_features; i++) + { + SysFeature* ifeat = &(in->features[i]); + add_to_feature_list(inout, ifeat); + } + + + return 0; +} + +void free_feature_list(SysFeatureList *list) +{ + if (list) + { + for (int i = 0; i < list->num_features; i++) + { + SysFeature* f = &(list->features[i]); + if (f->name) free(f->name); + if (f->category) free(f->category); + if (f->description) free(f->description); + } + memset(list->features, 0, list->num_features * sizeof(SysFeature)); + free(list->features); + list->features = NULL; + list->num_features = 0; + } +} + +int _add_to_feature_list(_SysFeatureList *list, _SysFeature* feature) +{ + if ((!list) || (!feature)) + { + ERROR_PRINT(Invalid arguments for _add_to_feature_list); + return -EINVAL; + } + + _SysFeature* flist = realloc(list->features, (list->num_features + 1) * sizeof(_SysFeature)); + if (!flist) + { + ERROR_PRINT(Cannot allocate space for extended feature list); + return -ENOMEM; + } + list->features = flist; + + _SysFeature* iof = &(list->features[list->num_features]); + iof->name = feature->name; + iof->category = feature->category; + iof->description = feature->description; + iof->type = feature->type; + iof->getter = feature->getter; + iof->setter = feature->setter; + + list->num_features++; + + return 0; +} + +int _merge_feature_lists(_SysFeatureList *inout, _SysFeatureList *in) +{ + if ((!inout) || (!in)) + { + ERROR_PRINT(Invalid arguments for _merge_feature_lists); + return -EINVAL; + } + + _SysFeature* flist = realloc(inout->features, (inout->num_features + in->num_features) * sizeof(_SysFeature)); + if (!flist) + { + ERROR_PRINT(Cannot allocate space for extended feature list); + return -ENOMEM; + } + inout->features = flist; + + for (int i = 0; i < in->num_features; i++) + { + _SysFeature* ifeat = &(in->features[i]); + _SysFeature* iof = &(inout->features[inout->num_features + i]); + + iof->name = ifeat->name; + iof->category = ifeat->category; + iof->description = ifeat->description; + iof->type = ifeat->type; + iof->getter = ifeat->getter; + iof->setter = ifeat->setter; + iof->tester = ifeat->tester; + } + inout->num_features += in->num_features; + + return 0; +} + +void _free_feature_list(_SysFeatureList *list) +{ + if (list) + { + memset(list->features, 0, list->num_features * sizeof(_SysFeature)); + free(list->features); + list->features = NULL; + list->tester = NULL; + list->num_features = 0; + } +} + + +int internal_to_external_feature_list(_SysFeatureList *inlist, SysFeatureList* outlist) +{ + if ((!inlist) || (!outlist)) + { + ERROR_PRINT(Invalid arguments for internal_to_external_feature_list); + return -EINVAL; + } + outlist->num_features = 0; + outlist->features = NULL; + + outlist->features = malloc(inlist->num_features * sizeof(SysFeature)); + if (!outlist->features) + { + return -ENOMEM; + } + + for (int i = 0; i < inlist->num_features; i++) + { + SysFeature* out = &(outlist->features[i]); + _SysFeature* in = &(inlist->features[i]); + + out->name = malloc((strlen(in->name)+1) * sizeof(char)); + if (!out->name) + { + for (int j = 0; j < i; j++) + { + SysFeature* c = &(outlist->features[j]); + if (c->name) free(c->name); + if (c->category) free(c->category); + if (c->description) free(c->description); + } + free(outlist->features); + outlist->features = NULL; + return -ENOMEM; + } + out->category = malloc((strlen(in->category)+1) * sizeof(char)); + if (!out->category) + { + free(out->name); + for (int j = 0; j < i; j++) + { + SysFeature* c = &(outlist->features[j]); + if (c->name) free(c->name); + if (c->category) free(c->category); + if (c->description) free(c->description); + } + free(outlist->features); + outlist->features = NULL; + return -ENOMEM; + } + out->description = malloc((strlen(in->description)+1) * sizeof(char)); + if (!out->description) + { + free(out->name); + free(out->category); + for (int j = 0; j < i; j++) + { + SysFeature* c = &(outlist->features[j]); + if (c->name) free(c->name); + if (c->category) free(c->category); + if (c->description) free(c->description); + } + free(outlist->features); + outlist->features = NULL; + return -ENOMEM; + } + } + for (int i = 0; i < inlist->num_features; i++) + { + SysFeature* out = &(outlist->features[i]); + _SysFeature* in = &(inlist->features[i]); + int slen = HWFEATURES_MIN_STRLEN(strlen(in->name) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(out->name, in->name, slen); + slen = HWFEATURES_MIN_STRLEN(strlen(in->category) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(out->category, in->category, slen); + slen = HWFEATURES_MIN_STRLEN(strlen(in->description) + 1, HWFEATURES_MAX_STR_LENGTH); + strncpy(out->description, in->description, slen); + out->type = in->type; + out->readonly = 0; + out->writeonly = 0; + if (in->getter != NULL && in->setter == NULL) + { + out->readonly = 1; + } + else if (in->getter == NULL && in->setter != NULL) + { + out->writeonly = 1; + } + outlist->num_features++; + } + return 0; +} diff --git a/test/Makefile b/test/Makefile index 2a7f3a613..71aeb6c13 100644 --- a/test/Makefile +++ b/test/Makefile @@ -36,6 +36,7 @@ targets: @echo " - testTBBGCC (Intel TBB test code compiled with GCC)" @echo " - testTBBICC (Intel TBB test code compiled with Intel C++ Compiler)" @echo " - triadCU (Vector triad benchmark code in CUDA implementation and NvMarkerAPI)" + @echo " - test_sysFeatures (Test experimental sysFeatures API if configured)" @echo "" @echo " - clean (Clean all compiled files)" @@ -109,6 +110,14 @@ streamCU: stream.cu triadCU: triad.cu nvcc -O3 -Xcompiler -fopenmp -I. $(LIKWID_INC) $(LIKWID_LIB) -DLIKWID_NVMON -Xcompiler -fopenmp triad.cu -o $@ -lm -llikwid +ifeq ($(BUILD_SYSFEATURES),true) +test_sysFeatures: test_sysFeatures.c + $(CC) -DLIKWID_WITH_SYSFEATURES -I../src/includes -L.. test_sysFeatures.c -o $@ -llikwid +else +test_sysFeatures: test_sysFeatures.c + @echo "Support for sysFeatures not enabled" +endif + .PHONY: clean distclean streamGCC streamICC streamGCC_C11 streamICC_C11 testmarker-cnt testmarker-omp testmarkerF90 test-mpi test-mpi-pthreads stream_cilk serial test-likwidAPI streamAPIGCC test-msr-access testTBBGCC testTBBICC jacobi-2D-5pt-icc jacobi-2D-5pt-gcc matmul_marker matmul marker_overhead clean: diff --git a/test/test_hwfeatures.c b/test/test_hwfeatures.c deleted file mode 100644 index f2001a037..000000000 --- a/test/test_hwfeatures.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include - - -int main(int argc, char* argv[]) -{ - int err = 0; - HWFeatureList list = {0, NULL}; - err = topology_init(); - if (err != 0) - { - printf("Error topology_init\n"); - return 1; - } - err = HPMinit(); - if (err != 0) - { - printf("Error HPMinit\n"); - return 1; - } - err = HPMaddThread(0); - if (err != 0) - { - printf("Error HPMaddThread\n"); - return 1; - } - err = hwFeatures_init(); - if (err != 0) - { - printf("Error hwfeatures_init\n"); - return 1; - } - err = hwFeatures_list(&list); - if (err != 0) - { - printf("Error hwfeatures_list\n"); - return 1; - } - //perfmon_setVerbosity(3); - for (int i = 0; i < list.num_features; i++) - { - uint64_t val = 0; - hwFeatures_get(&list.features[i], 0, &val); - printf("%s : %d\n", list.features[i].name, val); - /*uint64_t new = !val; - uint64_t newread = 0; - hwFeatures_modify(&list.features[i], 0, new); - hwFeatures_get(&list.features[i], 0, &newread); - printf("%s : %d\n", list.features[i].name, newread); - hwFeatures_modify(&list.features[i], 0, val);*/ - - } - //perfmon_setVerbosity(0); - hwFeatures_list_return(&list); - hwFeatures_finalize(); - HPMfinalize(); - return 0; -} diff --git a/test/test_sysFeatures.c b/test/test_sysFeatures.c new file mode 100644 index 000000000..3d83e283a --- /dev/null +++ b/test/test_sysFeatures.c @@ -0,0 +1,96 @@ +#include +#include + +#include + + +int main(int argc, char* argv[]) +{ + int err = 0; + SysFeatureList list = {0, NULL}; + err = topology_init(); + if (err != 0) + { + printf("Error topology_init\n"); + return 1; + } + err = HPMinit(); + if (err != 0) + { + printf("Error HPMinit\n"); + return 1; + } + err = HPMaddThread(0); + if (err != 0) + { + printf("Error HPMaddThread\n"); + return 1; + } + + err = sysFeatures_init(); + if (err != 0) + { + printf("Error sysFeatures_init\n"); + return 1; + } + err = sysFeatures_list(&list); + if (err != 0) + { + printf("Error sysFeatures_list\n"); + return 1; + } + printf("Feature list:\n"); + for (int i = 0; i < list.num_features; i++) + { + printf("- %s.%s (Type: %s)\n", list.features[i].category, list.features[i].name, device_type_name(list.features[i].type)); + } + printf("\n"); + LikwidDevice_t hwtdevice = NULL; + err = likwid_device_create(DEVICE_TYPE_HWTHREAD, 0, &hwtdevice); + if (err != 0) + { + printf("Error sysFeatures_create_device (hwt)\n"); + return 1; + } + LikwidDevice_t nodedevice = NULL; + err = likwid_device_create(DEVICE_TYPE_NODE, 0, &nodedevice); + if (err != 0) + { + printf("Error sysFeatures_create_device (node)\n"); + return 1; + } + LikwidDevice_t socketdevice = NULL; + err = likwid_device_create(DEVICE_TYPE_SOCKET, 0, &socketdevice); + if (err != 0) + { + printf("Error sysFeatures_create_device (socket)\n"); + return 1; + } + //perfmon_setVerbosity(3); + for (int i = 0; i < list.num_features; i++) + { + char* val = NULL; + if (list.features[i].type == DEVICE_TYPE_HWTHREAD) + sysFeatures_get(&list.features[i], hwtdevice, &val); + else if (list.features[i].type == DEVICE_TYPE_NODE) + sysFeatures_get(&list.features[i], nodedevice, &val); + else if (list.features[i].type == DEVICE_TYPE_SOCKET) + sysFeatures_get(&list.features[i], socketdevice, &val); + printf("%s.%s : %s\n", list.features[i].category, list.features[i].name, val); + /*uint64_t new = !val; + uint64_t newread = 0; + sysFeatures_modify(&list.features[i], 0, new); + sysFeatures_get(&list.features[i], 0, &newread); + printf("%s : %d\n", list.features[i].name, newread); + sysFeatures_modify(&list.features[i], 0, val);*/ + + } + perfmon_setVerbosity(0); + likwid_device_destroy(hwtdevice); + likwid_device_destroy(nodedevice); + likwid_device_destroy(socketdevice); + sysFeatures_list_return(&list); + sysFeatures_finalize(); + HPMfinalize(); + return 0; +}