All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/mm: disable preemption during CR3 read+write
@ 2016-08-05 13:37 ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2016-08-05 13:37 UTC (permalink / raw)
  To: linux-mm, linux-kernel
  Cc: x86, Borislav Petkov, Andy Lutomirski, Rik van Riel, Mel Gorman,
	Peter Zijlstra

Usually current->mm (and therefore mm->pgd) stays the same during the
lifetime of a task so it does not matter if a task gets preempted during
the read and write of the CR3.

But then, there is this scenario on x86-UP:
TaskA is in do_exit() and exit_mm() sets current->mm = NULL followed by
mmput() -> exit_mmap() -> tlb_finish_mmu() -> tlb_flush_mmu() ->
tlb_flush_mmu_tlbonly() -> tlb_flush() -> flush_tlb_mm_range() ->
__flush_tlb_up() -> __flush_tlb() ->  __native_flush_tlb().

At this point current->mm is NULL but current->active_mm still points to
the "old" mm.
Let's preempt taskA _after_ native_read_cr3() by taskB. TaskB has its
own mm so CR3 has changed.
Now preempt back to taskA. TaskA has no ->mm set so it borrows taskB's
mm and so CR3 remains unchanged. Once taskA gets active it continues
where it was interrupted and that means it writes its old CR3 value
back. Everything is fine because userland won't need its memory
anymore.

Now the fun part. Let's preempt taskA one more time and get back to
taskB. This time switch_mm() won't do a thing because oldmm
(->active_mm) is the same as mm (as per context_switch()). So we remain
with a bad CR3 / pgd and return to userland.
The next thing that happens is handle_mm_fault() with an address for the
execution of its code in userland. handle_mm_fault() realizes that it
has a PTE with proper rights so it returns doing nothing. But the CPU
looks at the wrong pgd and insists that something is wrong and faults
again. And again. And one more time…

This pagefault circle continues until the scheduler gets tired of it and
puts another task on the CPU. It gets little difficult if the task is a
RT task with a high priority. The system will either freeze or it gets
fixed by the software watchdog thread which usually runs at RT-max prio.
But waiting for the watchdog will increase the latency of the RT task
which is no good.

Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/x86/include/asm/tlbflush.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 4e5be94e079a..1ee065954e24 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -135,7 +135,14 @@ static inline void cr4_set_bits_and_update_boot(unsigned long mask)
 
 static inline void __native_flush_tlb(void)
 {
+	/*
+	 * if current->mm == NULL then we borrow a mm which may change during a
+	 * task switch and therefore we must not be preempted while we write CR3
+	 * back.
+	 */
+	preempt_disable();
 	native_write_cr3(native_read_cr3());
+	preempt_enable();
 }
 
 static inline void __native_flush_tlb_global_irq_disabled(void)
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread
* [PATCH] x86/mm: Disable preemption during CR3 read+write
@ 2017-10-17 15:57 Sebastian Andrzej Siewior
  2017-10-18 15:01 ` Bernhard Kaindl
  0 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2017-10-17 15:57 UTC (permalink / raw)
  To: stable; +Cc: Bernhard Kaindl

Upstream commit 5cf0791da5c162ebc14b01eb01631cfa7ed4fa6e

This patch is already part of various stable tree but is missing in the
  v3.18
  v4.1

tree and applies cleanly on top of
  v3.18.69
  v4.1.43

I've been contacted by Bernhard Kaindl (Cc:) and he asked about the
whereabouts of the patch in the two stable trees. He can confirm that
this patch cures his problem on the v3.18 stable tree he is using.
He assumes that the same problem might occur on the v4.1 tree and should
be fixed by the patch but he has no working setup with v4.1 kernel to
confirm this.

Sebastian

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-10-18 16:51 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-05 13:37 [PATCH] x86/mm: disable preemption during CR3 read+write Sebastian Andrzej Siewior
2016-08-05 13:37 ` Sebastian Andrzej Siewior
2016-08-05 13:53 ` Peter Zijlstra
2016-08-05 13:53   ` Peter Zijlstra
2016-08-05 14:38 ` Rik van Riel
2016-08-05 15:42 ` Andy Lutomirski
2016-08-05 15:42   ` Andy Lutomirski
2016-08-05 15:52   ` Sebastian Andrzej Siewior
2016-08-05 15:52     ` Sebastian Andrzej Siewior
2016-08-10 18:10 ` [tip:x86/urgent] x86/mm: Disable " tip-bot for Sebastian Andrzej Siewior
2017-10-17 15:57 [PATCH] " Sebastian Andrzej Siewior
2017-10-18 15:01 ` Bernhard Kaindl
2017-10-18 16:51   ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.