From: Willy Tarreau <w@1wt.eu>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Andy Lutomirski <luto@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Andy Lutomirski <luto@amacapital.net>,
Borislav Petkov <bp@alien8.de>, Brian Gerst <brgerst@gmail.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
Denys Vlasenko <dvlasenk@redhat.com>,
"H. Peter Anvin" <hpa@zytor.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Peter Zijlstra <peterz@infradead.org>,
Rik van Riel <riel@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
linux-mm@kvack.org, Ingo Molnar <mingo@kernel.org>,
Ben Hutchings <ben@decadent.org.uk>, Willy Tarreau <w@1wt.eu>
Subject: [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization
Date: Fri, 04 Mar 2016 16:30:07 +0100 [thread overview]
Message-ID: <20160304153001.014867528@1wt.eu> (raw)
In-Reply-To: <148ee355b419e9976ca727513a1405c8@local>
2.6.32-longterm review patch. If anyone has any objections, please let me know.
------------------
From: Andy Lutomirski <luto@kernel.org>
commit 71b3c126e61177eb693423f2e18a1914205b165e upstream.
When switch_mm() activates a new PGD, it also sets a bit that
tells other CPUs that the PGD is in use so that TLB flush IPIs
will be sent. In order for that to work correctly, the bit
needs to be visible prior to loading the PGD and therefore
starting to fill the local TLB.
Document all the barriers that make this work correctly and add
a couple that were missing.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-mm@kvack.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
[bwh: Backported to 2.6.32:
- There's no flush_tlb_mm_range(), only flush_tlb_mm() which does not use
INVLPG
- Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
arch/x86/include/asm/mmu_context.h | 31 ++++++++++++++++++++++++++++++-
arch/x86/mm/tlb.c | 28 ++++++++++++++++++++++++----
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 8b5393e..b2c847a 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -42,7 +42,32 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
#endif
cpumask_set_cpu(cpu, mm_cpumask(next));
- /* Re-load page tables */
+ /*
+ * Re-load page tables.
+ *
+ * This logic has an ordering constraint:
+ *
+ * CPU 0: Write to a PTE for 'next'
+ * CPU 0: load bit 1 in mm_cpumask. if nonzero, send IPI.
+ * CPU 1: set bit 1 in next's mm_cpumask
+ * CPU 1: load from the PTE that CPU 0 writes (implicit)
+ *
+ * We need to prevent an outcome in which CPU 1 observes
+ * the new PTE value and CPU 0 observes bit 1 clear in
+ * mm_cpumask. (If that occurs, then the IPI will never
+ * be sent, and CPU 0's TLB will contain a stale entry.)
+ *
+ * The bad outcome can occur if either CPU's load is
+ * reordered before that CPU's store, so both CPUs much
+ * execute full barriers to prevent this from happening.
+ *
+ * Thus, switch_mm needs a full barrier between the
+ * store to mm_cpumask and any operation that could load
+ * from next->pgd. This barrier synchronizes with
+ * remote TLB flushers. Fortunately, load_cr3 is
+ * serializing and thus acts as a full barrier.
+ *
+ */
load_cr3(next->pgd);
/* stop flush ipis for the previous mm */
@@ -63,6 +88,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
/* We were in lazy tlb mode and leave_mm disabled
* tlb flush IPI delivery. We must reload CR3
* to make sure to use no freed page tables.
+ *
+ * As above, this is a barrier that forces
+ * TLB repopulation to be ordered after the
+ * store to mm_cpumask.
*/
load_cr3(next->pgd);
load_LDT_nolock(&next->context);
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 36fe08e..2a655b2 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -234,7 +234,9 @@ void flush_tlb_current_task(void)
preempt_disable();
+ /* This is an implicit full barrier that synchronizes with switch_mm. */
local_flush_tlb();
+
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
preempt_enable();
@@ -245,10 +247,20 @@ void flush_tlb_mm(struct mm_struct *mm)
preempt_disable();
if (current->active_mm == mm) {
- if (current->mm)
+ if (current->mm) {
+ /*
+ * This is an implicit full barrier (MOV to CR) that
+ * synchronizes with switch_mm.
+ */
local_flush_tlb();
- else
+ } else {
leave_mm(smp_processor_id());
+ /* Synchronize with switch_mm. */
+ smp_mb();
+ }
+ } else {
+ /* Synchronize with switch_mm. */
+ smp_mb();
}
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
@@ -263,10 +275,18 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
preempt_disable();
if (current->active_mm == mm) {
- if (current->mm)
+ if (current->mm) {
+ /*
+ * Implicit full barrier (INVLPG) that synchronizes
+ * with switch_mm.
+ */
__flush_tlb_one(va);
- else
+ } else {
leave_mm(smp_processor_id());
+
+ /* Synchronize with switch_mm. */
+ smp_mb();
+ }
}
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
--
1.7.12.2.21.g234cd45.dirty
next prev parent reply other threads:[~2016-03-04 16:03 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <148ee355b419e9976ca727513a1405c8@local>
2016-03-04 15:30 ` [PATCH 2.6.32 00/55] 2.6.32.71-longterm review Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Willy Tarreau
2016-03-04 15:30 ` Willy Tarreau [this message]
2016-03-04 15:30 ` [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl " Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success Willy Tarreau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160304153001.014867528@1wt.eu \
--to=w@1wt.eu \
--cc=akpm@linux-foundation.org \
--cc=ben@decadent.org.uk \
--cc=bp@alien8.de \
--cc=brgerst@gmail.com \
--cc=dave.hansen@linux.intel.com \
--cc=dvlasenk@redhat.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@amacapital.net \
--cc=luto@kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=riel@redhat.com \
--cc=stable@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®