Blob Blame History Raw
commit 01c9cbcf4face809cb6953bc3cd2a30cd075ed16
Author: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
Date:   Thu Dec 6 17:30:38 2018 -0600

    lparstat: correct calculation of physc to use tbr
    
    Currently phsyc is calculated using the sampled PURR values from lparcfg and
    a derived timebase that lparstat itself calculates. However, both the Timer
    Facilities section in Book III of the ISA and PAPR outline that this resource
    calcuation is done by computing the ratio of the PURR delta and the Timebase
    Register delta for the sampled period.
    
    I've sent a patch upstream to the kernel list to also export the Timebase
    Register (tbr) in /proc/ppc64/lparcfg [1]. Use this value for calculating
    physc value when running on a kernel that exposes tbr.
    
    [1] https://patchwork.ozlabs.org/patch/1009906/
    
    Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>

diff --git a/src/lparstat.c b/src/lparstat.c
index 23e45f7..ec57c1a 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -155,17 +155,27 @@ void get_cpu_physc(struct sysentry *unused_se, char *buf)
 	float elapsed;
 	float new_purr, old_purr;
 	float timebase, physc;
-
-	elapsed = elapsed_time() / 1000000.0;
-
-	se = get_sysentry("timebase");
-	timebase = atoi(se->value);
+	float new_tb, old_tb;
 
 	se = get_sysentry("purr");
 	new_purr = strtoll(se->value, NULL, 0);
 	old_purr = strtoll(se->old_value, NULL, 0);
 
-	physc = (new_purr - old_purr)/timebase/elapsed;
+	se = get_sysentry("tbr");
+	if (se->value[0] != '\0') {
+		new_tb = strtoll(se->value, NULL, 0);
+		old_tb = strtoll(se->old_value, NULL, 0);
+
+		physc = (new_purr - old_purr) / (new_tb - old_tb);
+	} else {
+		elapsed = elapsed_time() / 1000000.0;
+
+		se = get_sysentry("timebase");
+		timebase = atoi(se->value);
+
+		physc = (new_purr - old_purr)/timebase/elapsed;
+	}
+
 	sprintf(buf, "%.6f", physc);
 }
 
diff --git a/src/lparstat.h b/src/lparstat.h
index c447692..3aee192 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -129,6 +129,8 @@ struct sysentry system_data[] = {
 	 .descr = "Virtual Processor Dispersions"},
 	{.name = "purr",
 	 .descr = "Processor Utilization Resource Register"},
+	{.name = "tbr",
+	 .descr = "Timebase Register"},
 	{.name = "partition_active_processors",
 	 .descr = "Online Virtual CPUs"},
 	{.name = "partition_potential_processors",