mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 18:13:04 +00:00
powerpc/mm: Fix some SMP issues with MMU context handling
This patch fixes a couple of issues that can happen as a result of steal_context() dropping the context_lock when all possible PIDs are ineligible for stealing (hopefully an extremely hard to hit occurence). This case exposes the possibility of a stale context_mm[] entry to be seen since destroy_context() doesn't clear it and the free map isn't re-tested. It also means steal_context() will not notice a context freed while the lock was help, thus possibly trying to steal a context when a free one was available. This fixes it by always returning to the caller from steal_context when it dropped the lock with a return value that causes the caller to re-samble the number of free contexts, along with properly clearing the context_mm[] array for destroyed contexts. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
ec097c84df
commit
3035c8634f
@ -73,7 +73,6 @@ static unsigned int steal_context_smp(unsigned int id)
|
||||
struct mm_struct *mm;
|
||||
unsigned int cpu, max;
|
||||
|
||||
again:
|
||||
max = last_context - first_context;
|
||||
|
||||
/* Attempt to free next_context first and then loop until we manage */
|
||||
@ -108,7 +107,9 @@ static unsigned int steal_context_smp(unsigned int id)
|
||||
spin_unlock(&context_lock);
|
||||
cpu_relax();
|
||||
spin_lock(&context_lock);
|
||||
goto again;
|
||||
|
||||
/* This will cause the caller to try again */
|
||||
return MMU_NO_CONTEXT;
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
@ -194,6 +195,8 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
|
||||
WARN_ON(prev->context.active < 1);
|
||||
prev->context.active--;
|
||||
}
|
||||
|
||||
again:
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/* If we already have a valid assigned context, skip all that */
|
||||
@ -212,7 +215,8 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
|
||||
#ifdef CONFIG_SMP
|
||||
if (num_online_cpus() > 1) {
|
||||
id = steal_context_smp(id);
|
||||
goto stolen;
|
||||
if (id == MMU_NO_CONTEXT)
|
||||
goto again;
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
id = steal_context_up(id);
|
||||
@ -286,8 +290,8 @@ void destroy_context(struct mm_struct *mm)
|
||||
mm->context.id = MMU_NO_CONTEXT;
|
||||
#ifdef DEBUG_MAP_CONSISTENCY
|
||||
mm->context.active = 0;
|
||||
context_mm[id] = NULL;
|
||||
#endif
|
||||
context_mm[id] = NULL;
|
||||
nr_free_contexts++;
|
||||
}
|
||||
spin_unlock(&context_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user