In guest, Set idle_hint to 1 when the prev_cpu of a vCPU goes into idle state, similarly set idle_hint to 0 when exiting an idle state.
Since the idle_hint is in VPA region, the available_idle_cpu() in guest can read this region every time to find if a vCPU can be scheduled instantly by the hypervsior or not. Signed-off-by: Parth Shah <pa...@linux.ibm.com> --- arch/powerpc/include/asm/paravirt.h | 12 ++++++++++-- kernel/sched/idle.c | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h index bcb7b5f917be..b20e4d25bd00 100644 --- a/arch/powerpc/include/asm/paravirt.h +++ b/arch/powerpc/include/asm/paravirt.h @@ -21,6 +21,12 @@ static inline bool is_shared_processor(void) return static_branch_unlikely(&shared_processor); } +static inline int idle_hint_of(int cpu) +{ + __be32 idle_hint = READ_ONCE(lppaca_of(cpu).idle_hint); + return be32_to_cpu(idle_hint); +} + /* If bit 0 is set, the cpu has been preempted */ static inline u32 yield_count_of(int cpu) { @@ -109,8 +115,10 @@ static inline bool vcpu_is_preempted(int cpu) } #endif - if (yield_count_of(cpu) & 1) - return true; + if (yield_count_of(cpu) & 1) { + if (idle_hint_of(cpu) == 0) + return true; + } return false; } diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 7ca3d3d86c2a..fdc8d1d474f0 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -7,6 +7,7 @@ * tasks which are handled in sched/fair.c ) */ #include "sched.h" +#include <asm/idle_hint.h> #include <trace/events/power.h> @@ -290,6 +291,7 @@ static void do_idle(void) arch_cpu_idle_dead(); } + set_idle_hint(cpu, 1); arch_cpu_idle_enter(); rcu_nocb_flush_deferred_wakeup(); @@ -306,6 +308,7 @@ static void do_idle(void) cpuidle_idle_call(); } arch_cpu_idle_exit(); + set_idle_hint(cpu, 0); } /* -- 2.26.3