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