Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'powerpc-4.18-5' of git://git.kernel.org/pub/scm/linux/kernel/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

+21 -12
+21 -12
arch/powerpc/include/asm/mmu_context.h
··· 143 143 { 144 144 int c; 145 145 146 - c = atomic_dec_if_positive(&mm->context.copros); 147 - 148 - /* Detect imbalance between add and remove */ 149 - WARN_ON(c < 0); 150 - 151 146 /* 152 - * Need to broadcast a global flush of the full mm before 153 - * decrementing active_cpus count, as the next TLBI may be 154 - * local and the nMMU and/or PSL need to be cleaned up. 155 - * Should be rare enough so that it's acceptable. 147 + * When removing the last copro, we need to broadcast a global 148 + * flush of the full mm, as the next TLBI may be local and the 149 + * nMMU and/or PSL need to be cleaned up. 150 + * 151 + * Both the 'copros' and 'active_cpus' counts are looked at in 152 + * flush_all_mm() to determine the scope (local/global) of the 153 + * TLBIs, so we need to flush first before decrementing 154 + * 'copros'. If this API is used by several callers for the 155 + * same context, it can lead to over-flushing. It's hopefully 156 + * not common enough to be a problem. 156 157 * 157 158 * Skip on hash, as we don't know how to do the proper flush 158 159 * for the time being. Invalidations will remain global if 159 - * used on hash. 160 + * used on hash. Note that we can't drop 'copros' either, as 161 + * it could make some invalidations local with no flush 162 + * in-between. 160 163 */ 161 - if (c == 0 && radix_enabled()) { 164 + if (radix_enabled()) { 162 165 flush_all_mm(mm); 163 - dec_mm_active_cpus(mm); 166 + 167 + c = atomic_dec_if_positive(&mm->context.copros); 168 + /* Detect imbalance between add and remove */ 169 + WARN_ON(c < 0); 170 + 171 + if (c == 0) 172 + dec_mm_active_cpus(mm); 164 173 } 165 174 } 166 175 #else