cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cpuidle_sysfs.c (5026B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc
      4 */
      5
      6#include <stdio.h>
      7#include <stdlib.h>
      8#include <stdint.h>
      9#include <string.h>
     10#include <limits.h>
     11#include <cpuidle.h>
     12
     13#include "helpers/helpers.h"
     14#include "idle_monitor/cpupower-monitor.h"
     15
     16#define CPUIDLE_STATES_MAX 10
     17static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
     18struct cpuidle_monitor cpuidle_sysfs_monitor;
     19
     20static unsigned long long **previous_count;
     21static unsigned long long **current_count;
     22static struct timespec start_time;
     23static unsigned long long timediff;
     24
     25static int cpuidle_get_count_percent(unsigned int id, double *percent,
     26				     unsigned int cpu)
     27{
     28	unsigned long long statediff = current_count[cpu][id]
     29		- previous_count[cpu][id];
     30	dprint("%s: - diff: %llu - percent: %f (%u)\n",
     31	       cpuidle_cstates[id].name, timediff, *percent, cpu);
     32
     33	if (timediff == 0)
     34		*percent = 0.0;
     35	else
     36		*percent = ((100.0 * statediff) / timediff);
     37
     38	dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
     39	       cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
     40
     41	return 0;
     42}
     43
     44static int cpuidle_start(void)
     45{
     46	int cpu, state;
     47	clock_gettime(CLOCK_REALTIME, &start_time);
     48	for (cpu = 0; cpu < cpu_count; cpu++) {
     49		for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
     50		     state++) {
     51			previous_count[cpu][state] =
     52				cpuidle_state_time(cpu, state);
     53			dprint("CPU %d - State: %d - Val: %llu\n",
     54			       cpu, state, previous_count[cpu][state]);
     55		}
     56	}
     57	return 0;
     58}
     59
     60static int cpuidle_stop(void)
     61{
     62	int cpu, state;
     63	struct timespec end_time;
     64	clock_gettime(CLOCK_REALTIME, &end_time);
     65	timediff = timespec_diff_us(start_time, end_time);
     66
     67	for (cpu = 0; cpu < cpu_count; cpu++) {
     68		for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
     69		     state++) {
     70			current_count[cpu][state] =
     71				cpuidle_state_time(cpu, state);
     72			dprint("CPU %d - State: %d - Val: %llu\n",
     73			       cpu, state, previous_count[cpu][state]);
     74		}
     75	}
     76	return 0;
     77}
     78
     79void fix_up_intel_idle_driver_name(char *tmp, int num)
     80{
     81	/* fix up cpuidle name for intel idle driver */
     82	if (!strncmp(tmp, "NHM-", 4)) {
     83		switch (num) {
     84		case 1:
     85			strcpy(tmp, "C1");
     86			break;
     87		case 2:
     88			strcpy(tmp, "C3");
     89			break;
     90		case 3:
     91			strcpy(tmp, "C6");
     92			break;
     93		}
     94	} else if (!strncmp(tmp, "SNB-", 4)) {
     95		switch (num) {
     96		case 1:
     97			strcpy(tmp, "C1");
     98			break;
     99		case 2:
    100			strcpy(tmp, "C3");
    101			break;
    102		case 3:
    103			strcpy(tmp, "C6");
    104			break;
    105		case 4:
    106			strcpy(tmp, "C7");
    107			break;
    108		}
    109	} else if (!strncmp(tmp, "ATM-", 4)) {
    110		switch (num) {
    111		case 1:
    112			strcpy(tmp, "C1");
    113			break;
    114		case 2:
    115			strcpy(tmp, "C2");
    116			break;
    117		case 3:
    118			strcpy(tmp, "C4");
    119			break;
    120		case 4:
    121			strcpy(tmp, "C6");
    122			break;
    123		}
    124	}
    125}
    126
    127#ifdef __powerpc__
    128void map_power_idle_state_name(char *tmp)
    129{
    130	if (!strncmp(tmp, "stop0_lite", CSTATE_NAME_LEN))
    131		strcpy(tmp, "stop0L");
    132	else if (!strncmp(tmp, "stop1_lite", CSTATE_NAME_LEN))
    133		strcpy(tmp, "stop1L");
    134	else if (!strncmp(tmp, "stop2_lite", CSTATE_NAME_LEN))
    135		strcpy(tmp, "stop2L");
    136}
    137#else
    138void map_power_idle_state_name(char *tmp) { }
    139#endif
    140
    141static struct cpuidle_monitor *cpuidle_register(void)
    142{
    143	int num;
    144	char *tmp;
    145	int this_cpu;
    146
    147	this_cpu = sched_getcpu();
    148
    149	/* Assume idle state count is the same for all CPUs */
    150	cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(this_cpu);
    151
    152	if (cpuidle_sysfs_monitor.hw_states_num <= 0)
    153		return NULL;
    154
    155	for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
    156		tmp = cpuidle_state_name(this_cpu, num);
    157		if (tmp == NULL)
    158			continue;
    159
    160		map_power_idle_state_name(tmp);
    161		fix_up_intel_idle_driver_name(tmp, num);
    162		strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
    163		free(tmp);
    164
    165		tmp = cpuidle_state_desc(this_cpu, num);
    166		if (tmp == NULL)
    167			continue;
    168		strncpy(cpuidle_cstates[num].desc, tmp,	CSTATE_DESC_LEN - 1);
    169		free(tmp);
    170
    171		cpuidle_cstates[num].range = RANGE_THREAD;
    172		cpuidle_cstates[num].id = num;
    173		cpuidle_cstates[num].get_count_percent =
    174			cpuidle_get_count_percent;
    175	}
    176
    177	/* Free this at program termination */
    178	previous_count = malloc(sizeof(long long *) * cpu_count);
    179	current_count = malloc(sizeof(long long *) * cpu_count);
    180	for (num = 0; num < cpu_count; num++) {
    181		previous_count[num] = malloc(sizeof(long long) *
    182					cpuidle_sysfs_monitor.hw_states_num);
    183		current_count[num] = malloc(sizeof(long long) *
    184					cpuidle_sysfs_monitor.hw_states_num);
    185	}
    186
    187	cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
    188	return &cpuidle_sysfs_monitor;
    189}
    190
    191void cpuidle_unregister(void)
    192{
    193	int num;
    194
    195	for (num = 0; num < cpu_count; num++) {
    196		free(previous_count[num]);
    197		free(current_count[num]);
    198	}
    199	free(previous_count);
    200	free(current_count);
    201}
    202
    203struct cpuidle_monitor cpuidle_sysfs_monitor = {
    204	.name			= "Idle_Stats",
    205	.hw_states		= cpuidle_cstates,
    206	.start			= cpuidle_start,
    207	.stop			= cpuidle_stop,
    208	.do_register		= cpuidle_register,
    209	.unregister		= cpuidle_unregister,
    210	.flags.needs_root	= 0,
    211	.overflow_s		= UINT_MAX,
    212};