summaryrefslogtreecommitdiff
path: root/tools/power/cpupower/utils/helpers/msr.c
blob: 7869ca64dfd3a8d9a0f7af68c1e03c99d09150f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#if defined(__i386__) || defined(__x86_64__)

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>

#include "helpers/helpers.h"

/* Intel specific MSRs */
#define MSR_IA32_PERF_STATUS		0x198
#define MSR_IA32_MISC_ENABLES		0x1a0
#define MSR_IA32_ENERGY_PERF_BIAS	0x1b0
#define MSR_NEHALEM_TURBO_RATIO_LIMIT	0x1ad

/*
 * read_msr
 *
 * Will return 0 on success and -1 on failure.
 * Possible errno values could be:
 * EFAULT -If the read/write did not fully complete
 * EIO    -If the CPU does not support MSRs
 * ENXIO  -If the CPU does not exist
 */

int read_msr(int cpu, unsigned int idx, unsigned long long *val)
{
	int fd;
	char msr_file_name[64];

	sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
	fd = open(msr_file_name, O_RDONLY);
	if (fd < 0)
		return -1;
	if (lseek(fd, idx, SEEK_CUR) == -1)
		goto err;
	if (read(fd, val, sizeof *val) != sizeof *val)
		goto err;
	close(fd);
	return 0;
 err:
	close(fd);
	return -1;
}

/*
 * write_msr
 *
 * Will return 0 on success and -1 on failure.
 * Possible errno values could be:
 * EFAULT -If the read/write did not fully complete
 * EIO    -If the CPU does not support MSRs
 * ENXIO  -If the CPU does not exist
 */
int write_msr(int cpu, unsigned int idx, unsigned long long val)
{
	int fd;
	char msr_file_name[64];

	sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
	fd = open(msr_file_name, O_WRONLY);
	if (fd < 0)
		return -1;
	if (lseek(fd, idx, SEEK_CUR) == -1)
		goto err;
	if (write(fd, &val, sizeof val) != sizeof val)
		goto err;
	close(fd);
	return 0;
 err:
	close(fd);
	return -1;
}

int msr_intel_has_boost_support(unsigned int cpu)
{
	unsigned long long misc_enables;
	int ret;

	ret = read_msr(cpu, MSR_IA32_MISC_ENABLES, &misc_enables);
	if (ret)
		return ret;

	return (misc_enables >> 38) & 0x1;
}

int msr_intel_boost_is_active(unsigned int cpu)
{
	unsigned long long perf_status;
	int ret;

	ret = read_msr(cpu, MSR_IA32_PERF_STATUS, &perf_status);
	if (ret)
		return ret;
	return (perf_status >> 32) & 0x1;
}

int msr_intel_get_perf_bias(unsigned int cpu)
{
	unsigned long long val;
	int ret;

	if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
		return -1;

	ret = read_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &val);
	if (ret)
		return ret;
	return val;
}

int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
{
	int ret;

	if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
		return -1;

	ret = write_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, val);
	if (ret)
		return ret;
	return 0;
}

unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
{
	unsigned long long val;
	int ret;

	if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO))
		return -1;

	ret = read_msr(cpu, MSR_NEHALEM_TURBO_RATIO_LIMIT, &val);
	if (ret)
		return ret;
	return val;
}
#endif