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