-
Notifications
You must be signed in to change notification settings - Fork 25
/
msr-access.c
129 lines (104 loc) · 2.83 KB
/
msr-access.c
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
/*
* msr-access.c
*/
// for pread() and sched_getcpu()
#define _GNU_SOURCE
#include "msr-access.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <inttypes.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
/** if there are this many CPUs or less, we'll never allocate memory */
#define STATIC_ARRAY_SIZE 32
#ifndef MSR_USE_PTHREADS
// thread-safe by default
#define MSR_USE_PTHREADS 1
#endif
#if MSR_USE_PTHREADS
#include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
#else
void lock() {}
void unlock(){}
#endif
/* size of the rfile array */
int rfile_static[STATIC_ARRAY_SIZE] = {};
int rfile_size = STATIC_ARRAY_SIZE;
int *rfile_array = rfile_static;
//int rfile_error;
/** get the read-only file associated with the given cpu */
int get_rfile(int cpu) {
assert(cpu >= 0);
lock();
if (cpu >= rfile_size) {
// expand array
size_t new_size = rfile_size * 2 > cpu ? rfile_size * 2 : cpu;
int *new_array = calloc(new_size, sizeof(int));
memcpy(new_array, rfile_array, rfile_size * sizeof(int));
if (rfile_array != rfile_static) {
free(rfile_array);
}
rfile_array = new_array;
rfile_size = new_size;
}
if (rfile_array[cpu] == 0) {
char filename[64] = {};
int ret = snprintf(filename, 64, "/dev/cpu/%d/msr", cpu);
assert(ret > 0);
rfile_array[cpu] = open(filename, O_RDONLY);
if (rfile_array[cpu] == -1) {
rfile_array[cpu] = -errno;
}
}
int ret = rfile_array[cpu];
unlock();
return ret;
}
int read_msr(int cpu, uint32_t msr_index, uint64_t* value) {
int file = get_rfile(cpu);
assert(file);
if (file < 0) {
// file open failes are stored as negative errno
return file;
}
int read = pread(file, value, 8, msr_index);
return read == -1 ? errno : 0;
}
int read_msr_cur_cpu(uint32_t msr_index, uint64_t* value) {
return read_msr(sched_getcpu(), msr_index, value);
}
// rename this to main to build an exe that can be run as ./a.out CPU MSR
// to read MSR from CPU (like a really simple rdmsr)
int test(int argc, char** argv) {
assert(argc == 3);
int cpu = atoi(argv[1]);
uint32_t msr = atoi(argv[2]);
printf("reading msr %u from cpu %d\n", msr, cpu);
uint64_t value = -1;
int res = read_msr(cpu, msr, &value);
if (res) {
printf("error %d\n", res);
} else {
printf("value %lx\n", value);
}
res = read_msr_cur_cpu(msr, &value);
if (res) {
printf("error %d\n", res);
} else {
printf("value %lx\n", value);
}
return EXIT_SUCCESS;
}