From: Yunfeng Ye yeyunfeng@huawei.com
mainline inclusion from mainline-5.14-rc1 commit 96c9b90396f9ab6caf13b4ebf00095818ac53b7f category: feature feature: Deep isolation bugzilla: https://gitee.com/openeuler/kernel/issues/I4N00D CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The idle_exittime field of tick_sched is used to record the time when the idle state was left. but currently the idle_exittime is updated in the function tick_nohz_restart_sched_tick(), which is not always in idle state when nohz_full is configured:
tick_irq_exit tick_nohz_irq_exit tick_nohz_full_update_tick tick_nohz_restart_sched_tick ts->idle_exittime = now;
It's thus overwritten by mistake on nohz_full tick restart. Move the update to the appropriate idle exit path instead.
Signed-off-by: Yunfeng Ye yeyunfeng@huawei.com Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Ingo Molnar mingo@kernel.org Acked-by: Peter Zijlstra peterz@infradead.org Link: https://lore.kernel.org/r/20210512232924.150322-5-frederic@kernel.org Reviewed-by: Chao Liu liuchao173@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/time/tick-sched.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f9ec75c35ac5..e53a2a835f30 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -901,8 +901,6 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now) * Cancel the scheduled timer and restore the tick */ ts->tick_stopped = 0; - ts->idle_exittime = now; - tick_nohz_restart(ts, now); }
@@ -1170,10 +1168,13 @@ unsigned long tick_nohz_get_idle_calls(void) return ts->idle_calls; }
-static void tick_nohz_account_idle_ticks(struct tick_sched *ts) +static void tick_nohz_account_idle_time(struct tick_sched *ts, + ktime_t now) { unsigned long ticks;
+ ts->idle_exittime = now; + if (vtime_accounting_enabled_this_cpu()) return; /* @@ -1194,8 +1195,9 @@ void tick_nohz_idle_restart_tick(void) struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
if (ts->tick_stopped) { - tick_nohz_restart_sched_tick(ts, ktime_get()); - tick_nohz_account_idle_ticks(ts); + ktime_t now = ktime_get(); + tick_nohz_restart_sched_tick(ts, now); + tick_nohz_account_idle_time(ts, now); } }
@@ -1206,7 +1208,7 @@ static void tick_nohz_idle_update_tick(struct tick_sched *ts, ktime_t now) else tick_nohz_restart_sched_tick(ts, now);
- tick_nohz_account_idle_ticks(ts); + tick_nohz_account_idle_time(ts, now); }
/**