Skip to content

Commit 60c8dcc

Browse files
npigginFox Snowpatch
authored andcommitted
powerpc/64s/radix: add warning and comments in mm_cpumask trim
Add a comment explaining part of the logic for mm_cpumask trimming, and add a (hopefully graceful) check and warning in case something gets it wrong. Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
1 parent 3ae0387 commit 60c8dcc

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

arch/powerpc/mm/book3s64/radix_tlb.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,14 @@ static void do_exit_flush_lazy_tlb(void *arg)
653653
{
654654
struct mm_struct *mm = arg;
655655
unsigned long pid = mm->context.id;
656+
int cpu = smp_processor_id();
656657

657658
/*
658659
* A kthread could have done a mmget_not_zero() after the flushing CPU
659-
* checked mm_is_singlethreaded, and be in the process of
660-
* kthread_use_mm when interrupted here. In that case, current->mm will
661-
* be set to mm, because kthread_use_mm() setting ->mm and switching to
662-
* the mm is done with interrupts off.
660+
* checked mm_cpumask, and be in the process of kthread_use_mm when
661+
* interrupted here. In that case, current->mm will be set to mm,
662+
* because kthread_use_mm() setting ->mm and switching to the mm is
663+
* done with interrupts off.
663664
*/
664665
if (current->mm == mm)
665666
goto out_flush;
@@ -673,8 +674,22 @@ static void do_exit_flush_lazy_tlb(void *arg)
673674
mmdrop(mm);
674675
}
675676

676-
atomic_dec(&mm->context.active_cpus);
677-
cpumask_clear_cpu(smp_processor_id(), mm_cpumask(mm));
677+
/*
678+
* This IPI is only initiated from a CPU which is running mm which
679+
* is a single-threaded process, so there will not be another racing
680+
* IPI coming in where we would find our cpumask already clear.
681+
*
682+
* Nothing else clears our bit in the cpumask except CPU offlining,
683+
* in which case we should not be taking IPIs here. However check
684+
* this just in case the logic is wrong somewhere, and don't underflow
685+
* the active_cpus count.
686+
*/
687+
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
688+
atomic_dec(&mm->context.active_cpus);
689+
cpumask_clear_cpu(cpu, mm_cpumask(mm));
690+
} else {
691+
WARN_ON_ONCE(1);
692+
}
678693

679694
out_flush:
680695
_tlbiel_pid(pid, RIC_FLUSH_ALL);

0 commit comments

Comments
 (0)