]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
powerc/mm: try VMA lock-based page fault handling first
authorLaurent Dufour <ldufour@linux.ibm.com>
Fri, 3 Jun 2022 13:15:23 +0000 (15:15 +0200)
committerSuren Baghdasaryan <surenb@google.com>
Wed, 23 Nov 2022 02:09:47 +0000 (02:09 +0000)
Attempt VMA lock-based page fault handling first, and fall back to the
existing mmap_lock-based handling if that fails.
Copied from "x86/mm: try VMA lock-based page fault handling first"

Signed-off-by: Laurent Dufour <ldufour@linux.ibm.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
arch/powerpc/mm/fault.c
arch/powerpc/platforms/powernv/Kconfig
arch/powerpc/platforms/pseries/Kconfig

index 2bef19cc1b98c659b38109ba47ea2811d0976b66..f92f8956d5f2119daa5fb136b9cecc93af96392e 100644 (file)
@@ -469,6 +469,44 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
        if (is_exec)
                flags |= FAULT_FLAG_INSTRUCTION;
 
+#ifdef CONFIG_PER_VMA_LOCK
+       if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1)
+               goto lock_mmap;
+
+       vma = lock_vma_under_rcu(mm, address);
+       if (!vma)
+               goto lock_mmap;
+
+       if (unlikely(access_pkey_error(is_write, is_exec,
+                                      (error_code & DSISR_KEYFAULT), vma))) {
+               int rc = bad_access_pkey(regs, address, vma);
+
+               vma_read_unlock(vma);
+               return rc;
+       }
+
+       if (unlikely(access_error(is_write, is_exec, vma))) {
+               int rc = bad_access(regs, address);
+
+               vma_read_unlock(vma);
+               return rc;
+       }
+
+       fault = handle_mm_fault(vma, address, flags | FAULT_FLAG_VMA_LOCK, regs);
+       vma_read_unlock(vma);
+
+       if (!(fault & VM_FAULT_RETRY)) {
+               count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
+               goto done;
+       }
+       count_vm_vma_lock_event(VMA_LOCK_RETRY);
+
+       if (fault_signal_pending(fault, regs))
+               return user_mode(regs) ? 0 : SIGBUS;
+
+lock_mmap:
+#endif /* CONFIG_PER_VMA_LOCK */
+
        /* When running in the kernel we expect faults to occur only to
         * addresses in user space.  All other faults represent errors in the
         * kernel and should generate an OOPS.  Unfortunately, in the case of an
@@ -545,6 +583,9 @@ retry:
 
        mmap_read_unlock(current->mm);
 
+#ifdef CONFIG_PER_VMA_LOCK
+done:
+#endif
        if (unlikely(fault & VM_FAULT_ERROR))
                return mm_fault_error(regs, address, fault);
 
index ae248a161b435528317ea54dd82c29781fa5e1e2..70a46acc70d63d422d61039bd6f3d66ad6d65ed5 100644 (file)
@@ -16,6 +16,7 @@ config PPC_POWERNV
        select PPC_DOORBELL
        select MMU_NOTIFIER
        select FORCE_SMP
+       select ARCH_SUPPORTS_PER_VMA_LOCK
        default y
 
 config OPAL_PRD
index a3b4d99567cbec70bdfbc49e49a920269648561b..e036a04ff1ca8d5840a67f2f518046e9594183a2 100644 (file)
@@ -21,6 +21,7 @@ config PPC_PSERIES
        select HOTPLUG_CPU
        select FORCE_SMP
        select SWIOTLB
+       select ARCH_SUPPORTS_PER_VMA_LOCK
        default y
 
 config PARAVIRT