Skip to contentSkip to conversation

Patch "x86/mm: Add TLB purge to free pmd/pte page interfaces" has been added to the 4.4-stable tree

DISCUSSION [email protected] 1 participant 1 message Aug 16, 2018

Subsystems (3)
lore
Share & tools
lore

[email protected]

author Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

x86/mm: Add TLB purge to free pmd/pte page interfaces

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
x86-mm-add-tlb-purge-to-free-pmd-pte-page-interfaces.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 5e0fb5df2ee871b841f96f9cb6a7f2784e96aa4e Mon Sep 17 00:00:00 2001

From: Toshi Kani <[email protected]>
Date: Wed, 27 Jun 2018 08:13:48 -0600
Subject: x86/mm: Add TLB purge to free pmd/pte page interfaces

From: Toshi Kani <[email protected]>

commit 5e0fb5df2ee871b841f96f9cb6a7f2784e96aa4e upstream.

ioremap() calls pud_free_pmd_page() / pmd_free_pte_page() when it creates a pud / pmd map. The following preconditions are met at their entry.
- All pte entries for a target pud/pmd address range have been cleared.
- System-wide TLB purges have been peformed for a target pud/pmd address range.

The preconditions assure that there is no stale TLB entry for the range. Speculation may not cache TLB entries since it requires all levels of page entries, including ptes, to have P & A-bits set for an associated address. However, speculation may cache pud/pmd entries (paging-structure caches) when they have P-bit set.

Add a system-wide TLB purge (INVLPG) to a single page after clearing pud/pmd entry's P-bit.

SDM 4.10.4.1, Operation that Invalidate TLBs and Paging-Structure Caches, states that:
INVLPG invalidates all paging-structure caches associated with the current PCID regardless of the liner addresses to which they correspond.

Fixes 28ee90fe6048 ("x86/mm: implement free pmd/pte page interfaces")
Cc mhocko at suse.com
Cc akpm at linux-foundation.org
Cc hpa at zytor.com
Cc cpandya at codeaurora.org
Cc linux-mm at kvack.org
Cc linux-arm-kernel at lists.infradead.org
Cc Joerg Roedel <[email protected]>
Cc stable at vger.kernel.org
Cc Andrew Morton <[email protected]>
Cc Michal Hocko <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
---
 arch/x86/mm/pgtable.c |   38 +++++++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 7 deletions(-)
arch/x86/mm/pgtable.c +31 -7
@@ -682,24 +682,44 @@ int pmd_clear_huge(pmd_t *pmd)
  * @pud: Pointer to a PUD.
  * @addr: Virtual address associated with pud.
  *
- * Context: The pud range has been unmaped and TLB purged.
+ * Context: The pud range has been unmapped and TLB purged.
  * Return: 1 if clearing the entry succeeded. 0 otherwise.
+ *
+ * NOTE: Callers must allow a single page allocation.
  */
 int pud_free_pmd_page(pud_t *pud, unsigned long addr)
 {
-	pmd_t *pmd;
+	pmd_t *pmd, *pmd_sv;
+	pte_t *pte;
 	int i;
 
 	if (pud_none(*pud))
 		return 1;
 
 	pmd = (pmd_t *)pud_page_vaddr(*pud);
-
-	for (i = 0; i < PTRS_PER_PMD; i++)
-		if (!pmd_free_pte_page(&pmd[i], addr + (i * PMD_SIZE)))
-			return 0;
+	pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
+	if (!pmd_sv)
+		return 0;
+
+	for (i = 0; i < PTRS_PER_PMD; i++) {
+		pmd_sv[i] = pmd[i];
+		if (!pmd_none(pmd[i]))
+			pmd_clear(&pmd[i]);
+	}
 
 	pud_clear(pud);
+
+	/* INVLPG to clear all paging-structure caches */
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
+
+	for (i = 0; i < PTRS_PER_PMD; i++) {
+		if (!pmd_none(pmd_sv[i])) {
+			pte = (pte_t *)pmd_page_vaddr(pmd_sv[i]);
+			free_page((unsigned long)pte);
+		}
+	}
+
+	free_page((unsigned long)pmd_sv);
 	free_page((unsigned long)pmd);
 
 	return 1;
@@ -710,7 +730,7 @@ int pud_free_pmd_page(pud_t *pud, unsign
  * @pmd: Pointer to a PMD.
  * @addr: Virtual address associated with pmd.
  *
- * Context: The pmd range has been unmaped and TLB purged.
+ * Context: The pmd range has been unmapped and TLB purged.
  * Return: 1 if clearing the entry succeeded. 0 otherwise.
  */
 int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
@@ -722,6 +742,10 @@ int pmd_free_pte_page(pmd_t *pmd, unsign
 
 	pte = (pte_t *)pmd_page_vaddr(*pmd);
 	pmd_clear(pmd);
+
+	/* INVLPG to clear all paging-structure caches */
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
+
 	free_page((unsigned long)pte);
 
 	return 1;

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/x86-mm-disable-ioremap-free-page-handling-on-x86-pae.patch queue-4.4/ioremap-update-pgtable-free-interfaces-with-addr.patch queue-4.4/x86-mm-add-tlb-purge-to-free-pmd-pte-page-interfaces.patch