8 Commits
9 changed files with 240 additions and 72 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
.PHONY : clean debug .PHONY : clean debug
OBJS = evga-icx.o evga-card.o icx3.o board-sensors.o OBJS = evga-icx.o evga-card.o icx3.o board-sensors.o zen3-rapl.o
LDLIBS = -li2c LDLIBS = -li2c -lm
CFLAGS = -MD CFLAGS = -MD
ifdef USE_NVML ifdef USE_NVML
+4
View File
@@ -36,6 +36,9 @@ Add the make flag `USE_NVML=1` and the it will also display the main GPU tempera
### VRAM and Hotspot temperature ### VRAM and Hotspot temperature
Add the make flag `USE_LIBPCI=1` and you can also read the VRAM and "hotspot" temperatures. These require direct memory access to the PCI device so you must run as root and also enable the kernel parameter `iomem=relaxed`. These sensors are **extremely** undocumented so I can't say anything about their accuracy. Add the make flag `USE_LIBPCI=1` and you can also read the VRAM and "hotspot" temperatures. These require direct memory access to the PCI device so you must run as root and also enable the kernel parameter `iomem=relaxed`. These sensors are **extremely** undocumented so I can't say anything about their accuracy.
### Hardware monitoring
This program can also monitor hardware sensors using the standard linux `hwmon` API. See board-sensors.h for examples of how to configure these, they must be staticlly compiled in.
## Usage ## Usage
Note that when controlling fans directly through iCX3 they will fall offline from the Nvidia driver and show as 0 RPM until you return them to automatic mode. Note that when controlling fans directly through iCX3 they will fall offline from the Nvidia driver and show as 0 RPM until you return them to automatic mode.
@@ -56,6 +59,7 @@ Available options:
--overwrite : Overwrite previously displayed info with --watch and --compact instead of continuously logging new lines --overwrite : Overwrite previously displayed info with --watch and --compact instead of continuously logging new lines
--color : Print headers in color in --compact mode for better readability --color : Print headers in color in --compact mode for better readability
--no-reasons : Do not query NVML for clock reasons (can cause stuttering) --no-reasons : Do not query NVML for clock reasons (can cause stuttering)
--board : Also print temperatures from the CPU, motherboard, and other sensors
``` ```
### Examples: ### Examples:
+32 -17
View File
@@ -1,3 +1,6 @@
#ifndef BOARD_SENSORS_H
#define BOARD_SENSORS_H
#include <stdio.h> #include <stdio.h>
#define MAX_SENSOR_NAME_LENGTH 256 #define MAX_SENSOR_NAME_LENGTH 256
@@ -15,23 +18,33 @@ struct hwmon_sensor {
/* Note the order here matters, it's the order these will be printed in */ /* Note the order here matters, it's the order these will be printed in */
static struct hwmon_sensor hwmon_sensor_info[] = static struct hwmon_sensor hwmon_sensor_info[] =
{ {
{"zenpower", "temp1", "CPU ", "CPU", "°C", 1000.0, -40.0}, /* Tdie */ {"zenpower", "temp1", "CPU ", "CPU", "°C", 1000.0, -40.0 }, /* Tdie */
{"asusec", "temp2", "Motherboard ", "CPU", "°C", 1000.0, -40.0}, /* CPU */ {"asusec", "temp2", "Motherboard ", "CPU", "°C", 1000.0, -40.0 }, /* CPU */
{"zenpower", "temp3", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd1 */ {"zenpower", "temp3", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd1 */
{"zenpower", "temp4", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd2 */ {"zenpower", "temp4", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd2 */
{"zenpower", "temp5", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd3 */ {"zenpower", "temp5", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd3 */
{"zenpower", "temp6", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd4 */ {"zenpower", "temp6", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd4 */
{"zenpower", "temp7", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd5 */ {"zenpower", "temp7", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd5 */
{"zenpower", "temp8", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd6 */ {"zenpower", "temp8", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd6 */
{"zenpower", "temp9", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd7 */ {"zenpower", "temp9", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd7 */
{"zenpower", "temp10", "CPU ", "CCD", "°C", 1000.0, -40.0}, /* Tccd8 */ {"zenpower", "temp10", "CPU ", "CCD", "°C", 1000.0, -40.0 }, /* Tccd8 */
{"asusec", "temp1", "Motherboard ", "CHIP", "°C", 1000.0, -40.0}, /* Chipset */ {"zen-rapl", "", "CPU ", "POW", " W", 0.0, 0.0 }, /* Zen RAPL placeholder */
{"asusec", "temp5", "Motherboard ", "VRM", "°C", 1000.0, -40.0}, /* VRM */ {"asusec", "temp1", "Motherboard ", "CHIP", "°C", 1000.0, -40.0 }, /* Chipset */
{"asusec", "temp3", "", "MOBO", "°C", 1000.0, -40.0}, /* Motherboard */ {"asusec", "temp5", "Motherboard ", "VRM", "°C", 1000.0, -40.0 }, /* VRM */
{"asusec", "temp4", "Motherboard ", "SENS", "°C", 1000.0, -40.0}, /* T_Sensor */ {"asusec", "temp3", "", "MOBO", "°C", 1000.0, -40.0 }, /* Motherboard */
{"asusec", "temp6", "Motherboard ", "H2O", "°C", 1000.0, -40.0}, /* Water_In */ {"asusec", "temp4", "Motherboard ", "SENS", "°C", 1000.0, -40.0 }, /* T_Sensor */
{"asusec", "temp7", "Motherboard ", "H2O", "°C", 1000.0, -40.0}, /* Water_Out */ {"asusec", "temp6", "Motherboard ", "H2O", "°C", 1000.0, -40.0 }, /* Water_In */
{"nvme", "temp1", "NVMe ", "NVME", "°C", 1000.0, -40.0}, /* NVME Composite */ {"asusec", "temp7", "Motherboard ", "H2O", "°C", 1000.0, -40.0 }, /* Water_Out */
{"nvme", "temp1", "NVMe ", "NVME", "°C", 1000.0, -40.0 }, /* NVME Composite */
{"nct6798", "fan2", "CPU fan", "CPU", "%", 15.0, 0.0 }, /* cpu_fan, cpu mid */
{"asusec", "fan1", "", "CPU", "%", 15.0, 0.0 }, /* cpu_opt, cpu front */
{"nct6798", "fan5", "H amp", "CHA", "%", 12.0, 0.0 }, /* h_amp, front fan */
{"nct6798", "fan3", "Chassis 2", "CHA", "%", 12.0, 0.0 }, /* cha2, top front */
{"nct6798", "fan1", "Chassis 1", "CHA", "%", 12.0, 0.0 }, /* cha1, top rear */
{"nct6798", "fan4", "Chassis 3", "CHA", "%", 13.0, 0.0 }, /* cha3, rear */
{"nct6798", "fan6", "AIO pump", "CHA", "%", 12.0, 0.0 }, /* aio_pump? */
{"nct6798", "fan7", "W pump", "CHA", "%", 12.0, 0.0 }, /* w_pump+? */
{"asusec", "fan2", "", "CHIP", "%", 35.0, 0.0 }, /* chipset */
}; };
struct hwmon_avail_sensor { struct hwmon_avail_sensor {
@@ -43,3 +56,5 @@ struct hwmon_avail_sensor {
int find_board_sensors(struct hwmon_avail_sensor *board_sensors, int max_sensors); int find_board_sensors(struct hwmon_avail_sensor *board_sensors, int max_sensors);
int get_sensor_reading(struct hwmon_avail_sensor *sensor, float *reading); int get_sensor_reading(struct hwmon_avail_sensor *sensor, float *reading);
#endif
+14 -9
View File
@@ -10,9 +10,10 @@
and respond with the correct iCX3 version information */ and respond with the correct iCX3 version information */
int find_evga_gpu_i2cs(struct card_info *infos, int max_gpus, int i2c_bus) int find_evga_gpu_i2cs(struct card_info *infos, int max_gpus, int i2c_bus)
{ {
char i2c_devices_path[NAME_MAX]; char i2c_devices_path[PATH_MAX];
char device_path[NAME_MAX]; char device_path[PATH_MAX];
char dev_file[NAME_MAX]; char dev_file[PATH_MAX];
char pci_path[PATH_MAX];
char *pci_addr; char *pci_addr;
FILE *test_fd; FILE *test_fd;
@@ -55,10 +56,14 @@ int find_evga_gpu_i2cs(struct card_info *infos, int max_gpus, int i2c_bus)
continue; continue;
/* Read the PCI info for the underlying device */ /* Read the PCI info for the underlying device */
pci_vendor = read_pci_id(device_path, "/device/vendor"); strcat(device_path, "/../");
pci_device = read_pci_id(device_path, "/device/device"); if (realpath(device_path, pci_path) == NULL)
pci_subsystem_vendor = read_pci_id(device_path, "/device/subsystem_vendor"); continue;
pci_subsystem_device = read_pci_id(device_path, "/device/subsystem_device");
pci_vendor = read_pci_id(pci_path, "/vendor");
pci_device = read_pci_id(pci_path, "/device");
pci_subsystem_vendor = read_pci_id(pci_path, "/subsystem_vendor");
pci_subsystem_device = read_pci_id(pci_path, "/subsystem_device");
/* See if it's a matching device for a supported EVGA card */ /* See if it's a matching device for a supported EVGA card */
for (int i = 0; i < (sizeof(evga_pci_ids) / sizeof(struct gpu_pci_info)); i++) { for (int i = 0; i < (sizeof(evga_pci_ids) / sizeof(struct gpu_pci_info)); i++) {
@@ -97,7 +102,7 @@ int find_evga_gpu_i2cs(struct card_info *infos, int max_gpus, int i2c_bus)
unsigned short read_pci_id(char *device_path, char *field) unsigned short read_pci_id(char *device_path, char *field)
{ {
char buf[16]; char buf[16];
char file_path[NAME_MAX]; char file_path[PATH_MAX];
strcpy(file_path, device_path); strcpy(file_path, device_path);
strcat(file_path, field); strcat(file_path, field);
@@ -119,7 +124,7 @@ unsigned short read_pci_id(char *device_path, char *field)
char *read_nvidia_pci_address(char *device_path) char *read_nvidia_pci_address(char *device_path)
{ {
char file_path[NAME_MAX]; char file_path[PATH_MAX];
char *ret = calloc(16 + 1, sizeof(char)); /* assuming pci ids could look as large as 00000000:0C:00.0 */ char *ret = calloc(16 + 1, sizeof(char)); /* assuming pci ids could look as large as 00000000:0C:00.0 */
+51 -26
View File
@@ -16,14 +16,19 @@
#include "icx3.h" #include "icx3.h"
#include "evga-card.h" #include "evga-card.h"
#include "board-sensors.h" #include "board-sensors.h"
#include "zen3-rapl.h"
#define MAX_GPUS 16 #define MAX_GPUS 16
#define MAX_BOARD_SENSORS 256 #define MAX_BOARD_SENSORS 256
#define HEADER_COLOR_START "\x1b[36m" #define HEADER_COLOR_START "\x1b[36m"
#define HEADER_COLOR_END "\x1b[39m" #define HEADER_COLOR_END "\x1b[39m"
char *header_start = ""; static char *header_start = "";
char *header_end = ""; static char *header_end = "";
static int zen3_rapl_sensor = -1; /* Board sensor number for the RAPL sensor */
static int compact = 0; /* Compact one-line per GPU display */
static int no_reasons = 0; /* Don't probe or display NVML clock reasons */
static const char helpstring[] = "Available options:\n" static const char helpstring[] = "Available options:\n"
"--i2c N : Only probe I2C bus N instead of all (may help with stuttering or freezing when probing I2C devices)\n" "--i2c N : Only probe I2C bus N instead of all (may help with stuttering or freezing when probing I2C devices)\n"
@@ -41,10 +46,10 @@ static const char helpstring[] = "Available options:\n"
"--overwrite : Overwrite previously displayed info with --watch and --compact instead of continuously logging\n" "--overwrite : Overwrite previously displayed info with --watch and --compact instead of continuously logging\n"
"--color : Print headers in color in --compact mode for better readability\n" "--color : Print headers in color in --compact mode for better readability\n"
"--no-reasons : Do not query NVML for clock reasons (can cause stuttering)\n" "--no-reasons : Do not query NVML for clock reasons (can cause stuttering)\n"
"--board : Also print temperatures from the CPU, motherboard, and other sensors"; "--board : Also print temperatures from the CPU, motherboard, and other sensors\n";
void print_gpu_info(int gpu_num, struct card_info gpus[], int compact, int no_reasons); void print_gpu_info(int gpu_num, struct card_info gpus[]);
void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors, int compact); void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors);
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
@@ -52,11 +57,9 @@ int main (int argc, char **argv)
struct hwmon_avail_sensor board_sensors[MAX_BOARD_SENSORS]; struct hwmon_avail_sensor board_sensors[MAX_BOARD_SENSORS];
int gpu_count, board_sensor_count; int gpu_count, board_sensor_count;
int print_info = 0; int print_info = 0;
int compact = 0;
int gpu_num = -1; /* Card to control */ int gpu_num = -1; /* Card to control */
int i2c_bus = -1; /* Specific i2c bus to probe instead of all */ int i2c_bus = -1; /* Specific i2c bus to probe instead of all */
int overwrite = 0; /* Overwrite printed console info in compact mode */ int overwrite = 0; /* Overwrite printed console info in compact mode */
int no_reasons = 0; /* Don't probe or display NVML clock reasons */
unsigned int watch = 0; /* Refresh display every this many seconds */ unsigned int watch = 0; /* Refresh display every this many seconds */
int print_board_sensors = 0; /* Print CPU/motherbord/other sensors as well */ int print_board_sensors = 0; /* Print CPU/motherbord/other sensors as well */
char *fan_speed[ICX3_MAX_FANS] = {NULL}; char *fan_speed[ICX3_MAX_FANS] = {NULL};
@@ -159,8 +162,14 @@ int main (int argc, char **argv)
} }
/* Scan for motherboard/CPU/other sensors */ /* Scan for motherboard/CPU/other sensors */
if (print_board_sensors) if (print_board_sensors) {
board_sensor_count = find_board_sensors(board_sensors, MAX_BOARD_SENSORS); board_sensor_count = find_board_sensors(board_sensors, MAX_BOARD_SENSORS);
if (init_rapl() && board_sensor_count < MAX_BOARD_SENSORS) {
board_sensors[board_sensor_count] = rapl_sensor;
zen3_rapl_sensor = board_sensor_count;
board_sensor_count++;
}
}
/* execute fan commands */ /* execute fan commands */
if (gpu_num == -1) { if (gpu_num == -1) {
@@ -199,17 +208,17 @@ int main (int argc, char **argv)
printf("\x1b[K"); /* Clear current console line */ printf("\x1b[K"); /* Clear current console line */
if (print_board_sensors) if (print_board_sensors)
print_board_info(board_sensors, board_sensor_count, compact); print_board_info(board_sensors, board_sensor_count);
if (gpu_num == -1) { if (gpu_num == -1) {
/* No GPU specified on command line, loop over all supported GPUs */ /* No GPU specified on command line, loop over all supported GPUs */
for (int i = 0; i < gpu_count; i++){ for (int i = 0; i < gpu_count; i++){
if (i > 0) if (i > 0)
printf("\n"); printf("\n");
print_gpu_info(i, &gpus[i], compact, no_reasons); print_gpu_info(i, &gpus[i]);
} }
} else if (gpu_num <= gpu_count - 1) { } else if (gpu_num <= gpu_count - 1) {
print_gpu_info(gpu_num, &gpus[gpu_num], compact, no_reasons); print_gpu_info(gpu_num, &gpus[gpu_num]);
} }
if (!overwrite) if (!overwrite)
@@ -231,7 +240,7 @@ int main (int argc, char **argv)
#endif #endif
} }
void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors, int compact) void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors)
{ {
int printed_sensors = 0; int printed_sensors = 0;
int current_sort_index = 0; int current_sort_index = 0;
@@ -241,39 +250,56 @@ void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors,
char *last_short_name = NULL; char *last_short_name = NULL;
char *last_units = NULL; char *last_units = NULL;
while (printed_sensors < num_sensors) { float rapl_power;
for (int i=0; i < num_sensors; i++){
for (int i = 0; i < (sizeof(hwmon_sensor_info) / sizeof(struct hwmon_sensor)); i++) {
/* Inject our Zen RAPL power reading here */
if (strcmp(hwmon_sensor_info[i].driver_name, "zen-rapl") == 0) {
board_sensors[zen3_rapl_sensor].sort_index = current_sort_index;
board_sensors[zen3_rapl_sensor].sensor_info = &hwmon_sensor_info[i];
}
for (int j=0; j < num_sensors; j++) {
struct hwmon_avail_sensor *current_sensor = &board_sensors[j];
/* Loop over all sensors, but only output those with the current sort index so they come out sort of sorted /* Loop over all sensors, but only output those with the current sort index so they come out sort of sorted
Duplicates (e.g.) multiple NVMe will come out in whatever sort of order the directory listing happened to */ Duplicates (e.g.) multiple NVMe will come out in whatever sort of order the directory listing happened to */
if (board_sensors[i].sort_index == current_sort_index) { if (current_sensor->sort_index == current_sort_index) {
printed_sensors++; printed_sensors++;
good_reading = get_sensor_reading(&board_sensors[i], &current_reading);
if (j == zen3_rapl_sensor) {
good_reading = 1;
current_reading = get_rapl_package_power();
} else {
good_reading = get_sensor_reading(current_sensor, &current_reading);
}
if (!good_reading) if (!good_reading)
continue; continue;
if (compact) { if (compact) {
/* Print units if needed */ /* Print units if needed */
if (last_units != NULL && strcmp(board_sensors[i].sensor_info->units, last_units)) if (last_units != NULL && strcmp(current_sensor->sensor_info->units, last_units))
printf("%s", last_units); printf("%s", last_units);
/* Print new section header if needed */ /* Print new section header if needed */
if (last_short_name == NULL || strcmp(board_sensors[i].sensor_info->short_name, last_short_name)) { if (last_short_name == NULL || strcmp(current_sensor->sensor_info->short_name, last_short_name)) {
if (last_short_name != NULL) /* Spacer for all headings not the first one */ if (last_short_name != NULL) /* Spacer for all headings not the first one */
printf(" "); printf(" ");
printf("%s%s%s", header_start, board_sensors[i].sensor_info->short_name, header_end); printf("%s%s%s", header_start, current_sensor->sensor_info->short_name, header_end);
} }
printf(" %3.0f", current_reading); printf(" %3.0f", current_reading);
last_short_name = board_sensors[i].sensor_info->short_name; last_short_name = current_sensor->sensor_info->short_name;
last_units = board_sensors[i].sensor_info->units; last_units = current_sensor->sensor_info->units;
} else { } else {
printf("%s%s: %+.1f%s\n", printf("%s%s: %+.1f%s\n",
board_sensors[i].sensor_info->name_prefix, current_sensor->sensor_info->name_prefix,
board_sensors[i].sensor_name, current_sensor->sensor_name,
current_reading, current_reading,
board_sensors[i].sensor_info->units); current_sensor->sensor_info->units);
} }
} }
@@ -287,7 +313,7 @@ void print_board_info(struct hwmon_avail_sensor *board_sensors, int num_sensors,
printf("\n"); printf("\n");
} }
void print_gpu_info(int gpu_num, struct card_info *gpu, int compact, int no_reasons) void print_gpu_info(int gpu_num, struct card_info *gpu)
{ {
if (compact) { if (compact) {
/* One line per GPU */ /* One line per GPU */
@@ -360,6 +386,5 @@ void print_gpu_info(int gpu_num, struct card_info *gpu, int compact, int no_reas
printf("\n"); printf("\n");
#endif #endif
} }
} }
+15 -14
View File
@@ -1,6 +1,7 @@
#ifndef ICX3_H #ifndef ICX3_H
#define ICX3_H #define ICX3_H
#include <stdint.h>
#include "evga-card.h" #include "evga-card.h"
#define ICX3_I2C_ADDR 0x2D #define ICX3_I2C_ADDR 0x2D
@@ -22,26 +23,26 @@
#define ICX3_WRITE_DISABLED 0xFE #define ICX3_WRITE_DISABLED 0xFE
struct icx3_fan_control { struct icx3_fan_control {
unsigned char length; uint8_t length;
unsigned char fanmode; uint8_t fanmode;
unsigned short rpm_offset; uint16_t rpm_offset;
unsigned char duty; uint8_t duty;
unsigned char duty_status; uint8_t duty_status;
unsigned short rpm_status; uint16_t rpm_status;
}; };
struct icx3_temp_sensors { struct icx3_temp_sensors {
unsigned char length; uint8_t length;
unsigned char data[18]; uint8_t data[18];
}; };
struct icx3_info { struct icx3_info {
unsigned char length; uint8_t length;
unsigned char reserved; uint8_t reserved;
unsigned char slave_address; uint8_t slave_address;
unsigned char product_id; uint8_t product_id;
unsigned char major_version; uint8_t major_version;
unsigned char minor_version; uint8_t minor_version;
}; };
enum icx3_product_id { enum icx3_product_id {
+1 -1
View File
@@ -36,7 +36,7 @@ void print_nvml_clock_reason(int compact, struct card_info *card)
single_reason = 0; single_reason = 0;
if (compact) if (compact)
printf("%s", clock_reason_names[i].short_name); printf("%-15s", clock_reason_names[i].short_name);
else else
printf("%s", clock_reason_names[i].long_name); printf("%s", clock_reason_names[i].long_name);
} }
+112
View File
@@ -0,0 +1,112 @@
#include <stdio.h>
#include <unistd.h>
#include <cpuid.h>
#include <math.h>
#include <string.h>
#include <fcntl.h>
#include "zen3-rapl.h"
#define AMD_STRING "AuthenticAMD"
#define ZEN_FAMILY 0x17
#define ZEN3_FAMILY 0x19
#define MEASUREMENT_TIME 0.25
static float energy_unit = 0;
static int msr_file = -1;
static float package_power = 0.0;
static int check_zen()
{
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0, ext_family;
char vendor[13];
__get_cpuid(0, &eax, &ebx, &ecx, &edx);
memcpy(vendor, &ebx, 4);
memcpy(vendor+4, &edx, 4);
memcpy(vendor+8, &ecx, 4);
vendor[12] = 0;
if (strcmp(vendor, AMD_STRING) != 0){
return 0;
}
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
ext_family = ((eax >> 8) & 0xF) + ((eax >> 20) & 0xFF);
if (ext_family != ZEN_FAMILY && ext_family != ZEN3_FAMILY){
return 0;
}
return 1;
}
static int read_msr(int file, unsigned int index, unsigned long long *data)
{
if (file < 0)
return 0;
return pread(file, data, sizeof *data, index) == sizeof *data;
}
static float get_energy_unit()
{
unsigned long long data;
// AMD OSRR: page 139 - MSRC001_0299
if (!read_msr(msr_file, 0xC0010299, &data))
return 0.0;
return pow(1.0/2.0, (float)((data >> 8) & 0x1F));
}
static unsigned long get_package_energy()
{
unsigned long long data;
// AMD OSRR: page 139 - MSRC001_029B
if (!read_msr(msr_file, 0xC001029B, &data))
return 0;
return data;
}
int init_rapl()
{
/* Check for supported Zen CPU */
if (!check_zen())
return 0;
/* Open MSR file */
char *msr_path = "/dev/cpu/0/msr";
msr_file = open(msr_path, O_RDONLY);
if (msr_file < 0)
return 0;
/* Energy unit */
energy_unit = get_energy_unit();
if (energy_unit == 0)
return 0;
return 1;
}
float get_rapl_package_power()
{
unsigned long package_eng_b = 0;
unsigned long package_eng_a = 0;
package_eng_b = get_package_energy();
usleep(MEASUREMENT_TIME*1000000);
package_eng_a = get_package_energy();
/* Only update if we computed a good power reading, otherwise return the most recent measurement */
if (package_eng_a >= package_eng_b)
package_power = (package_eng_a - package_eng_b) * energy_unit / MEASUREMENT_TIME;
return package_power;
}
+6
View File
@@ -0,0 +1,6 @@
#include "board-sensors.h"
static struct hwmon_avail_sensor rapl_sensor = {"Package power", -1, NULL, NULL};
int init_rapl();
float get_rapl_package_power();