Skip to content

Commit

Permalink
Merge tag 'powerpc-4.18-5' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:
 "One fix for a regression in a recent TLB flush optimisation, which
  caused us to incorrectly not send TLB invalidations to coprocessors.

  Thanks to Frederic Barrat, Nicholas Piggin, Vaibhav Jain"

* tag 'powerpc-4.18-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/64s/radix: Fix missing global invalidations when removing copro
  • Loading branch information
torvalds committed Aug 3, 2018
2 parents 7827fc7 + cca19f0 commit 2ed7533
Showing 1 changed file with 21 additions and 12 deletions.
33 changes: 21 additions & 12 deletions arch/powerpc/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,24 +143,33 @@ static inline void mm_context_remove_copro(struct mm_struct *mm)
{
int c;

c = atomic_dec_if_positive(&mm->context.copros);

/* Detect imbalance between add and remove */
WARN_ON(c < 0);

/*
* Need to broadcast a global flush of the full mm before
* decrementing active_cpus count, as the next TLBI may be
* local and the nMMU and/or PSL need to be cleaned up.
* Should be rare enough so that it's acceptable.
* When removing the last copro, we need to broadcast a global
* flush of the full mm, as the next TLBI may be local and the
* nMMU and/or PSL need to be cleaned up.
*
* Both the 'copros' and 'active_cpus' counts are looked at in
* flush_all_mm() to determine the scope (local/global) of the
* TLBIs, so we need to flush first before decrementing
* 'copros'. If this API is used by several callers for the
* same context, it can lead to over-flushing. It's hopefully
* not common enough to be a problem.
*
* Skip on hash, as we don't know how to do the proper flush
* for the time being. Invalidations will remain global if
* used on hash.
* used on hash. Note that we can't drop 'copros' either, as
* it could make some invalidations local with no flush
* in-between.
*/
if (c == 0 && radix_enabled()) {
if (radix_enabled()) {
flush_all_mm(mm);
dec_mm_active_cpus(mm);

c = atomic_dec_if_positive(&mm->context.copros);
/* Detect imbalance between add and remove */
WARN_ON(c < 0);

if (c == 0)
dec_mm_active_cpus(mm);
}
}
#else
Expand Down

0 comments on commit 2ed7533

Please sign in to comment.