diff options
author | Pekka Enberg <penberg@kernel.org> | 2020-08-25 17:48:01 +0200 |
---|---|---|
committer | Palmer Dabbelt <palmerdabbelt@google.com> | 2020-09-16 03:45:59 +0200 |
commit | a51271d99cdd04910227060936d0598ba49fb1cc (patch) | |
tree | a4305ff0611142422a545f5a501a811df3e4221a | |
parent | riscv/mm/fault: Move no context handling to no_context() (diff) | |
download | linux-a51271d99cdd04910227060936d0598ba49fb1cc.tar.xz linux-a51271d99cdd04910227060936d0598ba49fb1cc.zip |
riscv/mm/fault: Move bad area handling to bad_area()
This patch moves the bad area handling in do_page_fault() to bad_area()
function and converts gotos to calls to the new function.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
-rw-r--r-- | arch/riscv/mm/fault.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 1612552478c5..ac9a99255365 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -37,6 +37,22 @@ static inline void no_context(struct pt_regs *regs, unsigned long addr) do_exit(SIGKILL); } +static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, 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); + return; + } + + no_context(regs, addr); +} + /* * This routine handles page faults. It determines the address and the * problem, and then passes it off to one of the appropriate routines. @@ -90,14 +106,20 @@ asmlinkage void do_page_fault(struct pt_regs *regs) retry: mmap_read_lock(mm); vma = find_vma(mm, addr); - if (unlikely(!vma)) - goto bad_area; + if (unlikely(!vma)) { + bad_area(regs, mm, code, addr); + return; + } if (likely(vma->vm_start <= addr)) goto good_area; - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) - goto bad_area; - if (unlikely(expand_stack(vma, addr))) - goto bad_area; + if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { + bad_area(regs, mm, code, addr); + return; + } + if (unlikely(expand_stack(vma, addr))) { + bad_area(regs, mm, code, addr); + return; + } /* * Ok, we have a good vm_area for this memory access, so @@ -108,16 +130,22 @@ good_area: switch (cause) { case EXC_INST_PAGE_FAULT: - if (!(vma->vm_flags & VM_EXEC)) - goto bad_area; + if (!(vma->vm_flags & VM_EXEC)) { + bad_area(regs, mm, code, addr); + return; + } break; case EXC_LOAD_PAGE_FAULT: - if (!(vma->vm_flags & VM_READ)) - goto bad_area; + if (!(vma->vm_flags & VM_READ)) { + bad_area(regs, mm, code, addr); + return; + } break; case EXC_STORE_PAGE_FAULT: - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; + if (!(vma->vm_flags & VM_WRITE)) { + bad_area(regs, mm, code, addr); + return; + } flags |= FAULT_FLAG_WRITE; break; default: @@ -162,21 +190,6 @@ good_area: return; /* - * Something tried to access memory that isn't in our memory map. - * Fix it, but check if it's kernel or user first. - */ -bad_area: - mmap_read_unlock(mm); - /* User mode accesses just cause a SIGSEGV */ - if (user_mode(regs)) { - do_trap(regs, SIGSEGV, code, addr); - return; - } - - no_context(regs, addr); - return; - - /* * We ran out of memory, call the OOM killer, and return the userspace * (which will retry the fault, or kill us if we got oom-killed). */ |