All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Will Deacon <will.deacon@arm.com>,
	Santosh Sivaraj <santosh@fossix.org>
Subject: [PATCH 4.19 16/35] asm-generic/tlb: Track which levels of the page tables have been cleared
Date: Mon,  4 Jan 2021 16:57:19 +0100	[thread overview]
Message-ID: <20210104155704.197670503@linuxfoundation.org> (raw)
In-Reply-To: <20210104155703.375788488@linuxfoundation.org>

From: Will Deacon <will.deacon@arm.com>

commit a6d60245d6d9b1caf66b0d94419988c4836980af upstream

It is common for architectures with hugepage support to require only a
single TLB invalidation operation per hugepage during unmap(), rather than
iterating through the mapping at a PAGE_SIZE increment. Currently,
however, the level in the page table where the unmap() operation occurs
is not stored in the mmu_gather structure, therefore forcing
architectures to issue additional TLB invalidation operations or to give
up and over-invalidate by e.g. invalidating the entire TLB.

Ideally, we could add an interval rbtree to the mmu_gather structure,
which would allow us to associate the correct mapping granule with the
various sub-mappings within the range being invalidated. However, this
is costly in terms of book-keeping and memory management, so instead we
approximate by keeping track of the page table levels that are cleared
and provide a means to query the smallest granule required for invalidation.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Cc: <stable@vger.kernel.org> # 4.19
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
[santosh: prerequisite for upcoming tlbflush backports]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/asm-generic/tlb.h |   58 +++++++++++++++++++++++++++++++++++++++-------
 mm/memory.c               |    4 ++-
 2 files changed, 53 insertions(+), 9 deletions(-)

--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -114,6 +114,14 @@ struct mmu_gather {
 	 */
 	unsigned int		freed_tables : 1;
 
+	/*
+	 * at which levels have we cleared entries?
+	 */
+	unsigned int		cleared_ptes : 1;
+	unsigned int		cleared_pmds : 1;
+	unsigned int		cleared_puds : 1;
+	unsigned int		cleared_p4ds : 1;
+
 	struct mmu_gather_batch *active;
 	struct mmu_gather_batch	local;
 	struct page		*__pages[MMU_GATHER_BUNDLE];
@@ -148,6 +156,10 @@ static inline void __tlb_reset_range(str
 		tlb->end = 0;
 	}
 	tlb->freed_tables = 0;
+	tlb->cleared_ptes = 0;
+	tlb->cleared_pmds = 0;
+	tlb->cleared_puds = 0;
+	tlb->cleared_p4ds = 0;
 }
 
 static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
@@ -197,6 +209,25 @@ static inline void tlb_remove_check_page
 }
 #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 1UL << 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,
@@ -230,13 +261,19 @@ static inline void tlb_remove_check_page
 #define tlb_remove_tlb_entry(tlb, ptep, address)		\
 	do {							\
 		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
+		tlb->cleared_ptes = 1;				\
 		__tlb_remove_tlb_entry(tlb, ptep, address);	\
 	} while (0)
 
