]> git.baikalelectronics.ru Git - kernel.git/commitdiff
powerpc/pseries: Implement CONFIG_PARAVIRT_TIME_ACCOUNTING
authorNicholas Piggin <npiggin@gmail.com>
Fri, 2 Sep 2022 08:53:14 +0000 (18:53 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 5 Sep 2022 04:14:02 +0000 (14:14 +1000)
CONFIG_VIRT_CPU_ACCOUNTING_GEN under pseries does not provide stolen
time accounting unless CONFIG_PARAVIRT_TIME_ACCOUNTING is enabled.
Implement this using the VPA accumulated wait counters.

Note this will not work on current KVM hosts because KVM does not
implement the VPA dispatch counters (yet). It could be implemented
with the dispatch trace log as it is for VIRT_CPU_ACCOUNTING_NATIVE,
but that is not necessary for the more limited accounting provided
by PARAVIRT_TIME_ACCOUNTING, and it is more expensive, complex, and
has downsides like potential log wrap.

From Shrikanth:

  [...] it was tested on Power10 [PowerVM] Shared LPAR. system has two
  LPAR. we will call first one LPAR1 and second one as LPAR2. Test was
  carried out in SMT=1. Similar observation was seen in SMT=8 as well.

  LPAR config header from each LPAR is below. LPAR1 is twice as big as
  LPAR2. Since Both are sharing the same underlying hardware, work
  stealing will happen when both the LPAR's are contending for the same
  resource.

  LPAR1:
  type=Shared mode=Uncapped smt=Off lcpu=40 cpus=40 ent=20.00
  LPAR2:
  type=Shared mode=Uncapped smt=Off lcpu=20 cpus=40 ent=10.00

  mpstat was used to check for the utilization. stress-ng has been used
  as the workload. Few cases are tested. when the both LPAR are idle
  there is no steal time. when LPAR1 starts running at 100% which
  consumes all of the physical resource, steal time starts to get
  accounted.  With LPAR1 running at 100% and LPAR2 starts running, steal
  time starts increasing. This is as expected. When the LPAR2 Load is
  increased further, steal time increases further.

  Case 1: 0% LPAR1; 0% LPAR2
   %usr  %nice   %sys %iowait  %irq  %soft %steal %guest %gnice  %idle
   0.00   0.00   0.05   0.00   0.00   0.00   0.00   0.00   0.00  99.95

  Case 2: 100% LPAR1; 0% LPAR2
   %usr  %nice   %sys %iowait  %irq  %soft %steal %guest %gnice  %idle
  97.68   0.00   0.00   0.00   0.00   0.00   2.32   0.00   0.00   0.00

  Case 3: 100% LPAR1; 50% LPAR2
   %usr  %nice   %sys %iowait  %irq  %soft %steal %guest %gnice  %idle
  86.34   0.00   0.10   0.00   0.00   0.03  13.54   0.00   0.00   0.00

  Case 4: 100% LPAR1; 100% LPAR2
   %usr  %nice   %sys %iowait  %irq  %soft %steal %guest %gnice  %idle
  78.54   0.00   0.07   0.00   0.00   0.02  21.36   0.00   0.00   0.00

  Case 5: 50% LPAR1; 100% LPAR2
   %usr  %nice   %sys %iowait  %irq  %soft %steal %guest %gnice  %idle
  49.37   0.00   0.00   0.00   0.00   0.00   1.17   0.00   0.00  49.47

  Patch is accounting for the steal time and basic tests are holding
  good.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Tested-by: Shrikanth Hegde <sshegde@linux.ibm.com>
[mpe: Add SPDX tag to new paravirt_api_clock.h]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220902085316.2071519-3-npiggin@gmail.com
Documentation/admin-guide/kernel-parameters.txt
arch/powerpc/include/asm/paravirt.h
arch/powerpc/include/asm/paravirt_api_clock.h [new file with mode: 0644]
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/setup.c

index d7f30902fda02fe09ea9eaa6563065b1655b0c2c..d62fdd0ac49745217aafc8062076447e18193981 100644 (file)
                        [X86,PV_OPS] Disable paravirtualized VMware scheduler
                        clock and use the default one.
 
-       no-steal-acc    [X86,PV_OPS,ARM64] Disable paravirtualized steal time
-                       accounting. steal time is computed, but won't
-                       influence scheduler behaviour
+       no-steal-acc    [X86,PV_OPS,ARM64,PPC/PSERIES] Disable paravirtualized
+                       steal time accounting. steal time is computed, but
+                       won't influence scheduler behaviour
 
        nolapic         [X86-32,APIC] Do not enable or use the local APIC.
 
index eb7df559ae7497c8bee9bb57ac9c9bc59302f3a0..f5ba1a3c41f8e508fd9d5e94224b24bbb4827bc0 100644 (file)
@@ -21,6 +21,18 @@ static inline bool is_shared_processor(void)
        return static_branch_unlikely(&shared_processor);
 }
 
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+extern struct static_key paravirt_steal_enabled;
+extern struct static_key paravirt_steal_rq_enabled;
+
+u64 pseries_paravirt_steal_clock(int cpu);
+
+static inline u64 paravirt_steal_clock(int cpu)
+{
+       return pseries_paravirt_steal_clock(cpu);
+}
+#endif
+
 /* If bit 0 is set, the cpu has been ceded, conferred, or preempted */
 static inline u32 yield_count_of(int cpu)
 {
diff --git a/arch/powerpc/include/asm/paravirt_api_clock.h b/arch/powerpc/include/asm/paravirt_api_clock.h
new file mode 100644 (file)
index 0000000..d25ca7a
--- /dev/null
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <asm/paravirt.h>
index fb6499977f99a56d4fa5055c035701f61f4a510d..a3b4d99567cbec70bdfbc49e49a920269648561b 100644 (file)
@@ -23,13 +23,21 @@ config PPC_PSERIES
        select SWIOTLB
        default y
 
+config PARAVIRT
+       bool
+
 config PARAVIRT_SPINLOCKS
        bool
 
+config PARAVIRT_TIME_ACCOUNTING
+       select PARAVIRT
+       bool
+
 config PPC_SPLPAR
        bool "Support for shared-processor logical partitions"
        depends on PPC_PSERIES
        select PARAVIRT_SPINLOCKS if PPC_QUEUED_SPINLOCKS
+       select PARAVIRT_TIME_ACCOUNTING if VIRT_CPU_ACCOUNTING_GEN
        default y
        help
          Enabling this option will make the kernel run more efficiently
index e6c117fb64913fe45cda16c169deb5b7080a0a75..97ef6499e50191708afe9f4d72bdcad75717795b 100644 (file)
@@ -660,6 +660,17 @@ static int __init vcpudispatch_stats_procfs_init(void)
 }
 
 machine_device_initcall(pseries, vcpudispatch_stats_procfs_init);
