aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/trap.c')
-rw-r--r--arch/um/kernel/trap.c35
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 {
79survive: 79survive:
@@ -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 */
160unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) 160unsigned 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
220void relay_signal(int sig, union uml_pt_regs *regs) 221void 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