xref: /openbmc/linux/tools/power/cpupower/debug/i386/centrino-decode.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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