]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
x86: mm: only do a local tlb flush in ptep_set_access_flags()
authorRik van Riel <riel@redhat.com>
Tue, 6 Nov 2012 09:54:47 +0000 (09:54 +0000)
committerMel Gorman <mgorman@suse.de>
Tue, 11 Dec 2012 14:28:33 +0000 (14:28 +0000)
The function ptep_set_access_flags() is only ever invoked to set access
flags or add write permission on a PTE.  The write bit is only ever set
together with the dirty bit.

Because we only ever upgrade a PTE, it is safe to skip flushing entries on
remote TLBs. The worst that can happen is a spurious page fault on other
CPUs, which would flush that TLB entry.

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

Signed-off-by: Rik van Riel <riel@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Michel Lespinasse <walken@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
arch/x86/mm/pgtable.c

index 8573b83a63d037bf2f7eb09c8922b94c2b535c45..be3bb4690887e283712a77fb9b6cb23ba5a6b2a1 100644 (file)
@@ -301,6 +301,13 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
        free_page((unsigned long)pgd);
 }
 
+/*
+ * Used to set accessed or dirty bits in the page table entries
+ * on other architectures. On x86, the accessed and dirty bits
+ * are tracked by hardware. However, do_wp_page calls this function
+ * to also make the pte writeable at the same time the dirty bit is
+ * set. In that case we do actually need to write the PTE.
+ */
 int ptep_set_access_flags(struct vm_area_struct *vma,
                          unsigned long address, pte_t *ptep,
                          pte_t entry, int dirty)
@@ -310,7 +317,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
        if (changed && dirty) {
                *ptep = entry;
                pte_update_defer(vma->vm_mm, address, ptep);
-               flush_tlb_page(vma, address);
+               __flush_tlb_one(address);
        }
 
        return changed;