-#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	     \
-	do {							     \
-		__tlb_adjust_range(tlb, address, huge_page_size(h)); \
-		__tlb_remove_tlb_entry(tlb, ptep, address);	     \
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	do {							\
+		unsigned long _sz = huge_page_size(h);		\
+		__tlb_adjust_range(tlb, address, _sz);		\
+		if (_sz == PMD_SIZE)				\
+			tlb->cleared_pmds = 1;			\
+		else if (_sz == PUD_SIZE)			\
+			tlb->cleared_puds = 1;			\
+		__tlb_remove_tlb_entry(tlb, ptep, address);	\
 	} while (0)
 
 /**
@@ -250,6 +287,7 @@ static inline void tlb_remove_check_page
 #define tlb_remove_pmd_tlb_entry(tlb, pmdp, address)			\
 	do {								\
 		__tlb_adjust_range(tlb, address, HPAGE_PMD_SIZE);	\
+		tlb->cleared_pmds = 1;					\
 		__tlb_remove_pmd_tlb_entry(tlb, pmdp, address);		\
 	} while (0)
 
@@ -264,6 +302,7 @@ static inline void tlb_remove_check_page
 #define tlb_remove_pud_tlb_entry(tlb, pudp, address)			\
 	do {								\
 		__tlb_adjust_range(tlb, address, HPAGE_PUD_SIZE);	\
+		tlb->cleared_puds = 1;					\
 		__tlb_remove_pud_tlb_entry(tlb, pudp, address);		\
 	} while (0)
 
@@ -289,7 +328,8 @@ static inline void tlb_remove_check_page
 #define pte_free_tlb(tlb, ptep, address)			\
 	do {							\
 		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
-		tlb->freed_tables = 1;			\
+		tlb->freed_tables = 1;				\
+		tlb->cleared_pmds = 1;				\
 		__pte_free_tlb(tlb, ptep, address);		\
 	} while (0)
 #endif
@@ -298,7 +338,8 @@ static inline void tlb_remove_check_page
 #define pmd_free_tlb(tlb, pmdp, address)			\
 	do {							\
 		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
-		tlb->freed_tables = 1;			\
+		tlb->freed_tables = 1;				\
+		tlb->cleared_puds = 1;				\
 		__pmd_free_tlb(tlb, pmdp, address);		\
 	} while (0)
 #endif
@@ -308,7 +349,8 @@ static inline void tlb_remove_check_page
 #define pud_free_tlb(tlb, pudp, address)			\
 	do {							\
 		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
-		tlb->freed_tables = 1;			\
+		tlb->freed_tables = 1;				\
+		tlb->cleared_p4ds = 1;				\
 		__pud_free_tlb(tlb, pudp, address);		\
 	} while (0)
 #endif
@@ -319,7 +361,7 @@ static inline void tlb_remove_check_page
 #define p4d_free_tlb(tlb, pudp, address)			\
 	do {							\
 		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
-		tlb->freed_tables = 1;			\
+		tlb->freed_tables = 1;				\
 		__p4d_free_tlb(tlb, pudp, address);		\
 	} while (0)
 #endif
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -279,8 +279,10 @@ void arch_tlb_finish_mmu(struct mmu_gath
 {
 	struct mmu_gather_batch *batch, *next;
 
-	if (force)
+	if (force) {
+		__tlb_reset_range(tlb);
 		__tlb_adjust_range(tlb, start, end - start);
+	}
 
 	tlb_flush_mmu(tlb);
 



  parent reply	other threads:[~2021-01-04 15:59 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-04 15:57 [PATCH 4.19 00/35] 4.19.165-rc1 review Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 01/35] md/raid10: initialize r10_bio->read_slot before use Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 02/35] fscrypt: add fscrypt_is_nokey_name() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 03/35] ext4: prevent creating duplicate encrypted filenames Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 04/35] f2fs: " Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 05/35] ubifs: " Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 06/35] vfio/pci: Move dummy_resources_list init in vfio_pci_probe() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 07/35] ext4: dont remount read-only with errors=continue on reboot Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 08/35] uapi: move constants from <linux/kernel.h> to <linux/const.h> Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 09/35] KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 10/35] KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 11/35] powerpc/bitops: Fix possible undefined behaviour with fls() and fls64() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 12/35] xen/gntdev.c: Mark pages as dirty Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 13/35] null_blk: Fix zone size initialization Greg Kroah-Hartman
2021-01-06 12:54   ` Pavel Machek
2021-01-11  2:46     ` Damien Le Moal
2021-01-04 15:57 ` [PATCH 4.19 14/35] of: fix linker-section match-table corruption Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 15/35] asm-generic/tlb: Track freeing of page-table directories in struct mmu_gather Greg Kroah-Hartman
2021-01-04 15:57 ` Greg Kroah-Hartman [this message]
2021-01-04 15:57 ` [PATCH 4.19 17/35] asm-generic/tlb, arch: Invert CONFIG_HAVE_RCU_TABLE_INVALIDATE Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 18/35] powerpc/mmu_gather: enable RCU_TABLE_FREE even for !SMP case Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 19/35] mm/mmu_gather: invalidate TLB correctly on batch allocation failure and flush Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 20/35] asm-generic/tlb: avoid potential double flush Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 21/35] Bluetooth: hci_h5: close serdev device and free hu in h5_close Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 22/35] reiserfs: add check for an invalid ih_entry_count Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 23/35] misc: vmw_vmci: fix kernel info-leak by initializing dbells in vmci_ctx_get_chkpt_doorbells() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 24/35] media: gp8psk: initialize stats at power control logic Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 25/35] ALSA: seq: Use bool for snd_seq_queue internal flags Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 26/35] ALSA: rawmidi: Access runtime->avail always in spinlock Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 27/35] fcntl: Fix potential deadlock in send_sig{io, urg}() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 28/35] rtc: sun6i: Fix memleak in sun6i_rtc_clk_init Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 29/35] module: set MODULE_STATE_GOING state when a module fails to load Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 30/35] quota: Dont overflow quota file offsets Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 31/35] powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe() Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 32/35] NFSv4: Fix a pNFS layout related use-after-free race when freeing the inode Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 33/35] module: delay kobject uevent until after module init call Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 34/35] ALSA: pcm: Clear the full allocated memory at hw_params Greg Kroah-Hartman
2021-01-04 15:57 ` [PATCH 4.19 35/35] dm verity: skip verity work if I/O error when system is shutting down Greg Kroah-Hartman
2021-01-04 17:43 ` [PATCH 4.19 00/35] 4.19.165-rc1 review Daniel Díaz
2021-01-05  9:06   ` Greg Kroah-Hartman
2021-01-04 19:59 ` Pavel Machek
2021-01-04 21:09 ` Jon Hunter
2021-01-05  1:58 ` Guenter Roeck
2021-01-05  9:06   ` Greg Kroah-Hartman
2021-01-05 16:44 ` Shuah Khan
2021-01-06 13:46   ` Greg Kroah-Hartman

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=20210104155704.197670503@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=santosh@fossix.org \
    --cc=stable@vger.kernel.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 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.