From: Peter Zijlstra <peterz@infradead.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Will Deacon <will.deacon@arm.com>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Benjamin Herrenschmidt <benh@au1.ibm.com>,
Nick Piggin <npiggin@gmail.com>,
Catalin Marinas <catalin.marinas@arm.com>,
linux-arm-kernel <linux-arm-kernel@lists.infradead.org>
Subject: Re: [RFC PATCH 00/11] Avoid synchronous TLB invalidation for intermediate page-table entries on arm64
Date: Sun, 26 Aug 2018 12:56:48 +0200 [thread overview]
Message-ID: <20180826105648.GU24124@hirez.programming.kicks-ass.net> (raw)
In-Reply-To: <CA+55aFxNs5B=j_g_OpAd=Xp_iiO_+idT-ogd_WM2EcL_6brbqg@mail.gmail.com>
On Fri, Aug 24, 2018 at 09:20:00AM -0700, Linus Torvalds wrote:
> On Fri, Aug 24, 2018 at 8:52 AM Will Deacon <will.deacon@arm.com> wrote:
> >
> > I hacked up this RFC on the back of the recent changes to the mmu_gather
> > stuff in mainline. It's had a bit of testing and it looks pretty good so
> > far.
>
> Looks good to me.
>
> Apart from the arm64-specific question I had, I wonder whether we need
> to have that single "freed_tables" bit at all, since you wanted to
> have the four individual bits for the different levels.
I think so; because he also sets those size bits for things like hugetlb
and thp user page frees, not only table page frees. So they're not
exactly the same.
And I think x86 could use this too; if we know we only freed 2M
pages, we can use that in flush_tlb_mm_range() to range flush in 2M
increments instead of 4K.
Something a little like so..
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index cb0a1f470980..cb0898fe9d37 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -8,10 +8,15 @@
#define tlb_flush(tlb) \
{ \
- if (!tlb->fullmm && !tlb->need_flush_all) \
- flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 0UL); \
- else \
- flush_tlb_mm_range(tlb->mm, 0UL, TLB_FLUSH_ALL, 0UL); \
+ unsigned long start = 0UL, end = TLB_FLUSH_ALL; \
+ unsigned int invl_shift = tlb_get_unmap_shift(tlb); \
+ \
+ if (!tlb->fullmm && !tlb->need_flush_all) { \
+ start = tlb->start; \
+ end = tlb->end; \
+ } \
+ \
+ flush_tlb_mm_range(tlb->mm, start, end, invl_shift); \
}
#include <asm-generic/tlb.h>
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 511bf5fae8b8..8ac1cac34f63 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -491,23 +491,25 @@ struct flush_tlb_info {
unsigned long start;
unsigned long end;
u64 new_tlb_gen;
+ unsigned int invl_shift;
};
#define local_flush_tlb() __flush_tlb()
#define flush_tlb_mm(mm) flush_tlb_mm_range(mm, 0UL, TLB_FLUSH_ALL, 0UL)
-#define flush_tlb_range(vma, start, end) \
- flush_tlb_mm_range(vma->vm_mm, start, end, vma->vm_flags)
+#define flush_tlb_range(vma, start, end) \
+ flush_tlb_mm_range(vma->vm_mm, start, end, \
+ vma->vm_flags & VM_HUGETLB ? PMD_SHUFT : PAGE_SHIFT)
extern void flush_tlb_all(void);
extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned long vmflag);
+ unsigned long end, unsigned int invl_shift);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long a)
{
- flush_tlb_mm_range(vma->vm_mm, a, a + PAGE_SIZE, VM_NONE);
+ flush_tlb_mm_range(vma->vm_mm, a, a + PAGE_SIZE, PAGE_SHIFT);
}
void native_flush_tlb_others(const struct cpumask *cpumask,
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 752dbf4e0e50..806aa74a8fb4 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -537,12 +537,12 @@ static void flush_tlb_func_common(const struct flush_tlb_info *f,
f->new_tlb_gen == mm_tlb_gen) {
/* Partial flush */
unsigned long addr;
- unsigned long nr_pages = (f->end - f->start) >> PAGE_SHIFT;
+ unsigned long nr_pages = (f->end - f->start) >> f->invl_shift;
addr = f->start;
while (addr < f->end) {
__flush_tlb_one_user(addr);
- addr += PAGE_SIZE;
+ addr += 1UL << f->invl_shift;
}
if (local)
count_vm_tlb_events(NR_TLB_LOCAL_FLUSH_ONE, nr_pages);
@@ -653,12 +653,13 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned long vmflag)
+ unsigned long end, unsigned int invl_shift)
{
int cpu;
struct flush_tlb_info info __aligned(SMP_CACHE_BYTES) = {
.mm = mm,
+ .invl_shift = invl_shift;
};
cpu = get_cpu();
@@ -668,8 +669,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
/* Should we flush just the requested range? */
if ((end != TLB_FLUSH_ALL) &&
- !(vmflag & VM_HUGETLB) &&
- ((end - start) >> PAGE_SHIFT) <= tlb_single_page_flush_ceiling) {
+ ((end - start) >> invl_shift) <= tlb_single_page_flush_ceiling) {
info.start = start;
info.end = end;
} else {
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index e811ef7b8350..cdde0cdb23e7 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -175,6 +200,25 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
}
#endif
+static inline unsigned long tlb_get_unmap_shift(struct mmu_gather *tlb)
+{
+ if (tlb->cleared_ptes)
+ return PAGE_SHIFT;
+ if (tlb->cleared_pmds)
+ return PMD_SHIFT;
+ if (tlb->cleared_puds)
+ return PUD_SHIFT;
+ if (tlb->cleared_p4ds)
+ return P4D_SHIFT;
+
+ return PAGE_SHIFT;
+}
+
+static inline unsigned long tlb_get_unmap_size(struct mmu_gather *tlb)
+{
+ return 1ULL << tlb_get_unmap_shift(tlb);
+}
+
/*
* In the case of tlb vma handling, we can optimise these away in the
* case where we're doing a full MM flush. When we're doing a munmap,
next prev parent reply other threads:[~2018-08-26 11:03 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-24 15:52 [RFC PATCH 00/11] Avoid synchronous TLB invalidation for intermediate page-table entries on arm64 Will Deacon
2018-08-24 15:52 ` [RFC PATCH 01/11] arm64: tlb: Use last-level invalidation in flush_tlb_kernel_range() Will Deacon
2018-08-24 15:52 ` [RFC PATCH 02/11] arm64: tlb: Add DSB ISHST prior to TLBI in __flush_tlb_[kernel_]pgtable() Will Deacon
2018-08-24 17:56 ` Peter Zijlstra
2018-08-28 13:03 ` Will Deacon
2018-08-24 15:52 ` [RFC PATCH 03/11] arm64: pgtable: Implement p[mu]d_valid() and check in set_p[mu]d() Will Deacon
2018-08-24 16:15 ` Linus Torvalds
2018-08-28 12:49 ` Will Deacon
2018-08-24 15:52 ` [RFC PATCH 04/11] arm64: tlb: Justify non-leaf invalidation in flush_tlb_range() Will Deacon
2018-08-24 15:52 ` [RFC PATCH 05/11] arm64: tlbflush: Allow stride to be specified for __flush_tlb_range() Will Deacon
2018-08-24 15:52 ` [RFC PATCH 06/11] arm64: tlb: Remove redundant !CONFIG_HAVE_RCU_TABLE_FREE code Will Deacon
2018-08-24 15:52 ` [RFC PATCH 07/11] asm-generic/tlb: Guard with #ifdef CONFIG_MMU Will Deacon
2018-08-24 15:52 ` [RFC PATCH 08/11] asm-generic/tlb: Track freeing of page-table directories in struct mmu_gather Will Deacon
2018-08-27 4:44 ` Nicholas Piggin
2018-08-28 13:46 ` Peter Zijlstra
2018-08-28 13:48 ` Peter Zijlstra
2018-08-28 14:12 ` Nicholas Piggin
2018-08-24 15:52 ` [RFC PATCH 09/11] asm-generic/tlb: Track which levels of the page tables have been cleared Will Deacon
2018-08-27 7:53 ` Peter Zijlstra
2018-08-28 13:12 ` Will Deacon
2018-08-24 15:52 ` [RFC PATCH 10/11] arm64: tlb: Adjust stride and type of TLBI according to mmu_gather Will Deacon
2018-08-24 15:52 ` [RFC PATCH 11/11] arm64: tlb: Avoid synchronous TLBIs when freeing page tables Will Deacon
2018-08-24 16:20 ` [RFC PATCH 00/11] Avoid synchronous TLB invalidation for intermediate page-table entries on arm64 Linus Torvalds
2018-08-26 10:56 ` Peter Zijlstra [this message]
2018-09-04 18:38 ` Jon Masters
2018-09-05 12:28 ` Will Deacon
2018-09-07 6:36 ` Jon Masters
2018-09-13 15:53 ` Will Deacon
2018-09-13 16:53 ` Jon Masters
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=20180826105648.GU24124@hirez.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=benh@au1.ibm.com \
--cc=catalin.marinas@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=npiggin@gmail.com \
--cc=torvalds@linux-foundation.org \
--cc=will.deacon@arm.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