]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
powerpc/pseries: lparcfg calculate PURR on demand
authorNicholas Piggin <npiggin@gmail.com>
Fri, 4 May 2018 17:19:30 +0000 (03:19 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Sun, 3 Jun 2018 10:40:27 +0000 (20:40 +1000)
For SPLPAR, lparcfg provides a sum of PURR registers for all CPUs.
Currently this is done by reading PURR in context switch and timer
interrupt, and storing that into a per-CPU variable. These are summed
to provide the value.

This does not work with all timer schemes (e.g., NO_HZ_FULL), and it
is sub-optimal for performance because it reads the PURR register on
every context switch, although that's been difficult to distinguish
from noise in the contxt_switch microbenchmark.

This patch implements the sum by calling a function on each CPU, to
read and add PURR values of each CPU.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/time.h
arch/powerpc/kernel/process.c
arch/powerpc/kernel/time.c
arch/powerpc/platforms/pseries/lparcfg.c

index db546c034905a3365fdfe4d58f6621d7c32cf10c..c965c79765c4e32f07188edc44fe09662c2ebeb3 100644 (file)
@@ -196,14 +196,6 @@ extern u64 mulhdu(u64, u64);
 extern void div128_by_32(u64 dividend_high, u64 dividend_low,
                         unsigned divisor, struct div_result *dr);
 
-/* Used to store Processor Utilization register (purr) values */
-
-struct cpu_usage {
-        u64 current_tb;  /* Holds the current purr register values */
-};
-
-DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
-
 extern void secondary_cpu_time_init(void);
 extern void __init time_init(void);
 
index f4e5291584c55fae4cbfa10b956faf4fc0475075..2a7fa5000ccecec51c630b13bba63434790e1ed6 100644 (file)
@@ -846,10 +846,6 @@ bool ppc_breakpoint_available(void)
 }
 EXPORT_SYMBOL_GPL(ppc_breakpoint_available);
 
-#ifdef CONFIG_PPC64
-DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-#endif
-
 static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
                              struct arch_hw_breakpoint *b)
 {
@@ -1182,16 +1178,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
        WARN_ON(!irqs_disabled());
 
-#ifdef CONFIG_PPC64
-       /*
-        * Collect processor utilization data per process
-        */
-       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-               struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array);
-               cu->current_tb = mfspr(SPRN_PURR);
-       }
-#endif /* CONFIG_PPC64 */
-
 #ifdef CONFIG_PPC_BOOK3S_64
        batch = this_cpu_ptr(&ppc64_tlb_batch);
        if (batch->active) {
index e7e8611e88633956862380d1bb19b95173b1746e..1fe6a24357e7d0030491382db337332b2e134b7e 100644 (file)
@@ -597,14 +597,6 @@ static void __timer_interrupt(void)
                __this_cpu_inc(irq_stat.timer_irqs_others);
        }
 
-#ifdef CONFIG_PPC64
-       /* collect purr register values often, for accurate calculations */
-       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-               struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array);
-               cu->current_tb = mfspr(SPRN_PURR);
-       }
-#endif
-
        trace_timer_interrupt_exit(regs);
 }
 
index c508c938dc71e0bc0d76d0764ffe81ddcd5f8b8f..7c872dc01bdb0aa4389302b89eec898b710c0462 100644 (file)
  * Track sum of all purrs across all processors. This is used to further
  * calculate usage values by different applications
  */
+static void cpu_get_purr(void *arg)
+{
+       atomic64_t *sum = arg;
+
+       atomic64_add(mfspr(SPRN_PURR), sum);
+}
+
 static unsigned long get_purr(void)
 {
-       unsigned long sum_purr = 0;
-       int cpu;
+       atomic64_t purr = ATOMIC64_INIT(0);
 
-       for_each_possible_cpu(cpu) {
-               struct cpu_usage *cu;
+       on_each_cpu(cpu_get_purr, &purr, 1);
 
-               cu = &per_cpu(cpu_usage_array, cpu);
-               sum_purr += cu->current_tb;
-       }
-       return sum_purr;
+       return atomic64_read(&purr);
 }
 
 /*