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, &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(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(cpu); 108 else 109 decode_live(cpu); 110 111 return 0; 112 } 113