idle.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. #ifndef _ASM_POWERPC_IDLE_H
  3. #define _ASM_POWERPC_IDLE_H
  4. #include <asm/runlatch.h>
  5. #include <asm/paca.h>
  6. #ifdef CONFIG_PPC_PSERIES
  7. DECLARE_PER_CPU(u64, idle_spurr_cycles);
  8. DECLARE_PER_CPU(u64, idle_entry_purr_snap);
  9. DECLARE_PER_CPU(u64, idle_entry_spurr_snap);
  10. static inline void snapshot_purr_idle_entry(void)
  11. {
  12. *this_cpu_ptr(&idle_entry_purr_snap) = mfspr(SPRN_PURR);
  13. }
  14. static inline void snapshot_spurr_idle_entry(void)
  15. {
  16. *this_cpu_ptr(&idle_entry_spurr_snap) = mfspr(SPRN_SPURR);
  17. }
  18. static inline void update_idle_purr_accounting(void)
  19. {
  20. u64 wait_cycles;
  21. u64 in_purr = *this_cpu_ptr(&idle_entry_purr_snap);
  22. wait_cycles = be64_to_cpu(get_lppaca()->wait_state_cycles);
  23. wait_cycles += mfspr(SPRN_PURR) - in_purr;
  24. get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);
  25. }
  26. static inline void update_idle_spurr_accounting(void)
  27. {
  28. u64 *idle_spurr_cycles_ptr = this_cpu_ptr(&idle_spurr_cycles);
  29. u64 in_spurr = *this_cpu_ptr(&idle_entry_spurr_snap);
  30. *idle_spurr_cycles_ptr += mfspr(SPRN_SPURR) - in_spurr;
  31. }
  32. static inline void pseries_idle_prolog(void)
  33. {
  34. ppc64_runlatch_off();
  35. snapshot_purr_idle_entry();
  36. snapshot_spurr_idle_entry();
  37. /*
  38. * Indicate to the HV that we are idle. Now would be
  39. * a good time to find other work to dispatch.
  40. */
  41. get_lppaca()->idle = 1;
  42. }
  43. static inline void pseries_idle_epilog(void)
  44. {
  45. update_idle_purr_accounting();
  46. update_idle_spurr_accounting();
  47. get_lppaca()->idle = 0;
  48. ppc64_runlatch_on();
  49. }
  50. static inline u64 read_this_idle_purr(void)
  51. {
  52. /*
  53. * If we are reading from an idle context, update the
  54. * idle-purr cycles corresponding to the last idle period.
  55. * Since the idle context is not yet over, take a fresh
  56. * snapshot of the idle-purr.
  57. */
  58. if (unlikely(get_lppaca()->idle == 1)) {
  59. update_idle_purr_accounting();
  60. snapshot_purr_idle_entry();
  61. }
  62. return be64_to_cpu(get_lppaca()->wait_state_cycles);
  63. }
  64. static inline u64 read_this_idle_spurr(void)
  65. {
  66. /*
  67. * If we are reading from an idle context, update the
  68. * idle-spurr cycles corresponding to the last idle period.
  69. * Since the idle context is not yet over, take a fresh
  70. * snapshot of the idle-spurr.
  71. */
  72. if (get_lppaca()->idle == 1) {
  73. update_idle_spurr_accounting();
  74. snapshot_spurr_idle_entry();
  75. }
  76. return *this_cpu_ptr(&idle_spurr_cycles);
  77. }
  78. #endif /* CONFIG_PPC_PSERIES */
  79. #endif