From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753533AbeEVXul (ORCPT ); Tue, 22 May 2018 19:50:41 -0400 Received: from mail-pl0-f65.google.com ([209.85.160.65]:33232 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753324AbeEVXuj (ORCPT ); Tue, 22 May 2018 19:50:39 -0400 X-Google-Smtp-Source: AB8JxZpCPpYRBcnLh28T5cJYsPJfG2KdQHJbKuafSm/fbhsOgNe4j/3UtXaEKXfbNKFEnPgUULHL/w== From: "Joel Fernandes (Google)" X-Google-Original-From: "Joel Fernandes (Google)" To: linux-kernel@vger.kernel.org Cc: "Joel Fernandes (Google)" , "Rafael J . Wysocki" , Peter Zijlstra , Ingo Molnar , Patrick Bellasi , Juri Lelli , Luca Abeni , Todd Kjos , claudio@evidence.eu.com, kernel-team@android.com, linux-pm@vger.kernel.org Subject: [PATCH RFC] schedutil: Address the r/w ordering race in kthread Date: Tue, 22 May 2018 16:50:28 -0700 Message-Id: <20180522235028.80564-1-joel@joelfernandes.org> X-Mailer: git-send-email 2.17.0.441.gb46fe60e1d-goog Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently there is a race in schedutil code for slow-switch single-CPU systems. Fix it by enforcing ordering the write to work_in_progress to happen before the read of next_freq. Kthread Sched update sugov_work() sugov_update_single() lock(); // The CPU is free to rearrange below // two in any order, so it may clear // the flag first and then read next // freq. Lets assume it does. work_in_progress = false if (work_in_progress) return; sg_policy->next_freq = 0; freq = sg_policy->next_freq; sg_policy->next_freq = real-freq; unlock(); Reported-by: Viresh Kumar CC: Rafael J. Wysocki CC: Peter Zijlstra CC: Ingo Molnar CC: Patrick Bellasi CC: Juri Lelli Cc: Luca Abeni CC: Todd Kjos CC: claudio@evidence.eu.com CC: kernel-team@android.com CC: linux-pm@vger.kernel.org Signed-off-by: Joel Fernandes (Google) --- I split this into separate patch, because this race can also happen in mainline. kernel/sched/cpufreq_schedutil.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 5c482ec38610..ce7749da7a44 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -401,6 +401,13 @@ static void sugov_work(struct kthread_work *work) */ raw_spin_lock_irqsave(&sg_policy->update_lock, flags); freq = sg_policy->next_freq; + + /* + * sugov_update_single can access work_in_progress without update_lock, + * make sure next_freq is read before work_in_progress is set. + */ + smp_mb(); + sg_policy->work_in_progress = false; raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); -- 2.17.0.441.gb46fe60e1d-goog