diff options
Diffstat (limited to 'arch/um/kernel/trap.c')
-rw-r--r-- | arch/um/kernel/trap.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 2de81d4d9b57..c3e62e634c0a 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -72,8 +72,8 @@ good_area: | |||
72 | goto out; | 72 | goto out; |
73 | 73 | ||
74 | /* Don't require VM_READ|VM_EXEC for write faults! */ | 74 | /* Don't require VM_READ|VM_EXEC for write faults! */ |
75 | if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) | 75 | if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) |
76 | goto out; | 76 | goto out; |
77 | 77 | ||
78 | do { | 78 | do { |
79 | survive: | 79 | survive: |
@@ -157,18 +157,19 @@ static void segv_handler(int sig, union uml_pt_regs *regs) | |||
157 | * the info in the regs. A pointer to the info then would | 157 | * the info in the regs. A pointer to the info then would |
158 | * give us bad data! | 158 | * give us bad data! |
159 | */ | 159 | */ |
160 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | 160 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, |
161 | union uml_pt_regs *regs) | ||
161 | { | 162 | { |
162 | struct siginfo si; | 163 | struct siginfo si; |
163 | void *catcher; | 164 | void *catcher; |
164 | int err; | 165 | int err; |
165 | int is_write = FAULT_WRITE(fi); | 166 | int is_write = FAULT_WRITE(fi); |
166 | unsigned long address = FAULT_ADDRESS(fi); | 167 | unsigned long address = FAULT_ADDRESS(fi); |
167 | 168 | ||
168 | if(!is_user && (address >= start_vm) && (address < end_vm)){ | 169 | if(!is_user && (address >= start_vm) && (address < end_vm)){ |
169 | flush_tlb_kernel_vm(); | 170 | flush_tlb_kernel_vm(); |
170 | return(0); | 171 | return 0; |
171 | } | 172 | } |
172 | else if(current->mm == NULL) | 173 | else if(current->mm == NULL) |
173 | panic("Segfault with no mm"); | 174 | panic("Segfault with no mm"); |
174 | 175 | ||
@@ -183,17 +184,17 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
183 | 184 | ||
184 | catcher = current->thread.fault_catcher; | 185 | catcher = current->thread.fault_catcher; |
185 | if(!err) | 186 | if(!err) |
186 | return(0); | 187 | return 0; |
187 | else if(catcher != NULL){ | 188 | else if(catcher != NULL){ |
188 | current->thread.fault_addr = (void *) address; | 189 | current->thread.fault_addr = (void *) address; |
189 | do_longjmp(catcher, 1); | 190 | do_longjmp(catcher, 1); |
190 | } | 191 | } |
191 | else if(current->thread.fault_addr != NULL) | 192 | else if(current->thread.fault_addr != NULL) |
192 | panic("fault_addr set but no fault catcher"); | 193 | panic("fault_addr set but no fault catcher"); |
193 | else if(!is_user && arch_fixup(ip, sc)) | 194 | else if(!is_user && arch_fixup(ip, regs)) |
194 | return(0); | 195 | return 0; |
195 | 196 | ||
196 | if(!is_user) | 197 | if(!is_user) |
197 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", | 198 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", |
198 | address, ip); | 199 | address, ip); |
199 | 200 | ||
@@ -202,7 +203,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
202 | si.si_errno = 0; | 203 | si.si_errno = 0; |
203 | si.si_code = BUS_ADRERR; | 204 | si.si_code = BUS_ADRERR; |
204 | si.si_addr = (void __user *)address; | 205 | si.si_addr = (void __user *)address; |
205 | current->thread.arch.faultinfo = fi; | 206 | current->thread.arch.faultinfo = fi; |
206 | force_sig_info(SIGBUS, &si, current); | 207 | force_sig_info(SIGBUS, &si, current); |
207 | } else if (err == -ENOMEM) { | 208 | } else if (err == -ENOMEM) { |
208 | printk("VM: killing process %s\n", current->comm); | 209 | printk("VM: killing process %s\n", current->comm); |
@@ -211,10 +212,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
211 | BUG_ON(err != -EFAULT); | 212 | BUG_ON(err != -EFAULT); |
212 | si.si_signo = SIGSEGV; | 213 | si.si_signo = SIGSEGV; |
213 | si.si_addr = (void __user *) address; | 214 | si.si_addr = (void __user *) address; |
214 | current->thread.arch.faultinfo = fi; | 215 | current->thread.arch.faultinfo = fi; |
215 | force_sig_info(SIGSEGV, &si, current); | 216 | force_sig_info(SIGSEGV, &si, current); |
216 | } | 217 | } |
217 | return(0); | 218 | return 0; |
218 | } | 219 | } |
219 | 220 | ||
220 | void relay_signal(int sig, union uml_pt_regs *regs) | 221 | void relay_signal(int sig, union uml_pt_regs *regs) |
@@ -229,7 +230,7 @@ void relay_signal(int sig, union uml_pt_regs *regs) | |||
229 | panic("Kernel mode signal %d", sig); | 230 | panic("Kernel mode signal %d", sig); |
230 | } | 231 | } |
231 | 232 | ||
232 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); | 233 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); |
233 | force_sig(sig, current); | 234 | force_sig(sig, current); |
234 | } | 235 | } |
235 | 236 | ||