+
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+u64 pseries_paravirt_steal_clock(int cpu)
+{
+       struct lppaca *lppaca = &lppaca_of(cpu);
+
+       return be64_to_cpu(READ_ONCE(lppaca->enqueue_dispatch_tb)) +
+               be64_to_cpu(READ_ONCE(lppaca->ready_enqueue_tb));
+}
+#endif
+
 #endif /* CONFIG_PPC_SPLPAR */
 
 void vpa_init(int cpu)
index 489f4c4df468a1e49634c49ffe6cc3e508e24a62..5e44c65a032c3596d1c37d08c0cca9cbc806f821 100644 (file)
 DEFINE_STATIC_KEY_FALSE(shared_processor);
 EXPORT_SYMBOL(shared_processor);
 
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+struct static_key paravirt_steal_enabled;
+struct static_key paravirt_steal_rq_enabled;
+
+static bool steal_acc = true;
+static int __init parse_no_stealacc(char *arg)
+{
+       steal_acc = false;
+       return 0;
+}
+
+early_param("no-steal-acc", parse_no_stealacc);
+#endif
+
 int CMO_PrPSP = -1;
 int CMO_SecPSP = -1;
 unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);
@@ -834,6 +848,11 @@ static void __init pSeries_setup_arch(void)
                if (lppaca_shared_proc(get_lppaca())) {
                        static_branch_enable(&shared_processor);
                        pv_spinlocks_init();
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+                       static_key_slow_inc(&paravirt_steal_enabled);
+                       if (steal_acc)
+                               static_key_slow_inc(&paravirt_steal_rq_enabled);
+#endif
                }
 
                ppc_md.power_save = pseries_lpar_idle;