[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200331142927.1237-9-yezhenyu2@huawei.com>
Date: Tue, 31 Mar 2020 22:29:27 +0800
From: Zhenyu Ye <yezhenyu2@...wei.com>
To: <peterz@...radead.org>, <mark.rutland@....com>, <will@...nel.org>,
<catalin.marinas@....com>, <aneesh.kumar@...ux.ibm.com>,
<akpm@...ux-foundation.org>, <npiggin@...il.com>, <arnd@...db.de>,
<rostedt@...dmis.org>, <maz@...nel.org>, <suzuki.poulose@....com>,
<tglx@...utronix.de>, <yuzhao@...gle.com>, <Dave.Martin@....com>,
<steven.price@....com>, <broonie@...nel.org>,
<guohanjun@...wei.com>, <corbet@....net>, <vgupta@...opsys.com>,
<tony.luck@...el.com>
CC: <yezhenyu2@...wei.com>, <linux-arm-kernel@...ts.infradead.org>,
<linux-kernel@...r.kernel.org>, <linux-arch@...r.kernel.org>,
<linux-mm@...ck.org>, <arm@...nel.org>, <xiexiangyou@...wei.com>,
<prime.zeng@...ilicon.com>, <zhangshaokun@...ilicon.com>,
<kuhn.chenqun@...wei.com>
Subject: [RFC PATCH v5 8/8] arm64: tlb: Set the TTL field in flush_tlb_range
This patch uses the cleared_* in struct mmu_gather to set the
TTL field in flush_tlb_range().
Signed-off-by: Zhenyu Ye <yezhenyu2@...wei.com>
---
arch/arm64/include/asm/tlb.h | 39 ++++++++++++++++++++++++++++++-
arch/arm64/include/asm/tlbflush.h | 22 +++++------------
2 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index b76df828e6b7..72b6e3763df2 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -21,11 +21,34 @@ static void tlb_flush(struct mmu_gather *tlb);
#include <asm-generic/tlb.h>
+/*
+ * get the tlbi levels in arm64. Default value is 0 if more than one
+ * of cleared_* is set or neither is set.
+ * Arm64 doesn't support p4ds now.
+ */
+static inline int tlb_get_level(struct mmu_gather *tlb)
+{
+ int sum = tlb->cleared_ptes + tlb->cleared_pmds +
+ tlb->cleared_puds + tlb->cleared_p4ds;
+
+ if (sum != 1)
+ return 0;
+ else if (tlb->cleared_ptes)
+ return 3;
+ else if (tlb->cleared_pmds)
+ return 2;
+ else if (tlb->cleared_puds)
+ return 1;
+
+ return 0;
+}
+
static inline void tlb_flush(struct mmu_gather *tlb)
{
struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0);
bool last_level = !tlb->freed_tables;
unsigned long stride = tlb_get_unmap_size(tlb);
+ int tlb_level = tlb_get_level(tlb);
/*
* If we're tearing down the address space then we only care about
@@ -38,7 +61,21 @@ static inline void tlb_flush(struct mmu_gather *tlb)
return;
}
- __flush_tlb_range(&vma, tlb->start, tlb->end, stride, last_level);
+ __flush_tlb_range(&vma, tlb->start, tlb->end, stride,
+ last_level, tlb_level);
+}
+
+static inline void flush_tlb_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ /*
+ * We cannot use leaf-only invalidation here, since we may be invalidating
+ * table entries as part of collapsing hugepages or moving page tables.
+ */
+ unsigned long stride = tlb_get_unmap_size(tlb);
+ int tlb_level = tlb_get_level(tlb);
+ __flush_tlb_range(vma, start, end, stride, false, tlb_level);
}
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 0b4d75a2270b..dc8e803692f8 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -215,7 +215,8 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
static inline void __flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end,
- unsigned long stride, bool last_level)
+ unsigned long stride, bool last_level,
+ int tlb_level)
{
unsigned long asid = ASID(vma->vm_mm);
unsigned long addr;
@@ -237,27 +238,16 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
dsb(ishst);
for (addr = start; addr < end; addr += stride) {
if (last_level) {
- __tlbi_level(vale1is, addr, 0);
- __tlbi_user_level(vale1is, addr, 0);
+ __tlbi_level(vale1is, addr, tlb_level);
+ __tlbi_user_level(vale1is, addr, tlb_level);
} else {
- __tlbi_level(vae1is, addr, 0);
- __tlbi_user_level(vae1is, addr, 0);
+ __tlbi_level(vae1is, addr, tlb_level);
+ __tlbi_user_level(vae1is, addr, tlb_level);
}
}
dsb(ish);
}
-static inline void flush_tlb_range(struct mmu_gather *tlb,
- struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- /*
- * We cannot use leaf-only invalidation here, since we may be invalidating
- * table entries as part of collapsing hugepages or moving page tables.
- */
- __flush_tlb_range(vma, start, end, PAGE_SIZE, false);
-}
-
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
unsigned long addr;
--
2.19.1
Powered by blists - more mailing lists