summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Herrmann <andreas.herrmann3@amd.com>2011-04-05 20:29:41 +0200
committerDave Jones <davej@redhat.com>2011-04-05 18:51:04 -0400
commit23ac5c6c87710e3e77e1a9ad6d5fd23438797563 (patch)
tree35aa3220f1f35d0920472f3522dc2c2890353a5e
parentc781dbc4f8959b7fbb1dacb7cce1ca12252fd0eb (diff)
x86info, AMD: powernow: Display boosted Pstate information
Fix output on systems with boosted Pstates. Indicate whether CPB is enabled. Display all Pstates (including the boosted ones). Example: Boosting enabled Number of boost states: 1 Pstate-Pb0: 3600MHz (boost state) Pstate-P0: 3200MHz (current) Pstate-P1: 2400MHz Pstate-P2: 1600MHz Pstate-P3: 800MHz In addition get rid of fid and vid information for HW Pstates. It's too CPU family specific. (Use lsmsr instead for this kind of information.) Note: this patch adds a new requirement to link x86info against libpci which usually is installed with pciutils (http://mj.ucw.cz/pciutils.html). Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
-rw-r--r--AMD/powernow.c99
-rw-r--r--Makefile2
2 files changed, 87 insertions, 14 deletions
diff --git a/AMD/powernow.c b/AMD/powernow.c
index 520fe30..e2b18d8 100644
--- a/AMD/powernow.c
+++ b/AMD/powernow.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
+#include <pci/pci.h>
#include "../x86info.h"
#include "AMD.h"
#include "powernow.h"
@@ -117,21 +118,85 @@ static void k8_decode_fidvid(struct cpudata *cpu)
k8_fid_codes[fidvidstatus.bits.cfid]);
}
-static int get_cof(int fid, int did, int family)
+static int get_did(int family, union msr_pstate pstate)
{
- int t = 0x10;
- if (family == 0x10)
- t = 0x10;
+ int t;
+
+ if (family == 0x14)
+ t = ((pstate.val >> 2) & 0x1f) + 4 + ((pstate.val & 0x3));
+ else if (family == 0x12)
+ t = pstate.val & 0xf;
else
+ t = pstate.bits.did;
+
+ return t;
+}
+
+static int get_cof(int family, union msr_pstate pstate)
+{
+ int t;
+ int fid, did;
+
+ did = get_did(family, pstate);
+
+ t = 0x10;
+ fid = pstate.bits.fid;
+ if (family == 0x11)
t = 0x8;
- return (100*(fid+t)>>did);
+
+ return ((100 * (fid + t)) >> did);
+ }
+
+static int get_num_boost_states(void)
+{
+ struct pci_filter filter_nb_link = { -1, -1, -1, -1, 0x1022, 0};
+ int dev_ids[3] = {0x1204};
+ struct pci_access *pacc;
+ struct pci_dev *z = NULL;
+ u8 val;
+ int i;
+
+ pacc = pci_alloc();
+ pci_init(pacc);
+ pci_scan_bus(pacc);
+
+ for (i=0; i<ARRAY_SIZE(dev_ids); i++) {
+ filter_nb_link.device = dev_ids[i];
+ for (z=pacc->devices; z; z=z->next) {
+ if (pci_filter_match(&filter_nb_link, z))
+ goto match;
+ }
+ }
+
+ match:
+ val = 0;
+ if (z) {
+ val = pci_read_byte(z, 0x15c);
+ if (val & 3)
+ printf("Boosting enabled\n");
+ else
+ printf("Boosting disabled\n");
+ val = (val >> 2) & 1;
+ printf("Number of boost states: %d\n", val);
+ }
+
+ pci_cleanup(pacc);
+ return val;
}
-static void decode_pstates(struct cpudata *cpu)
+static void decode_pstates(struct cpudata *cpu, int has_cpb)
{
- int i, psmax, pscur;
+ int i, psmax, pscur, fam;
union msr_pstate pstate;
unsigned long long val;
+ int boost_states = 0;
+
+ fam = family(cpu);
+ if (fam < 0x10)
+ return;
+
+ if (has_cpb)
+ boost_states = get_num_boost_states();
if (read_msr(cpu->number, MSR_PSTATE_LIMIT, &val) != 1) {
printf("Something went wrong reading MSR_PSTATE_CUR_LIMIT\n");
@@ -145,16 +210,21 @@ static void decode_pstates(struct cpudata *cpu)
}
pscur = val & 0x7;
+ pscur += boost_states;
+ psmax += boost_states;
for (i=0; i<=psmax; i++) {
if (read_msr(cpu->number, MSR_PSTATE + i, &pstate.val) != 1) {
printf("Something went wrong reading MSR_PSTATE_%d\n",
i);
return;
}
- printf("Pstate-%d: fid=%x, did=%x, vid=%x (%dMHz)%s\n", i,
- pstate.bits.fid, pstate.bits.did, pstate.bits.vid,
- get_cof(pstate.bits.fid, pstate.bits.did, family(cpu)),
- (i == pscur) ? " (current)" : "");
+ if (i < boost_states)
+ printf("Pstate-Pb%d: %dMHz (boost state)\n",
+ i, get_cof(fam, pstate));
+ else
+ printf("Pstate-P%d: %dMHz%s\n",
+ i - boost_states, get_cof(fam, pstate),
+ (i == pscur) ? " (current)" : "");
}
printf("\n");
}
@@ -163,6 +233,7 @@ void decode_powernow(struct cpudata *cpu)
{
unsigned int eax, ebx, ecx, edx;
int can_scale_vid=0, can_scale_fid=0;
+ int has_cpb = 0;
if (cpu->maxei < 0x80000007)
return;
@@ -195,8 +266,10 @@ void decode_powernow(struct cpudata *cpu)
}
if (edx & (1<<8))
printf("\n\tinvariant TSC");
- if (edx & (1<<9))
+ if (edx & (1<<9)) {
printf("\n\tCore Performance Boost");
+ has_cpb = 1;
+ }
if (edx & (1<<10))
printf("\n\read-only Effective Frequency Interface");
if (!(edx & 0x1ff))
@@ -219,5 +292,5 @@ void decode_powernow(struct cpudata *cpu)
else if (family(cpu) == 0xf)
k8_decode_fidvid(cpu);
else if (family(cpu) >= 0x10)
- decode_pstates(cpu);
+ decode_pstates(cpu, has_cpb);
}
diff --git a/Makefile b/Makefile
index 66fc195..cd5c4a7 100644
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,7 @@ X86INFO_SRC = \
X86INFO_OBJS = $(X86INFO_SRC:%.c=%.o)
x86info: $(X86INFO_OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o x86info $(X86INFO_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o x86info $(X86INFO_OBJS) -lpci