Skip to contentSkip to conversation

x86/mm: Reduce tlb flushes from ptep_set_access_flags()

tip:sched/numa tip-bot for Rik van Riel 1 participant 1 message Oct 12, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw
Commit-ID:  d8769ca9a6272795acf650698abe29d8ed149888
Gitweb:     http://git.kernel.org/tip/d8769ca9a6272795acf650698abe29d8ed149888
Author:     Rik van Riel <[email protected]>
AuthorDate: Tue, 9 Oct 2012 15:31:34 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Fri, 12 Oct 2012 12:07:15 +0200

x86/mm: Reduce tlb flushes from ptep_set_access_flags()

If ptep_set_access_flags() is invoked to upgrade access permissions on a PTE, there is no security or data integrity reason to do a remote TLB flush.

Lazily letting another CPU incur a spurious page fault occasionally is (much!) cheaper than aggressively flushing everybody else's TLB.

---
 arch/x86/mm/pgtable.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)
arch/x86/mm/pgtable.c +16 -1
index 8573b83..fc82cf1 100644
@@ -306,11 +306,26 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
 			  pte_t entry, int dirty)
 {
 	int changed = !pte_same(*ptep, entry);
+	/*
+	 * If the page used to be inaccessible (_PAGE_PROTNONE), or
+	 * this call upgrades the access permissions on the same page,
+	 * it is safe to skip the remote TLB flush.
+	 */
+	bool flush_remote = false;
+	if (!pte_accessible(*ptep))
+		flush_remote = false;
+	else if (pte_pfn(*ptep) != pte_pfn(entry) ||
+			(pte_write(*ptep) && !pte_write(entry)) ||
+			(pte_exec(*ptep) && !pte_exec(entry)))
+		flush_remote = true;
 
 	if (changed && dirty) {
 		*ptep = entry;
 		pte_update_defer(vma->vm_mm, address, ptep);
-		flush_tlb_page(vma, address);
+		if (flush_remote)
+			flush_tlb_page(vma, address);
+		else
+			__flush_tlb_one(address);
 	}
 
 	return changed;