riscv: mm: try VMA lock-based page fault handling first
[platform/kernel/linux-starfive.git] / arch / riscv / mm / fault.c
index b023fb3..e52ed89 100644 (file)
@@ -274,6 +274,36 @@ void handle_page_fault(struct pt_regs *regs)
                flags |= FAULT_FLAG_WRITE;
        else if (cause == EXC_INST_PAGE_FAULT)
                flags |= FAULT_FLAG_INSTRUCTION;
+#ifdef CONFIG_PER_VMA_LOCK
+       if (!(flags & FAULT_FLAG_USER))
+               goto lock_mmap;
+
+       vma = lock_vma_under_rcu(mm, addr);
+       if (!vma)
+               goto lock_mmap;
+
+       if (unlikely(access_error(cause, vma))) {
+               vma_end_read(vma);
+               goto lock_mmap;
+       }
+
+       fault = handle_mm_fault(vma, addr, flags | FAULT_FLAG_VMA_LOCK, regs);
+       vma_end_read(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)) {
+               if (!user_mode(regs))
+                       no_context(regs, addr);
+               return;
+       }
+lock_mmap:
+#endif /* CONFIG_PER_VMA_LOCK */
+
 retry:
        mmap_read_lock(mm);
        vma = find_vma(mm, addr);
@@ -343,6 +373,9 @@ good_area:
 
        mmap_read_unlock(mm);
 
+#ifdef CONFIG_PER_VMA_LOCK
+done:
+#endif
        if (unlikely(fault & VM_FAULT_ERROR)) {
                tsk->thread.bad_cause = cause;
                mm_fault_error(regs, addr, fault);