Patch "powerpc/mm: Ensure IRQs are off in switch_mm()" has been added to the 4.11-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
powerpc/mm: Ensure IRQs are off in switch_mm()
to the 4.11-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
powerpc-mm-ensure-irqs-are-off-in-switch_mm.patch
and it can be found in the queue-4.11 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
9765ad134a00a01cbcc69c78ff6defbfad209bc5Mon Sep 17 00:00:00 2001
From: David Gibson <[email protected]>
Date: Wed, 19 Apr 2017 16:38:26 +1000
Subject: powerpc/mm: Ensure IRQs are off in switch_mm()
From: David Gibson <[email protected]>
commit 9765ad134a00a01cbcc69c78ff6defbfad209bc5 upstream.
powerpc expects IRQs to already be (soft) disabled when switch_mm() is called, as made clear in the commit message of 9c1e105238c4 ("powerpc: Allow perf_counters to access user memory at interrupt time").
Aside from any race conditions that might exist between switch_mm() and an IRQ, there is also an unconditional hard_irq_disable() in switch_slb(). If that isn't followed at some point by an IRQ enable then interrupts will remain disabled until we return to userspace.
It is true that when switch_mm() is called from the scheduler IRQs are off, but not when it's called by use_mm(). Looking closer we see that last year in commit f98db6013c55 ("sched/core: Add switch_mm_irqs_off() and use it in the scheduler") this was made more explicit by the addition of switch_mm_irqs_off() which is now called by the scheduler, vs switch_mm() which is used by use_mm().
Arguably it is a bug in use_mm() to call switch_mm() in a different context than it expects, but fixing that will take time.
This was discovered recently when vhost started throwing warnings such as:
BUG: sleeping function called from invalid context at kernel/mutex.c:578
in_atomic(): 0, irqs_disabled(): 1, pid: 10768, name: vhost-10760
no locks held by vhost-10760/10768.
irq event stamp: 10
hardirqs last enabled at (9): _raw_spin_unlock_irq+0x40/0x80
hardirqs last disabled at (10): switch_slb+0x2e4/0x490
softirqs last enabled at (0): copy_process+0x5e8/0x1260
softirqs last disabled at (0): (null)
Call Trace:
show_stack+0x88/0x390 (unreliable)
dump_stack+0x30/0x44
__might_sleep+0x1c4/0x2d0
mutex_lock_nested+0x74/0x5c0
cgroup_attach_task_all+0x5c/0x180
vhost_attach_cgroups_work+0x58/0x80 [vhost]
vhost_worker+0x24c/0x3d0 [vhost]
kthread+0xec/0x100
ret_from_kernel_thread+0x5c/0xd4Prior to commit 04b96e5528ca ("vhost: lockless enqueuing") (Aug 2016) the vhost_worker() would do a spin_unlock_irq() not long after calling use_mm(), which had the effect of reenabling IRQs. Since that commit removed the locking in vhost_worker() the body of the vhost_worker() loop now runs with interrupts off causing the warnings.
This patch addresses the problem by making the powerpc code mirror the x86 code, ie. we disable interrupts in switch_mm(), and optimise the scheduler case by defining switch_mm_irqs_off().
--- arch/powerpc/include/asm/mmu_context.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/mmu_context.h +15 -2
@@ -70,8 +70,9 @@ extern void drop_cop(unsigned long acop,* switch_mm is the entry point called from the architecture independent * code in kernel/sched/core.c */ -static inline void switch_mm (struct mm_struct *prev,struct mm_struct *next, -struct task_struct *tsk) +static inline void switch_mm_irqs_off (struct mm_struct *prev, +struct mm_struct *next, +struct task_struct *tsk) {/* Mark this context has been used on the new CPU */ if (!cpumask_test_cpu (smp_processor_id (),mm_cpumask (next)))
@@ -110,6 +111,18 @@ static inline void switch_mm(struct mm_sswitch_mmu_context (prev, next, tsk); } +static inline void switch_mm (struct mm_struct *prev,struct mm_struct *next, +struct task_struct *tsk) +{ +unsigned long flags; + +local_irq_save (flags); +switch_mm_irqs_off (prev, next, tsk); +local_irq_restore (flags); +} +#define switch_mm_irqs_off switch_mm_irqs_off + +#define deactivate_mm (tsk,mm) do { } while (0)/*
Patches currently in stable-queue which might be from [email protected] are
queue-4.11/powerpc-mm-ensure-irqs-are-off-in-switch_mm.patch