@@ -659,18 +659,78 @@ static int __init vcpudispatch_stats_procfs_init(void)
659659machine_device_initcall (pseries , vcpudispatch_stats_procfs_init );
660660
661661#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
662+ #define STEAL_MULTIPLE (STEAL_RATIO * STEAL_RATIO)
663+
664+ static u8 steal_interval = 1 ;
665+
666+ static bool should_cpu_process_steal (int cpu )
667+ {
668+ if (cpu == cpumask_first (cpu_online_mask ))
669+ return true;
670+
671+ return false;
672+ }
673+
674+ extern bool process_steal_enable ;
675+ static void process_steal (int cpu )
676+ {
677+ unsigned long steal_ratio , delta_tb , interval_tb ;
678+ static unsigned long next_tb , prev_steal ;
679+ unsigned long tb = mftb ();
680+ unsigned long steal = 0 ;
681+ unsigned int i ;
682+
683+ if (!process_steal_enable )
684+ return ;
685+
686+ if (!should_cpu_process_steal (cpu ))
687+ return ;
688+
689+ if (tb < next_tb )
690+ return ;
691+
692+ for_each_online_cpu (i ) {
693+ struct lppaca * lppaca = & lppaca_of (i );
694+
695+ steal += be64_to_cpu (READ_ONCE (lppaca -> ready_enqueue_tb ));
696+ steal += be64_to_cpu (READ_ONCE (lppaca -> enqueue_dispatch_tb ));
697+ }
698+
699+ if (!steal_interval )
700+ steal_interval = 1 ;
701+
702+ interval_tb = steal_interval * tb_ticks_per_sec ;
703+ if (next_tb && prev_steal ) {
704+ delta_tb = max (tb - (next_tb - interval_tb ), 1 );
705+ steal_ratio = (steal - prev_steal ) * STEAL_MULTIPLE ;
706+ steal_ratio /= (delta_tb * num_online_cpus ());
707+ trigger_softoffline (steal_ratio );
708+ }
709+
710+ next_tb = tb + interval_tb ;
711+ prev_steal = steal ;
712+ }
713+
662714u64 pseries_paravirt_steal_clock (int cpu )
663715{
664716 struct lppaca * lppaca = & lppaca_of (cpu );
717+ unsigned long steal ;
718+
719+ steal = be64_to_cpu (READ_ONCE (lppaca -> ready_enqueue_tb ));
720+ steal += be64_to_cpu (READ_ONCE (lppaca -> enqueue_dispatch_tb ));
721+
722+ if (is_shared_processor () && !is_kvm_guest ())
723+ process_steal (cpu );
665724
666725 /*
667726 * VPA steal time counters are reported at TB frequency. Hence do a
668- * conversion to ns before returning
727+ * conversion to ns before using.
669728 */
670- return tb_to_ns (be64_to_cpu (READ_ONCE (lppaca -> enqueue_dispatch_tb )) +
671- be64_to_cpu (READ_ONCE (lppaca -> ready_enqueue_tb )));
729+ steal = tb_to_ns (steal );
730+
731+ return steal ;
672732}
673- #endif
733+ #endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */
674734
675735#endif /* CONFIG_PPC_SPLPAR */
676736
@@ -2025,6 +2085,9 @@ static int __init vpa_debugfs_init(void)
20252085 debugfs_create_file (name , 0400 , vpa_dir , (void * )i , & vpa_fops );
20262086 }
20272087
2088+ #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
2089+ debugfs_create_u8 ("steal_interval_secs" , 0600 , arch_debugfs_dir , & steal_interval );
2090+ #endif
20282091 return 0 ;
20292092}
20302093machine_arch_initcall (pseries , vpa_debugfs_init );
0 commit comments