From: Valentin Schneider <vschneid@redhat.com>
To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-mm@kvack.org, bpf@vger.kernel.org, x86@kernel.org
Cc: "Steven Rostedt" <rostedt@goodmis.org>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
"Jonathan Corbet" <corbet@lwn.net>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Ingo Molnar" <mingo@redhat.com>,
"Borislav Petkov" <bp@alien8.de>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Wanpeng Li" <wanpengli@tencent.com>,
"Vitaly Kuznetsov" <vkuznets@redhat.com>,
"Andy Lutomirski" <luto@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Paul E. McKenney" <paulmck@kernel.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Christoph Hellwig" <hch@infradead.org>,
"Lorenzo Stoakes" <lstoakes@gmail.com>,
"Josh Poimboeuf" <jpoimboe@kernel.org>,
"Kees Cook" <keescook@chromium.org>,
"Sami Tolvanen" <samitolvanen@google.com>,
"Ard Biesheuvel" <ardb@kernel.org>,
"Nicholas Piggin" <npiggin@gmail.com>,
"Juerg Haefliger" <juerg.haefliger@canonical.com>,
"Nicolas Saenz Julienne" <nsaenz@kernel.org>,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
"Nadav Amit" <namit@vmware.com>,
"Dan Carpenter" <error27@gmail.com>,
"Chuang Wang" <nashuiliang@gmail.com>,
"Yang Jihong" <yangjihong1@huawei.com>,
"Petr Mladek" <pmladek@suse.com>,
"Jason A. Donenfeld" <Jason@zx2c4.com>,
"Song Liu" <song@kernel.org>,
"Julian Pidancet" <julian.pidancet@oracle.com>,
"Tom Lendacky" <thomas.lendacky@amd.com>,
"Dionna Glaze" <dionnaglaze@google.com>,
"Thomas Weißschuh" <linux@weissschuh.net>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Daniel Bristot de Oliveira" <bristot@redhat.com>,
"Marcelo Tosatti" <mtosatti@redhat.com>,
"Yair Podemsky" <ypodemsk@redhat.com>
Subject: [RFC PATCH 14/14] x86/mm, mm/vmalloc: Defer flush_tlb_kernel_range() targeting NOHZ_FULL CPUs
Date: Wed, 5 Jul 2023 19:12:56 +0100 [thread overview]
Message-ID: <20230705181256.3539027-15-vschneid@redhat.com> (raw)
In-Reply-To: <20230705181256.3539027-1-vschneid@redhat.com>
vunmap()'s issued from housekeeping CPUs are a relatively common source of
interference for isolated NOHZ_FULL CPUs, as they are hit by the
flush_tlb_kernel_range() IPIs.
Given that CPUs executing in userspace do not access data in the vmalloc
range, these IPIs could be deferred until their next kernel entry.
This does require a guarantee that nothing in the vmalloc range can be
accessed in early entry code. vmalloc'd kernel stacks (VMAP_STACK) are
AFAICT a safe exception, as a task running in userspace needs to enter
kernelspace to execute do_exit() before its stack can be vfree'd.
XXX: Validation that nothing in the vmalloc range is accessed in .noinstr or
somesuch?
Blindly deferring any and all flush of the kernel mappings is a risky move,
so introduce a variant of flush_tlb_kernel_range() that explicitly allows
deferral. Use it for vunmap flushes.
Note that while flush_tlb_kernel_range() may end up issuing a full
flush (including user mappings), this only happens when reaching a
invalidation range threshold where it is cheaper to do a full flush than to
individually invalidate each page in the range via INVLPG. IOW, it doesn't
*require* invalidating user mappings, and thus remains safe to defer until
a later kernel entry.
Signed-off-by: Valentin Schneider <vschneid@redhat.com>
---
arch/x86/include/asm/tlbflush.h | 1 +
arch/x86/mm/tlb.c | 23 ++++++++++++++++++++---
mm/vmalloc.c | 15 ++++++++++-----
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 9064aa0027d05..2b3605c09649c 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -255,6 +255,7 @@ extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned int stride_shift,
bool freed_tables);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range_deferrable(unsigned long start, unsigned long end);
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long a)
{
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 631df9189ded4..bb18b35e61b4a 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -10,6 +10,7 @@
#include <linux/debugfs.h>
#include <linux/sched/smt.h>
#include <linux/task_work.h>
+#include <linux/context_tracking.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -1045,6 +1046,11 @@ static void do_flush_tlb_all(void *info)
__flush_tlb_all();
}
+static bool do_kernel_flush_defer_cond(int cpu, void *info)
+{
+ return !ct_set_cpu_work(cpu, CONTEXT_WORK_TLBI);
+}
+
void flush_tlb_all(void)
{
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
@@ -1061,12 +1067,13 @@ static void do_kernel_range_flush(void *info)
flush_tlb_one_kernel(addr);
}
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+static inline void
+__flush_tlb_kernel_range(smp_cond_func_t cond_func, unsigned long start, unsigned long end)
{
/* Balance as user space task's flush, a bit conservative */
if (end == TLB_FLUSH_ALL ||
(end - start) > tlb_single_page_flush_ceiling << PAGE_SHIFT) {
- on_each_cpu(do_flush_tlb_all, NULL, 1);
+ on_each_cpu_cond(cond_func, do_flush_tlb_all, NULL, 1);
} else {
struct flush_tlb_info *info;
@@ -1074,13 +1081,23 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
info = get_flush_tlb_info(NULL, start, end, 0, false,
TLB_GENERATION_INVALID);
- on_each_cpu(do_kernel_range_flush, info, 1);
+ on_each_cpu_cond(cond_func, do_kernel_range_flush, info, 1);
put_flush_tlb_info();
preempt_enable();
}
}
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ __flush_tlb_kernel_range(NULL, start, end);
+}
+
+void flush_tlb_kernel_range_deferrable(unsigned long start, unsigned long end)
+{
+ __flush_tlb_kernel_range(do_kernel_flush_defer_cond, start, end);
+}
+
/*
* This can be used from process context to figure out what the value of
* CR3 is without needing to do a (slow) __read_cr3().
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 1d13d71687d73..10f99224e12e0 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -439,6 +439,11 @@ void vunmap_range_noflush(unsigned long start, unsigned long end)
__vunmap_range_noflush(start, end);
}
+#ifndef flush_tlb_kernel_range_deferrable
+#define flush_tlb_kernel_range_deferrable(start, end) \
+ flush_tlb_kernel_range(start, end)
+#endif
+
/**
* vunmap_range - unmap kernel virtual addresses
* @addr: start of the VM area to unmap
@@ -452,7 +457,7 @@ void vunmap_range(unsigned long addr, unsigned long end)
{
flush_cache_vunmap(addr, end);
vunmap_range_noflush(addr, end);
- flush_tlb_kernel_range(addr, end);
+ flush_tlb_kernel_range_deferrable(addr, end);
}
static int vmap_pages_pte_range(pmd_t *pmd, unsigned long addr,
@@ -1747,7 +1752,7 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
list_last_entry(&local_purge_list,
struct vmap_area, list)->va_end);
- flush_tlb_kernel_range(start, end);
+ flush_tlb_kernel_range_deferrable(start, end);
resched_threshold = lazy_max_pages() << 1;
spin_lock(&free_vmap_area_lock);
@@ -1849,7 +1854,7 @@ static void free_unmap_vmap_area(struct vmap_area *va)
flush_cache_vunmap(va->va_start, va->va_end);
vunmap_range_noflush(va->va_start, va->va_end);
if (debug_pagealloc_enabled_static())
- flush_tlb_kernel_range(va->va_start, va->va_end);
+ flush_tlb_kernel_range_deferrable(va->va_start, va->va_end);
free_vmap_area_noflush(va);
}
@@ -2207,7 +2212,7 @@ static void vb_free(unsigned long addr, unsigned long size)
vunmap_range_noflush(addr, addr + size);
if (debug_pagealloc_enabled_static())
- flush_tlb_kernel_range(addr, addr + size);
+ flush_tlb_kernel_range_deferrable(addr, addr + size);
spin_lock(&vb->lock);
@@ -2260,7 +2265,7 @@ static void _vm_unmap_aliases(unsigned long start, unsigned long end, int flush)
mutex_lock(&vmap_purge_lock);
purge_fragmented_blocks_allcpus();
if (!__purge_vmap_area_lazy(start, end) && flush)
- flush_tlb_kernel_range(start, end);
+ flush_tlb_kernel_range_deferrable(start, end);
mutex_unlock(&vmap_purge_lock);
}
--
2.31.1
next prev parent reply other threads:[~2023-07-05 18:17 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-05 18:12 [RFC PATCH 00/14] context_tracking,x86: Defer some IPIs until a user->kernel transition Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 01/14] tracing/filters: Dynamically allocate filter_pred.regex Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 02/14] tracing/filters: Enable filtering a cpumask field by another cpumask Valentin Schneider
2023-07-05 18:54 ` Steven Rostedt
2023-07-05 18:12 ` [RFC PATCH 03/14] tracing/filters: Enable filtering a scalar field by a cpumask Valentin Schneider
2023-07-05 19:00 ` Steven Rostedt
2023-07-05 18:12 ` [RFC PATCH 04/14] tracing/filters: Enable filtering the CPU common " Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 05/14] tracing/filters: Document cpumask filtering Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 06/14] objtool: Flesh out warning related to pv_ops[] calls Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 07/14] objtool: Warn about non __ro_after_init static key usage in .noinstr Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 08/14] BROKEN: context_tracking: Make context_tracking_key __ro_after_init Valentin Schneider
2023-07-05 20:41 ` Peter Zijlstra
2023-07-05 18:12 ` [RFC PATCH 09/14] x86/kvm: Make kvm_async_pf_enabled __ro_after_init Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 10/14] x86/sev-es: Make sev_es_enable_key __ro_after_init Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 11/14] context-tracking: Introduce work deferral infrastructure Valentin Schneider
2023-07-05 22:23 ` Frederic Weisbecker
2023-07-05 22:41 ` Peter Zijlstra
2023-07-06 9:53 ` Frederic Weisbecker
2023-07-06 10:01 ` Frederic Weisbecker
2023-07-06 11:30 ` Valentin Schneider
2023-07-06 11:40 ` Frederic Weisbecker
2023-07-06 16:39 ` Paul E. McKenney
2023-07-06 18:05 ` Valentin Schneider
2023-07-06 11:55 ` Frederic Weisbecker
2023-07-05 22:39 ` Peter Zijlstra
2023-07-06 11:31 ` Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 12/14] context_tracking,x86: Defer kernel text patching IPIs Valentin Schneider
2023-07-05 18:12 ` [RFC PATCH 13/14] context_tracking,x86: Add infrastructure to defer kernel TLBI Valentin Schneider
2023-07-05 18:12 ` Valentin Schneider [this message]
2023-07-05 18:48 ` [RFC PATCH 00/14] context_tracking,x86: Defer some IPIs until a user->kernel transition Nadav Amit
2023-07-06 11:29 ` Valentin Schneider
2023-07-05 19:03 ` Steven Rostedt
2023-07-06 11:30 ` Valentin Schneider
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=20230705181256.3539027-15-vschneid@redhat.com \
--to=vschneid@redhat.com \
--cc=Jason@zx2c4.com \
--cc=akpm@linux-foundation.org \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=bpf@vger.kernel.org \
--cc=bristot@redhat.com \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=dionnaglaze@google.com \
--cc=error27@gmail.com \
--cc=frederic@kernel.org \
--cc=hch@infradead.org \
--cc=hpa@zytor.com \
--cc=jpoimboe@kernel.org \
--cc=juerg.haefliger@canonical.com \
--cc=julian.pidancet@oracle.com \
--cc=juri.lelli@redhat.com \
--cc=keescook@chromium.org \
--cc=kirill.shutemov@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=linux@weissschuh.net \
--cc=lstoakes@gmail.com \
--cc=luto@kernel.org \
--cc=mhiramat@kernel.org \
--cc=mingo@redhat.com \
--cc=mtosatti@redhat.com \
--cc=namit@vmware.com \
--cc=nashuiliang@gmail.com \
--cc=npiggin@gmail.com \
--cc=nsaenz@kernel.org \
--cc=paulmck@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=rostedt@goodmis.org \
--cc=samitolvanen@google.com \
--cc=song@kernel.org \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--cc=urezki@gmail.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
--cc=x86@kernel.org \
--cc=yangjihong1@huawei.com \
--cc=ypodemsk@redhat.com \
/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