1/* 2 * (C) 2004 Bruno Ducrot <ducrot@poupinou.org> 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/powernow-k8.c 8 * and originally developed by Paul Devriendt 9 */ 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <stdint.h> 14#include <unistd.h> 15#include <errno.h> 16#include <fcntl.h> 17 18#include <sys/types.h> 19#include <sys/stat.h> 20 21#define MCPU 32 22 23#define MSR_FIDVID_STATUS 0xc0010042 24 25#define MSR_S_HI_CURRENT_VID 0x0000001f 26#define MSR_S_LO_CURRENT_FID 0x0000003f 27 28static int get_fidvid(uint32_t cpu, uint32_t *fid, uint32_t *vid) 29{ 30 int err = 1; 31 uint64_t msr = 0; 32 int fd; 33 char file[20]; 34 35 if (cpu > MCPU) 36 goto out; 37 38 sprintf(file, "/dev/cpu/%d/msr", cpu); 39 40 fd = open(file, O_RDONLY); 41 if (fd < 0) 42 goto out; 43 lseek(fd, MSR_FIDVID_STATUS, SEEK_CUR); 44 if (read(fd, &msr, 8) != 8) 45 goto err1; 46 47 *fid = ((uint32_t )(msr & 0xffffffffull)) & MSR_S_LO_CURRENT_FID; 48 *vid = ((uint32_t )(msr>>32 & 0xffffffffull)) & MSR_S_HI_CURRENT_VID; 49 err = 0; 50err1: 51 close(fd); 52out: 53 return err; 54} 55 56 57/* Return a frequency in MHz, given an input fid */ 58static uint32_t find_freq_from_fid(uint32_t fid) 59{ 60 return 800 + (fid * 100); 61} 62 63/* Return a voltage in miliVolts, given an input vid */ 64static uint32_t find_millivolts_from_vid(uint32_t vid) 65{ 66 return 1550-vid*25; 67} 68 69int main (int argc, char *argv[]) 70{ 71 int err; 72 int cpu; 73 uint32_t fid, vid; 74 75 if (argc < 2) 76 cpu = 0; 77 else 78 cpu = strtoul(argv[1], NULL, 0); 79 80 err = get_fidvid(cpu, &fid, &vid); 81 82 if (err) { 83 printf("can't get fid, vid from MSR\n"); 84 printf("Possible trouble: you don't run a powernow-k8 capable cpu\n"); 85 printf("or you are not root, or the msr driver is not present\n"); 86 exit(1); 87 } 88 89 90 printf("cpu %d currently at %d MHz and %d mV\n", 91 cpu, 92 find_freq_from_fid(fid), 93 find_millivolts_from_vid(vid)); 94 95 return 0; 96} 97