1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * (C) 2003 - 2004 Dominik Brodowski <linux@dominikbrodowski.de> |
4 | * |
5 | * Based on code found in |
6 | * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c |
7 | * and originally developed by Jeremy Fitzhardinge. |
8 | * |
9 | * USAGE: simply run it to decode the current settings on CPU 0, |
10 | * or pass the CPU number as argument, or pass the MSR content |
11 | * as argument. |
12 | */ |
13 | |
14 | #include <stdio.h> |
15 | #include <stdlib.h> |
16 | #include <stdint.h> |
17 | #include <unistd.h> |
18 | #include <errno.h> |
19 | #include <fcntl.h> |
20 | |
21 | #include <sys/types.h> |
22 | #include <sys/stat.h> |
23 | |
24 | #define MCPU 32 |
25 | |
26 | #define MSR_IA32_PERF_STATUS 0x198 |
27 | |
28 | static int rdmsr(unsigned int cpu, unsigned int msr, |
29 | unsigned int *lo, unsigned int *hi) |
30 | { |
31 | int fd; |
32 | char file[20]; |
33 | unsigned long long val; |
34 | int retval = -1; |
35 | |
36 | *lo = *hi = 0; |
37 | |
38 | if (cpu > MCPU) |
39 | goto err1; |
40 | |
41 | sprintf(file, "/dev/cpu/%d/msr" , cpu); |
42 | fd = open(file, O_RDONLY); |
43 | |
44 | if (fd < 0) |
45 | goto err1; |
46 | |
47 | if (lseek(fd, msr, SEEK_CUR) == -1) |
48 | goto err2; |
49 | |
50 | if (read(fd, &val, 8) != 8) |
51 | goto err2; |
52 | |
53 | *lo = (uint32_t )(val & 0xffffffffull); |
54 | *hi = (uint32_t )(val>>32 & 0xffffffffull); |
55 | |
56 | retval = 0; |
57 | err2: |
58 | close(fd); |
59 | err1: |
60 | return retval; |
61 | } |
62 | |
63 | static void decode (unsigned int msr) |
64 | { |
65 | unsigned int multiplier; |
66 | unsigned int mv; |
67 | |
68 | multiplier = ((msr >> 8) & 0xFF); |
69 | |
70 | mv = (((msr & 0xFF) * 16) + 700); |
71 | |
72 | printf("0x%x means multiplier %d @ %d mV\n" , msr, multiplier, mv); |
73 | } |
74 | |
75 | static int decode_live(unsigned int cpu) |
76 | { |
77 | unsigned int lo, hi; |
78 | int err; |
79 | |
80 | err = rdmsr(cpu, MSR_IA32_PERF_STATUS, lo: &lo, hi: &hi); |
81 | |
82 | if (err) { |
83 | printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n" , cpu); |
84 | printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n" ); |
85 | printf("or you are not root, or the msr driver is not present\n" ); |
86 | return 1; |
87 | } |
88 | |
89 | decode(msr: lo); |
90 | |
91 | return 0; |
92 | } |
93 | |
94 | int main (int argc, char **argv) |
95 | { |
96 | unsigned int cpu, mode = 0; |
97 | |
98 | if (argc < 2) |
99 | cpu = 0; |
100 | else { |
101 | cpu = strtoul(argv[1], NULL, 0); |
102 | if (cpu >= MCPU) |
103 | mode = 1; |
104 | } |
105 | |
106 | if (mode) |
107 | decode(msr: cpu); |
108 | else |
109 | decode_live(cpu); |
110 | |
111 | return 0; |
112 | } |
113 | |