Loading arch/riscv/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ config RISCV select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA if MODULES select MODULE_SECTIONS if MODULES select OF Loading arch/riscv/mm/fault.c +13 −18 Original line number Diff line number Diff line Loading @@ -84,13 +84,13 @@ static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_f BUG(); } static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) static inline void bad_area_nosemaphore(struct pt_regs *regs, int code, unsigned long addr) { /* * Something tried to access memory that isn't in our memory map. * Fix it, but check if it's kernel or user first. */ mmap_read_unlock(mm); /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { do_trap(regs, SIGSEGV, code, addr); Loading @@ -100,6 +100,15 @@ static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code no_context(regs, addr); } static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) { mmap_read_unlock(mm); bad_area_nosemaphore(regs, code, addr); } static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long addr) { pgd_t *pgd, *pgd_k; Loading Loading @@ -287,23 +296,10 @@ void handle_page_fault(struct pt_regs *regs) else if (cause == EXC_INST_PAGE_FAULT) flags |= FAULT_FLAG_INSTRUCTION; retry: mmap_read_lock(mm); vma = find_vma(mm, addr); vma = lock_mm_and_find_vma(mm, addr, regs); if (unlikely(!vma)) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); return; } if (likely(vma->vm_start <= addr)) goto good_area; if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); return; } if (unlikely(expand_stack(vma, addr))) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); bad_area_nosemaphore(regs, code, addr); return; } Loading @@ -311,7 +307,6 @@ void handle_page_fault(struct pt_regs *regs) * Ok, we have a good vm_area for this memory access, so * we can handle it. */ good_area: code = SEGV_ACCERR; if (unlikely(access_error(cause, vma))) { Loading Loading
arch/riscv/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ config RISCV select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA if MODULES select MODULE_SECTIONS if MODULES select OF Loading
arch/riscv/mm/fault.c +13 −18 Original line number Diff line number Diff line Loading @@ -84,13 +84,13 @@ static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_f BUG(); } static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) static inline void bad_area_nosemaphore(struct pt_regs *regs, int code, unsigned long addr) { /* * Something tried to access memory that isn't in our memory map. * Fix it, but check if it's kernel or user first. */ mmap_read_unlock(mm); /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { do_trap(regs, SIGSEGV, code, addr); Loading @@ -100,6 +100,15 @@ static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code no_context(regs, addr); } static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) { mmap_read_unlock(mm); bad_area_nosemaphore(regs, code, addr); } static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long addr) { pgd_t *pgd, *pgd_k; Loading Loading @@ -287,23 +296,10 @@ void handle_page_fault(struct pt_regs *regs) else if (cause == EXC_INST_PAGE_FAULT) flags |= FAULT_FLAG_INSTRUCTION; retry: mmap_read_lock(mm); vma = find_vma(mm, addr); vma = lock_mm_and_find_vma(mm, addr, regs); if (unlikely(!vma)) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); return; } if (likely(vma->vm_start <= addr)) goto good_area; if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); return; } if (unlikely(expand_stack(vma, addr))) { tsk->thread.bad_cause = cause; bad_area(regs, mm, code, addr); bad_area_nosemaphore(regs, code, addr); return; } Loading @@ -311,7 +307,6 @@ void handle_page_fault(struct pt_regs *regs) * Ok, we have a good vm_area for this memory access, so * we can handle it. */ good_area: code = SEGV_ACCERR; if (unlikely(access_error(cause, vma))) { Loading