aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/include/arch.h2
-rw-r--r--arch/um/include/kern_util.h2
-rw-r--r--arch/um/kernel/trap.c35
-rw-r--r--arch/um/os-Linux/skas/trap.c17
-rw-r--r--arch/um/sys-i386/fault.c18
-rw-r--r--arch/um/sys-i386/signal.c41
-rw-r--r--arch/um/sys-x86_64/fault.c30
-rw-r--r--arch/um/sys-x86_64/signal.c2
8 files changed, 63 insertions, 84 deletions
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 8e11dd7c1adb..10ad52daa8c5 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -9,7 +9,7 @@
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10 10
11extern void arch_check_bugs(void); 11extern void arch_check_bugs(void);
12extern int arch_fixup(unsigned long address, void *sc_ptr); 12extern int arch_fixup(unsigned long address, union uml_pt_regs *regs);
13extern int arch_handle_signal(int sig, union uml_pt_regs *regs); 13extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
14 14
15#endif 15#endif
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index ae434a9b400d..092a2841556f 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -44,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic);
44extern int do_signal(void); 44extern int do_signal(void);
45extern int is_stack_fault(unsigned long sp); 45extern int is_stack_fault(unsigned long sp);
46extern unsigned long segv(struct faultinfo fi, unsigned long ip, 46extern unsigned long segv(struct faultinfo fi, unsigned long ip,
47 int is_user, void *sc); 47 int is_user, union uml_pt_regs *regs);
48extern int handle_page_fault(unsigned long address, unsigned long ip, 48extern int handle_page_fault(unsigned long address, unsigned long ip,
49 int is_write, int is_user, int *code_out); 49 int is_write, int is_user, int *code_out);
50extern void syscall_ready(void); 50extern void syscall_ready(void);
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
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
index f104427d2caf..6a20d08caf91 100644
--- a/arch/um/os-Linux/skas/trap.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -18,10 +18,9 @@
18void sig_handler_common_skas(int sig, void *sc_ptr) 18void sig_handler_common_skas(int sig, void *sc_ptr)
19{ 19{
20 struct sigcontext *sc = sc_ptr; 20 struct sigcontext *sc = sc_ptr;
21 struct skas_regs *r; 21 union uml_pt_regs *r;
22 void (*handler)(int, union uml_pt_regs *); 22 void (*handler)(int, union uml_pt_regs *);
23 int save_errno = errno; 23 int save_user, save_errno = errno;
24 int save_user;
25 24
26 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 25 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
27 * handler. This can happen in copy_user, and if SEGV is disabled, 26 * handler. This can happen in copy_user, and if SEGV is disabled,
@@ -31,13 +30,13 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
31 if(sig == SIGSEGV) 30 if(sig == SIGSEGV)
32 change_sig(SIGSEGV, 1); 31 change_sig(SIGSEGV, 1);
33 32
34 r = &TASK_REGS(get_current())->skas; 33 r = TASK_REGS(get_current());
35 save_user = r->is_user; 34 save_user = r->skas.is_user;
36 r->is_user = 0; 35 r->skas.is_user = 0;
37 if ( sig == SIGFPE || sig == SIGSEGV || 36 if ( sig == SIGFPE || sig == SIGSEGV ||
38 sig == SIGBUS || sig == SIGILL || 37 sig == SIGBUS || sig == SIGILL ||
39 sig == SIGTRAP ) { 38 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 39 GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc);
41 } 40 }
42 41
43 change_sig(SIGUSR1, 1); 42 change_sig(SIGUSR1, 1);
@@ -49,10 +48,10 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
49 sig != SIGVTALRM && sig != SIGALRM) 48 sig != SIGVTALRM && sig != SIGALRM)
50 unblock_signals(); 49 unblock_signals();
51 50
52 handler(sig, (union uml_pt_regs *) r); 51 handler(sig, r);
53 52
54 errno = save_errno; 53 errno = save_errno;
55 r->is_user = save_user; 54 r->skas.is_user = save_user;
56} 55}
57 56
58extern int ptrace_faultinfo; 57extern int ptrace_faultinfo;
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
index d0bbcdfdb53f..745b4fd49e9f 100644
--- a/arch/um/sys-i386/fault.c
+++ b/arch/um/sys-i386/fault.c
@@ -3,9 +3,7 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h>
7#include "sysdep/ptrace.h" 6#include "sysdep/ptrace.h"
8#include "sysdep/sigcontext.h"
9 7
10/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ 8/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
11struct exception_table_entry 9struct exception_table_entry
@@ -17,26 +15,14 @@ struct exception_table_entry
17const struct exception_table_entry *search_exception_tables(unsigned long add); 15const struct exception_table_entry *search_exception_tables(unsigned long add);
18 16
19/* Compare this to arch/i386/mm/extable.c:fixup_exception() */ 17/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
20int arch_fixup(unsigned long address, void *sc_ptr) 18int arch_fixup(unsigned long address, union uml_pt_regs *regs)
21{ 19{
22 struct sigcontext *sc = sc_ptr;
23 const struct exception_table_entry *fixup; 20 const struct exception_table_entry *fixup;
24 21
25 fixup = search_exception_tables(address); 22 fixup = search_exception_tables(address);
26 if(fixup != 0){ 23 if(fixup != 0){
27 sc->eip = fixup->fixup; 24 UPT_IP(regs) = fixup->fixup;
28 return(1); 25 return(1);
29 } 26 }
30 return(0); 27 return(0);
31} 28}
32
33/*
34 * Overrides for Emacs so that we follow Linus's tabbing style.
35 * Emacs will notice this stuff at the end of the file and automatically
36 * adjust the settings for this buffer only. This must remain at the end
37 * of the file.
38 * ---------------------------------------------------------------------------
39 * Local variables:
40 * c-file-style: "linux"
41 * End:
42 */
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 3f6acd667717..42ecf8e8ad08 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -28,7 +28,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
28 err = copy_from_user(&sc, from, sizeof(sc)); 28 err = copy_from_user(&sc, from, sizeof(sc));
29 err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); 29 err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
30 if(err) 30 if(err)
31 return(err); 31 return err;
32 32
33 REGS_GS(regs->regs.skas.regs) = sc.gs; 33 REGS_GS(regs->regs.skas.regs) = sc.gs;
34 REGS_FS(regs->regs.skas.regs) = sc.fs; 34 REGS_FS(regs->regs.skas.regs) = sc.fs;
@@ -50,11 +50,11 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
50 err = restore_fp_registers(userspace_pid[0], fpregs); 50 err = restore_fp_registers(userspace_pid[0], fpregs);
51 if(err < 0){ 51 if(err < 0){
52 printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " 52 printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
53 "errno = %d\n", err); 53 "errno = %d\n", -err);
54 return(1); 54 return err;
55 } 55 }
56 56
57 return(0); 57 return 0;
58} 58}
59 59
60int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, 60int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
@@ -90,16 +90,16 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *t
90 if(err < 0){ 90 if(err < 0){
91 printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " 91 printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
92 "errno = %d\n", err); 92 "errno = %d\n", err);
93 return(1); 93 return 1;
94 } 94 }
95 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); 95 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
96 sc.fpstate = to_fp; 96 sc.fpstate = to_fp;
97 97
98 if(err) 98 if(err)
99 return(err); 99 return err;
100 100
101 return(copy_to_user(to, &sc, sizeof(sc)) || 101 return copy_to_user(to, &sc, sizeof(sc)) ||
102 copy_to_user(to_fp, fpregs, sizeof(fpregs))); 102 copy_to_user(to_fp, fpregs, sizeof(fpregs));
103} 103}
104#endif 104#endif
105 105
@@ -129,7 +129,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
129 to->fpstate = to_fp; 129 to->fpstate = to_fp;
130 if(to_fp != NULL) 130 if(to_fp != NULL)
131 err |= copy_from_user(to_fp, from_fp, fpsize); 131 err |= copy_from_user(to_fp, from_fp, fpsize);
132 return(err); 132 return err;
133} 133}
134 134
135int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, 135int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
@@ -164,15 +164,15 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
164 ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, 164 ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
165 sizeof(struct _fpstate)), 165 sizeof(struct _fpstate)),
166 copy_sc_from_user_skas(to, from)); 166 copy_sc_from_user_skas(to, from));
167 return(ret); 167 return ret;
168} 168}
169 169
170static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, 170static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
171 struct pt_regs *from, unsigned long sp) 171 struct pt_regs *from, unsigned long sp)
172{ 172{
173 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 173 return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
174 sizeof(*fp), sp), 174 sizeof(*fp), sp),
175 copy_sc_to_user_skas(to, fp, from, sp))); 175 copy_sc_to_user_skas(to, fp, from, sp));
176} 176}
177 177
178static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, 178static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
@@ -185,7 +185,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __u
185 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); 185 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
186 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp); 186 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
187 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); 187 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
188 return(err); 188 return err;
189} 189}
190 190
191struct sigframe 191struct sigframe
@@ -359,7 +359,7 @@ long sys_sigreturn(struct pt_regs regs)
359 359
360 /* Avoid ERESTART handling */ 360 /* Avoid ERESTART handling */
361 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; 361 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
362 return(PT_REGS_SYSCALL_RET(&current->thread.regs)); 362 return PT_REGS_SYSCALL_RET(&current->thread.regs);
363 363
364 segfault: 364 segfault:
365 force_sig(SIGSEGV, current); 365 force_sig(SIGSEGV, current);
@@ -389,20 +389,9 @@ long sys_rt_sigreturn(struct pt_regs regs)
389 389
390 /* Avoid ERESTART handling */ 390 /* Avoid ERESTART handling */
391 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; 391 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
392 return(PT_REGS_SYSCALL_RET(&current->thread.regs)); 392 return PT_REGS_SYSCALL_RET(&current->thread.regs);
393 393
394 segfault: 394 segfault:
395 force_sig(SIGSEGV, current); 395 force_sig(SIGSEGV, current);
396 return 0; 396 return 0;
397} 397}
398
399/*
400 * Overrides for Emacs so that we follow Linus's tabbing style.
401 * Emacs will notice this stuff at the end of the file and automatically
402 * adjust the settings for this buffer only. This must remain at the end
403 * of the file.
404 * ---------------------------------------------------------------------------
405 * Local variables:
406 * c-file-style: "linux"
407 * End:
408 */
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
index cee1513c5c31..4636b1465b6c 100644
--- a/arch/um/sys-x86_64/fault.c
+++ b/arch/um/sys-x86_64/fault.c
@@ -4,20 +4,24 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "user.h" 7#include "sysdep/ptrace.h"
8 8
9int arch_fixup(unsigned long address, void *sc_ptr) 9/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
10struct exception_table_entry
10{ 11{
11 /* XXX search_exception_tables() */ 12 unsigned long insn;
13 unsigned long fixup;
14};
15
16const struct exception_table_entry *search_exception_tables(unsigned long add);
17int arch_fixup(unsigned long address, union uml_pt_regs *regs)
18{
19 const struct exception_table_entry *fixup;
20
21 fixup = search_exception_tables(address);
22 if(fixup != 0){
23 UPT_IP(regs) = fixup->fixup;
24 return(1);
25 }
12 return(0); 26 return(0);
13} 27}
14
15/* Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index af2f017617b4..068006213598 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -51,7 +51,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
51 51
52#undef GETREG 52#undef GETREG
53 53
54 return(err); 54 return err;
55} 55}
56 56
57int copy_sc_to_user_skas(struct sigcontext __user *to, 57int copy_sc_to_user_skas(struct sigcontext __user *to,