aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/trap_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/trap_kern.c')
-rw-r--r--arch/um/kernel/trap_kern.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 87cc6fd76ced..95c8f8733baf 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -18,6 +18,7 @@
18#include "asm/a.out.h" 18#include "asm/a.out.h"
19#include "asm/current.h" 19#include "asm/current.h"
20#include "asm/irq.h" 20#include "asm/irq.h"
21#include "sysdep/sigcontext.h"
21#include "user_util.h" 22#include "user_util.h"
22#include "kern_util.h" 23#include "kern_util.h"
23#include "kern.h" 24#include "kern.h"
@@ -25,6 +26,9 @@
25#include "mconsole_kern.h" 26#include "mconsole_kern.h"
26#include "mem.h" 27#include "mem.h"
27#include "mem_kern.h" 28#include "mem_kern.h"
29#ifdef CONFIG_MODE_SKAS
30#include "skas.h"
31#endif
28 32
29/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ 33/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
30int handle_page_fault(unsigned long address, unsigned long ip, 34int handle_page_fault(unsigned long address, unsigned long ip,
@@ -39,6 +43,12 @@ int handle_page_fault(unsigned long address, unsigned long ip,
39 int err = -EFAULT; 43 int err = -EFAULT;
40 44
41 *code_out = SEGV_MAPERR; 45 *code_out = SEGV_MAPERR;
46
47 /* If the fault was during atomic operation, don't take the fault, just
48 * fail. */
49 if (in_atomic())
50 goto out_nosemaphore;
51
42 down_read(&mm->mmap_sem); 52 down_read(&mm->mmap_sem);
43 vma = find_vma(mm, address); 53 vma = find_vma(mm, address);
44 if(!vma) 54 if(!vma)
@@ -89,6 +99,7 @@ survive:
89 flush_tlb_page(vma, address); 99 flush_tlb_page(vma, address);
90out: 100out:
91 up_read(&mm->mmap_sem); 101 up_read(&mm->mmap_sem);
102out_nosemaphore:
92 return(err); 103 return(err);
93 104
94/* 105/*
@@ -125,7 +136,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
125 } 136 }
126 else if(current->mm == NULL) 137 else if(current->mm == NULL)
127 panic("Segfault with no mm"); 138 panic("Segfault with no mm");
128 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 139
140 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
141 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
142 else {
143 err = -EFAULT;
144 /* A thread accessed NULL, we get a fault, but CR2 is invalid.
145 * This code is used in __do_copy_from_user() of TT mode. */
146 address = 0;
147 }
129 148
130 catcher = current->thread.fault_catcher; 149 catcher = current->thread.fault_catcher;
131 if(!err) 150 if(!err)