Path: blob/master/tools/power/cpupower/debug/i386/dump_psb.c
26296 views
// SPDX-License-Identifier: GPL-2.0-only1// dump_psb. (c) 2004, Dave Jones, Red Hat Inc.23#include <fcntl.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7#include <unistd.h>89#define _GNU_SOURCE10#include <getopt.h>1112#include <sys/mman.h>1314#define LEN (0x100000 - 0xc0000)15#define OFFSET (0xc0000)1617#ifndef __packed18#define __packed __attribute((packed))19#endif2021static long relevant;2223static const int fid_to_mult[32] = {24110, 115, 120, 125, 50, 55, 60, 65,2570, 75, 80, 85, 90, 95, 100, 105,2630, 190, 40, 200, 130, 135, 140, 210,27150, 225, 160, 165, 170, 180, -1, -1,28};2930static const int vid_to_voltage[32] = {312000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,321600, 1550, 1500, 1450, 1400, 1350, 1300, 0,331275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,341075, 1050, 1024, 1000, 975, 950, 925, 0,35};3637struct psb_header {38char signature[10];39u_char version;40u_char flags;41u_short settlingtime;42u_char res1;43u_char numpst;44} __packed;4546struct pst_header {47u_int32_t cpuid;48u_char fsb;49u_char maxfid;50u_char startvid;51u_char numpstates;52} __packed;5354static u_int fsb;55static u_int sgtc;5657static int58decode_pst(char *p, int npstates)59{60int i;61int freq, fid, vid;6263for (i = 0; i < npstates; ++i) {64fid = *p++;65vid = *p++;66freq = 100 * fid_to_mult[fid] * fsb;6768printf(" %2d %8dkHz FID %02x (%2d.%01d) VID %02x (%4dmV)\n",69i,70freq,71fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,72vid, vid_to_voltage[vid]);73}7475return 0;76}7778static79void decode_psb(char *p, int numpst)80{81int i;82struct psb_header *psb;83struct pst_header *pst;8485psb = (struct psb_header*) p;8687if (psb->version != 0x12)88return;8990printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",91psb->version,92psb->flags,93psb->settlingtime,94psb->res1,95psb->numpst);96sgtc = psb->settlingtime * 100;9798if (sgtc < 10000)99sgtc = 10000;100101p = ((char *) psb) + sizeof(struct psb_header);102103if (numpst < 0)104numpst = psb->numpst;105else106printf("Overriding number of pst :%d\n", numpst);107108for (i = 0; i < numpst; i++) {109pst = (struct pst_header*) p;110111if (relevant != 0) {112if (relevant!= pst->cpuid)113goto next_one;114}115116printf(" PST %d cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",117i+1,118pst->cpuid,119pst->fsb,120pst->maxfid,121pst->startvid,122pst->numpstates);123124fsb = pst->fsb;125decode_pst(p + sizeof(struct pst_header), pst->numpstates);126127next_one:128p += sizeof(struct pst_header) + 2*pst->numpstates;129}130131}132133static struct option info_opts[] = {134{"numpst", no_argument, NULL, 'n'},135};136137void print_help(void)138{139printf ("Usage: dump_psb [options]\n");140printf ("Options:\n");141printf (" -n, --numpst Set number of PST tables to scan\n");142printf (" -r, --relevant Only display PSTs relevant to cpuid N\n");143}144145int146main(int argc, char *argv[])147{148int fd;149int numpst=-1;150int ret=0, cont=1;151char *mem = NULL;152char *p;153154do {155ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);156switch (ret){157case '?':158case 'h':159print_help();160cont = 0;161break;162case 'r':163relevant = strtol(optarg, NULL, 16);164break;165case 'n':166numpst = strtol(optarg, NULL, 10);167break;168case -1:169cont = 0;170break;171}172173} while(cont);174175fd = open("/dev/mem", O_RDONLY);176if (fd < 0) {177printf ("Couldn't open /dev/mem. Are you root?\n");178exit(1);179}180181mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);182close(fd);183184for (p = mem; p - mem < LEN; p+=16) {185if (memcmp(p, "AMDK7PNOW!", 10) == 0) {186decode_psb(p, numpst);187break;188}189}190191munmap(mem, LEN);192return 0;193}194195196