1*4f19048fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27fe2f639SDominik Brodowski /*
37fe2f639SDominik Brodowski * (C) 2003 - 2004 Dominik Brodowski <linux@dominikbrodowski.de>
47fe2f639SDominik Brodowski *
57fe2f639SDominik Brodowski * Based on code found in
67fe2f639SDominik Brodowski * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
77fe2f639SDominik Brodowski * and originally developed by Jeremy Fitzhardinge.
87fe2f639SDominik Brodowski *
97fe2f639SDominik Brodowski * USAGE: simply run it to decode the current settings on CPU 0,
107fe2f639SDominik Brodowski * or pass the CPU number as argument, or pass the MSR content
117fe2f639SDominik Brodowski * as argument.
127fe2f639SDominik Brodowski */
137fe2f639SDominik Brodowski
147fe2f639SDominik Brodowski #include <stdio.h>
157fe2f639SDominik Brodowski #include <stdlib.h>
167fe2f639SDominik Brodowski #include <stdint.h>
177fe2f639SDominik Brodowski #include <unistd.h>
187fe2f639SDominik Brodowski #include <errno.h>
197fe2f639SDominik Brodowski #include <fcntl.h>
207fe2f639SDominik Brodowski
217fe2f639SDominik Brodowski #include <sys/types.h>
227fe2f639SDominik Brodowski #include <sys/stat.h>
237fe2f639SDominik Brodowski
247fe2f639SDominik Brodowski #define MCPU 32
257fe2f639SDominik Brodowski
267fe2f639SDominik Brodowski #define MSR_IA32_PERF_STATUS 0x198
277fe2f639SDominik Brodowski
rdmsr(unsigned int cpu,unsigned int msr,unsigned int * lo,unsigned int * hi)287fe2f639SDominik Brodowski static int rdmsr(unsigned int cpu, unsigned int msr,
297fe2f639SDominik Brodowski unsigned int *lo, unsigned int *hi)
307fe2f639SDominik Brodowski {
317fe2f639SDominik Brodowski int fd;
327fe2f639SDominik Brodowski char file[20];
337fe2f639SDominik Brodowski unsigned long long val;
347fe2f639SDominik Brodowski int retval = -1;
357fe2f639SDominik Brodowski
367fe2f639SDominik Brodowski *lo = *hi = 0;
377fe2f639SDominik Brodowski
387fe2f639SDominik Brodowski if (cpu > MCPU)
397fe2f639SDominik Brodowski goto err1;
407fe2f639SDominik Brodowski
417fe2f639SDominik Brodowski sprintf(file, "/dev/cpu/%d/msr", cpu);
427fe2f639SDominik Brodowski fd = open(file, O_RDONLY);
437fe2f639SDominik Brodowski
447fe2f639SDominik Brodowski if (fd < 0)
457fe2f639SDominik Brodowski goto err1;
467fe2f639SDominik Brodowski
477fe2f639SDominik Brodowski if (lseek(fd, msr, SEEK_CUR) == -1)
487fe2f639SDominik Brodowski goto err2;
497fe2f639SDominik Brodowski
507fe2f639SDominik Brodowski if (read(fd, &val, 8) != 8)
517fe2f639SDominik Brodowski goto err2;
527fe2f639SDominik Brodowski
537fe2f639SDominik Brodowski *lo = (uint32_t )(val & 0xffffffffull);
547fe2f639SDominik Brodowski *hi = (uint32_t )(val>>32 & 0xffffffffull);
557fe2f639SDominik Brodowski
567fe2f639SDominik Brodowski retval = 0;
577fe2f639SDominik Brodowski err2:
587fe2f639SDominik Brodowski close(fd);
597fe2f639SDominik Brodowski err1:
607fe2f639SDominik Brodowski return retval;
617fe2f639SDominik Brodowski }
627fe2f639SDominik Brodowski
decode(unsigned int msr)637fe2f639SDominik Brodowski static void decode (unsigned int msr)
647fe2f639SDominik Brodowski {
657fe2f639SDominik Brodowski unsigned int multiplier;
667fe2f639SDominik Brodowski unsigned int mv;
677fe2f639SDominik Brodowski
687fe2f639SDominik Brodowski multiplier = ((msr >> 8) & 0xFF);
697fe2f639SDominik Brodowski
707fe2f639SDominik Brodowski mv = (((msr & 0xFF) * 16) + 700);
717fe2f639SDominik Brodowski
727fe2f639SDominik Brodowski printf("0x%x means multiplier %d @ %d mV\n", msr, multiplier, mv);
737fe2f639SDominik Brodowski }
747fe2f639SDominik Brodowski
decode_live(unsigned int cpu)757fe2f639SDominik Brodowski static int decode_live(unsigned int cpu)
767fe2f639SDominik Brodowski {
777fe2f639SDominik Brodowski unsigned int lo, hi;
787fe2f639SDominik Brodowski int err;
797fe2f639SDominik Brodowski
807fe2f639SDominik Brodowski err = rdmsr(cpu, MSR_IA32_PERF_STATUS, &lo, &hi);
817fe2f639SDominik Brodowski
827fe2f639SDominik Brodowski if (err) {
837fe2f639SDominik Brodowski printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n", cpu);
847fe2f639SDominik Brodowski printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n");
857fe2f639SDominik Brodowski printf("or you are not root, or the msr driver is not present\n");
867fe2f639SDominik Brodowski return 1;
877fe2f639SDominik Brodowski }
887fe2f639SDominik Brodowski
897fe2f639SDominik Brodowski decode(lo);
907fe2f639SDominik Brodowski
917fe2f639SDominik Brodowski return 0;
927fe2f639SDominik Brodowski }
937fe2f639SDominik Brodowski
main(int argc,char ** argv)947fe2f639SDominik Brodowski int main (int argc, char **argv)
957fe2f639SDominik Brodowski {
967fe2f639SDominik Brodowski unsigned int cpu, mode = 0;
977fe2f639SDominik Brodowski
987fe2f639SDominik Brodowski if (argc < 2)
997fe2f639SDominik Brodowski cpu = 0;
1007fe2f639SDominik Brodowski else {
1017fe2f639SDominik Brodowski cpu = strtoul(argv[1], NULL, 0);
1027fe2f639SDominik Brodowski if (cpu >= MCPU)
1037fe2f639SDominik Brodowski mode = 1;
1047fe2f639SDominik Brodowski }
1057fe2f639SDominik Brodowski
1067fe2f639SDominik Brodowski if (mode)
1077fe2f639SDominik Brodowski decode(cpu);
1087fe2f639SDominik Brodowski else
1097fe2f639SDominik Brodowski decode_live(cpu);
1107fe2f639SDominik Brodowski
1117fe2f639SDominik Brodowski return 0;
1127fe2f639SDominik Brodowski }
113