1*fa82cce7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*fa82cce7SThomas Gleixner // dump_psb. (c) 2004, Dave Jones, Red Hat Inc.
37fe2f639SDominik Brodowski
47fe2f639SDominik Brodowski #include <fcntl.h>
57fe2f639SDominik Brodowski #include <stdio.h>
67fe2f639SDominik Brodowski #include <stdlib.h>
77fe2f639SDominik Brodowski #include <string.h>
87fe2f639SDominik Brodowski #include <unistd.h>
97fe2f639SDominik Brodowski
107fe2f639SDominik Brodowski #define _GNU_SOURCE
117fe2f639SDominik Brodowski #include <getopt.h>
127fe2f639SDominik Brodowski
137fe2f639SDominik Brodowski #include <sys/mman.h>
147fe2f639SDominik Brodowski
157fe2f639SDominik Brodowski #define LEN (0x100000 - 0xc0000)
167fe2f639SDominik Brodowski #define OFFSET (0xc0000)
177fe2f639SDominik Brodowski
187fe2f639SDominik Brodowski #ifndef __packed
197fe2f639SDominik Brodowski #define __packed __attribute((packed))
207fe2f639SDominik Brodowski #endif
217fe2f639SDominik Brodowski
227fe2f639SDominik Brodowski static long relevant;
237fe2f639SDominik Brodowski
247fe2f639SDominik Brodowski static const int fid_to_mult[32] = {
257fe2f639SDominik Brodowski 110, 115, 120, 125, 50, 55, 60, 65,
267fe2f639SDominik Brodowski 70, 75, 80, 85, 90, 95, 100, 105,
277fe2f639SDominik Brodowski 30, 190, 40, 200, 130, 135, 140, 210,
287fe2f639SDominik Brodowski 150, 225, 160, 165, 170, 180, -1, -1,
297fe2f639SDominik Brodowski };
307fe2f639SDominik Brodowski
317fe2f639SDominik Brodowski static const int vid_to_voltage[32] = {
327fe2f639SDominik Brodowski 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
337fe2f639SDominik Brodowski 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
347fe2f639SDominik Brodowski 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
357fe2f639SDominik Brodowski 1075, 1050, 1024, 1000, 975, 950, 925, 0,
367fe2f639SDominik Brodowski };
377fe2f639SDominik Brodowski
387fe2f639SDominik Brodowski struct psb_header {
397fe2f639SDominik Brodowski char signature[10];
407fe2f639SDominik Brodowski u_char version;
417fe2f639SDominik Brodowski u_char flags;
427fe2f639SDominik Brodowski u_short settlingtime;
437fe2f639SDominik Brodowski u_char res1;
447fe2f639SDominik Brodowski u_char numpst;
457fe2f639SDominik Brodowski } __packed;
467fe2f639SDominik Brodowski
477fe2f639SDominik Brodowski struct pst_header {
487fe2f639SDominik Brodowski u_int32_t cpuid;
497fe2f639SDominik Brodowski u_char fsb;
507fe2f639SDominik Brodowski u_char maxfid;
517fe2f639SDominik Brodowski u_char startvid;
527fe2f639SDominik Brodowski u_char numpstates;
537fe2f639SDominik Brodowski } __packed;
547fe2f639SDominik Brodowski
557fe2f639SDominik Brodowski static u_int fsb;
567fe2f639SDominik Brodowski static u_int sgtc;
577fe2f639SDominik Brodowski
587fe2f639SDominik Brodowski static int
decode_pst(char * p,int npstates)597fe2f639SDominik Brodowski decode_pst(char *p, int npstates)
607fe2f639SDominik Brodowski {
617fe2f639SDominik Brodowski int i;
627fe2f639SDominik Brodowski int freq, fid, vid;
637fe2f639SDominik Brodowski
647fe2f639SDominik Brodowski for (i = 0; i < npstates; ++i) {
657fe2f639SDominik Brodowski fid = *p++;
667fe2f639SDominik Brodowski vid = *p++;
677fe2f639SDominik Brodowski freq = 100 * fid_to_mult[fid] * fsb;
687fe2f639SDominik Brodowski
697fe2f639SDominik Brodowski printf(" %2d %8dkHz FID %02x (%2d.%01d) VID %02x (%4dmV)\n",
707fe2f639SDominik Brodowski i,
717fe2f639SDominik Brodowski freq,
727fe2f639SDominik Brodowski fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,
737fe2f639SDominik Brodowski vid, vid_to_voltage[vid]);
747fe2f639SDominik Brodowski }
757fe2f639SDominik Brodowski
767fe2f639SDominik Brodowski return 0;
777fe2f639SDominik Brodowski }
787fe2f639SDominik Brodowski
797fe2f639SDominik Brodowski static
decode_psb(char * p,int numpst)807fe2f639SDominik Brodowski void decode_psb(char *p, int numpst)
817fe2f639SDominik Brodowski {
827fe2f639SDominik Brodowski int i;
837fe2f639SDominik Brodowski struct psb_header *psb;
847fe2f639SDominik Brodowski struct pst_header *pst;
857fe2f639SDominik Brodowski
867fe2f639SDominik Brodowski psb = (struct psb_header*) p;
877fe2f639SDominik Brodowski
887fe2f639SDominik Brodowski if (psb->version != 0x12)
897fe2f639SDominik Brodowski return;
907fe2f639SDominik Brodowski
917fe2f639SDominik Brodowski printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",
927fe2f639SDominik Brodowski psb->version,
937fe2f639SDominik Brodowski psb->flags,
947fe2f639SDominik Brodowski psb->settlingtime,
957fe2f639SDominik Brodowski psb->res1,
967fe2f639SDominik Brodowski psb->numpst);
977fe2f639SDominik Brodowski sgtc = psb->settlingtime * 100;
987fe2f639SDominik Brodowski
997fe2f639SDominik Brodowski if (sgtc < 10000)
1007fe2f639SDominik Brodowski sgtc = 10000;
1017fe2f639SDominik Brodowski
1027fe2f639SDominik Brodowski p = ((char *) psb) + sizeof(struct psb_header);
1037fe2f639SDominik Brodowski
1047fe2f639SDominik Brodowski if (numpst < 0)
1057fe2f639SDominik Brodowski numpst = psb->numpst;
1067fe2f639SDominik Brodowski else
1077fe2f639SDominik Brodowski printf("Overriding number of pst :%d\n", numpst);
1087fe2f639SDominik Brodowski
1097fe2f639SDominik Brodowski for (i = 0; i < numpst; i++) {
1107fe2f639SDominik Brodowski pst = (struct pst_header*) p;
1117fe2f639SDominik Brodowski
1127fe2f639SDominik Brodowski if (relevant != 0) {
1137fe2f639SDominik Brodowski if (relevant!= pst->cpuid)
1147fe2f639SDominik Brodowski goto next_one;
1157fe2f639SDominik Brodowski }
1167fe2f639SDominik Brodowski
1177fe2f639SDominik Brodowski printf(" PST %d cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",
1187fe2f639SDominik Brodowski i+1,
1197fe2f639SDominik Brodowski pst->cpuid,
1207fe2f639SDominik Brodowski pst->fsb,
1217fe2f639SDominik Brodowski pst->maxfid,
1227fe2f639SDominik Brodowski pst->startvid,
1237fe2f639SDominik Brodowski pst->numpstates);
1247fe2f639SDominik Brodowski
1257fe2f639SDominik Brodowski fsb = pst->fsb;
1267fe2f639SDominik Brodowski decode_pst(p + sizeof(struct pst_header), pst->numpstates);
1277fe2f639SDominik Brodowski
1287fe2f639SDominik Brodowski next_one:
1297fe2f639SDominik Brodowski p += sizeof(struct pst_header) + 2*pst->numpstates;
1307fe2f639SDominik Brodowski }
1317fe2f639SDominik Brodowski
1327fe2f639SDominik Brodowski }
1337fe2f639SDominik Brodowski
1347fe2f639SDominik Brodowski static struct option info_opts[] = {
13557ab3b08SSriram Raghunathan {"numpst", no_argument, NULL, 'n'},
1367fe2f639SDominik Brodowski };
1377fe2f639SDominik Brodowski
print_help(void)1387fe2f639SDominik Brodowski void print_help(void)
1397fe2f639SDominik Brodowski {
1407fe2f639SDominik Brodowski printf ("Usage: dump_psb [options]\n");
1417fe2f639SDominik Brodowski printf ("Options:\n");
1427fe2f639SDominik Brodowski printf (" -n, --numpst Set number of PST tables to scan\n");
1437fe2f639SDominik Brodowski printf (" -r, --relevant Only display PSTs relevant to cpuid N\n");
1447fe2f639SDominik Brodowski }
1457fe2f639SDominik Brodowski
1467fe2f639SDominik Brodowski int
main(int argc,char * argv[])1477fe2f639SDominik Brodowski main(int argc, char *argv[])
1487fe2f639SDominik Brodowski {
1497fe2f639SDominik Brodowski int fd;
1507fe2f639SDominik Brodowski int numpst=-1;
1517fe2f639SDominik Brodowski int ret=0, cont=1;
1527fe2f639SDominik Brodowski char *mem = NULL;
1537fe2f639SDominik Brodowski char *p;
1547fe2f639SDominik Brodowski
1557fe2f639SDominik Brodowski do {
1567fe2f639SDominik Brodowski ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);
1577fe2f639SDominik Brodowski switch (ret){
1587fe2f639SDominik Brodowski case '?':
1597fe2f639SDominik Brodowski case 'h':
1607fe2f639SDominik Brodowski print_help();
1617fe2f639SDominik Brodowski cont = 0;
1627fe2f639SDominik Brodowski break;
1637fe2f639SDominik Brodowski case 'r':
1647fe2f639SDominik Brodowski relevant = strtol(optarg, NULL, 16);
1657fe2f639SDominik Brodowski break;
1667fe2f639SDominik Brodowski case 'n':
1677fe2f639SDominik Brodowski numpst = strtol(optarg, NULL, 10);
1687fe2f639SDominik Brodowski break;
1697fe2f639SDominik Brodowski case -1:
1707fe2f639SDominik Brodowski cont = 0;
1717fe2f639SDominik Brodowski break;
1727fe2f639SDominik Brodowski }
1737fe2f639SDominik Brodowski
1747fe2f639SDominik Brodowski } while(cont);
1757fe2f639SDominik Brodowski
1767fe2f639SDominik Brodowski fd = open("/dev/mem", O_RDONLY);
1777fe2f639SDominik Brodowski if (fd < 0) {
1787fe2f639SDominik Brodowski printf ("Couldn't open /dev/mem. Are you root?\n");
1797fe2f639SDominik Brodowski exit(1);
1807fe2f639SDominik Brodowski }
1817fe2f639SDominik Brodowski
1827fe2f639SDominik Brodowski mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);
1837fe2f639SDominik Brodowski close(fd);
1847fe2f639SDominik Brodowski
1857fe2f639SDominik Brodowski for (p = mem; p - mem < LEN; p+=16) {
1867fe2f639SDominik Brodowski if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
1877fe2f639SDominik Brodowski decode_psb(p, numpst);
1887fe2f639SDominik Brodowski break;
1897fe2f639SDominik Brodowski }
1907fe2f639SDominik Brodowski }
1917fe2f639SDominik Brodowski
1927fe2f639SDominik Brodowski munmap(mem, LEN);
1937fe2f639SDominik Brodowski return 0;
1947fe2f639SDominik Brodowski }
195