]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/um/sys-i386/signal.c
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
6 #include "linux/signal.h"
7 #include "linux/ptrace.h"
8 #include "asm/current.h"
9 #include "asm/ucontext.h"
10 #include "asm/uaccess.h"
11 #include "asm/unistd.h"
12 #include "frame_kern.h"
13 #include "signal_user.h"
14 #include "sigcontext.h"
15 #include "registers.h"
18 #ifdef CONFIG_MODE_SKAS
22 static int copy_sc_from_user_skas(struct pt_regs
*regs
,
23 struct sigcontext
*from
)
26 unsigned long fpregs
[HOST_FP_SIZE
];
29 err
= copy_from_user(&sc
, from
, sizeof(sc
));
30 err
|= copy_from_user(fpregs
, sc
.fpstate
, sizeof(fpregs
));
34 REGS_GS(regs
->regs
.skas
.regs
) = sc
.gs
;
35 REGS_FS(regs
->regs
.skas
.regs
) = sc
.fs
;
36 REGS_ES(regs
->regs
.skas
.regs
) = sc
.es
;
37 REGS_DS(regs
->regs
.skas
.regs
) = sc
.ds
;
38 REGS_EDI(regs
->regs
.skas
.regs
) = sc
.edi
;
39 REGS_ESI(regs
->regs
.skas
.regs
) = sc
.esi
;
40 REGS_EBP(regs
->regs
.skas
.regs
) = sc
.ebp
;
41 REGS_SP(regs
->regs
.skas
.regs
) = sc
.esp
;
42 REGS_EBX(regs
->regs
.skas
.regs
) = sc
.ebx
;
43 REGS_EDX(regs
->regs
.skas
.regs
) = sc
.edx
;
44 REGS_ECX(regs
->regs
.skas
.regs
) = sc
.ecx
;
45 REGS_EAX(regs
->regs
.skas
.regs
) = sc
.eax
;
46 REGS_IP(regs
->regs
.skas
.regs
) = sc
.eip
;
47 REGS_CS(regs
->regs
.skas
.regs
) = sc
.cs
;
48 REGS_EFLAGS(regs
->regs
.skas
.regs
) = sc
.eflags
;
49 REGS_SS(regs
->regs
.skas
.regs
) = sc
.ss
;
50 regs
->regs
.skas
.fault_addr
= sc
.cr2
;
51 regs
->regs
.skas
.fault_type
= FAULT_WRITE(sc
.err
);
52 regs
->regs
.skas
.trap_type
= sc
.trapno
;
54 err
= restore_fp_registers(userspace_pid
[0], fpregs
);
56 printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
64 int copy_sc_to_user_skas(struct sigcontext
*to
, struct _fpstate
*to_fp
,
65 struct pt_regs
*regs
, unsigned long fault_addr
,
69 unsigned long fpregs
[HOST_FP_SIZE
];
72 sc
.gs
= REGS_GS(regs
->regs
.skas
.regs
);
73 sc
.fs
= REGS_FS(regs
->regs
.skas
.regs
);
74 sc
.es
= REGS_ES(regs
->regs
.skas
.regs
);
75 sc
.ds
= REGS_DS(regs
->regs
.skas
.regs
);
76 sc
.edi
= REGS_EDI(regs
->regs
.skas
.regs
);
77 sc
.esi
= REGS_ESI(regs
->regs
.skas
.regs
);
78 sc
.ebp
= REGS_EBP(regs
->regs
.skas
.regs
);
79 sc
.esp
= REGS_SP(regs
->regs
.skas
.regs
);
80 sc
.ebx
= REGS_EBX(regs
->regs
.skas
.regs
);
81 sc
.edx
= REGS_EDX(regs
->regs
.skas
.regs
);
82 sc
.ecx
= REGS_ECX(regs
->regs
.skas
.regs
);
83 sc
.eax
= REGS_EAX(regs
->regs
.skas
.regs
);
84 sc
.eip
= REGS_IP(regs
->regs
.skas
.regs
);
85 sc
.cs
= REGS_CS(regs
->regs
.skas
.regs
);
86 sc
.eflags
= REGS_EFLAGS(regs
->regs
.skas
.regs
);
87 sc
.esp_at_signal
= regs
->regs
.skas
.regs
[UESP
];
88 sc
.ss
= regs
->regs
.skas
.regs
[SS
];
90 sc
.err
= TO_SC_ERR(fault_type
);
91 sc
.trapno
= regs
->regs
.skas
.trap_type
;
93 err
= save_fp_registers(userspace_pid
[0], fpregs
);
95 printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
99 to_fp
= (to_fp
? to_fp
: (struct _fpstate
*) (to
+ 1));
105 return(copy_to_user(to
, &sc
, sizeof(sc
)) ||
106 copy_to_user(to_fp
, fpregs
, sizeof(fpregs
)));
110 #ifdef CONFIG_MODE_TT
112 /* These copy a sigcontext to/from userspace. They copy the fpstate pointer,
113 * blowing away the old, good one. So, that value is saved, and then restored
114 * after the sigcontext copy. In copy_from, the variable holding the saved
115 * fpstate pointer, and the sigcontext that it should be restored to are both
116 * in the kernel, so we can just restore using an assignment. In copy_to, the
117 * saved pointer is in the kernel, but the sigcontext is in userspace, so we
120 int copy_sc_from_user_tt(struct sigcontext
*to
, struct sigcontext
*from
,
123 struct _fpstate
*to_fp
, *from_fp
;
128 from_fp
= from
->fpstate
;
130 err
= copy_from_user(to
, from
, sizeof(*to
));
134 err
|= copy_from_user(to_fp
, from_fp
, fpsize
);
138 int copy_sc_to_user_tt(struct sigcontext
*to
, struct _fpstate
*fp
,
139 struct sigcontext
*from
, int fpsize
)
141 struct _fpstate
*to_fp
, *from_fp
;
144 to_fp
= (fp
? fp
: (struct _fpstate
*) (to
+ 1));
145 from_fp
= from
->fpstate
;
146 err
= copy_to_user(to
, from
, sizeof(*to
));
148 err
|= copy_to_user(&to
->fpstate
, &to_fp
, sizeof(to
->fpstate
));
149 err
|= copy_to_user(to_fp
, from_fp
, fpsize
);
155 static int copy_sc_from_user(struct pt_regs
*to
, void __user
*from
)
159 ret
= CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to
->regs
), from
,
160 sizeof(struct _fpstate
)),
161 copy_sc_from_user_skas(to
, from
));
165 static int copy_sc_to_user(struct sigcontext
*to
, struct _fpstate
*fp
,
166 struct pt_regs
*from
)
168 return(CHOOSE_MODE(copy_sc_to_user_tt(to
, fp
, UPT_SC(&from
->regs
),
170 copy_sc_to_user_skas(to
, fp
, from
,
172 current
->thread
.err
)));
175 static int copy_ucontext_to_user(struct ucontext
*uc
, struct _fpstate
*fp
,
176 sigset_t
*set
, unsigned long sp
)
180 err
|= put_user(current
->sas_ss_sp
, &uc
->uc_stack
.ss_sp
);
181 err
|= put_user(sas_ss_flags(sp
), &uc
->uc_stack
.ss_flags
);
182 err
|= put_user(current
->sas_ss_size
, &uc
->uc_stack
.ss_size
);
183 err
|= copy_sc_to_user(&uc
->uc_mcontext
, fp
, ¤t
->thread
.regs
);
184 err
|= copy_to_user(&uc
->uc_sigmask
, set
, sizeof(*set
));
192 struct sigcontext sc
;
193 struct _fpstate fpstate
;
194 unsigned long extramask
[_NSIG_WORDS
-1];
202 struct siginfo
*pinfo
;
206 struct _fpstate fpstate
;
210 int setup_signal_stack_sc(unsigned long stack_top
, int sig
,
211 struct k_sigaction
*ka
, struct pt_regs
*regs
,
214 struct sigframe __user
*frame
;
219 frame
= (struct sigframe
*) stack_top
- 1;
220 if (!access_ok(VERIFY_WRITE
, frame
, sizeof(*frame
)))
223 restorer
= (void *) frame
->retcode
;
224 if(ka
->sa
.sa_flags
& SA_RESTORER
)
225 restorer
= ka
->sa
.sa_restorer
;
227 err
|= __put_user(restorer
, &frame
->pretcode
);
228 err
|= __put_user(sig
, &frame
->sig
);
229 err
|= copy_sc_to_user(&frame
->sc
, NULL
, regs
);
230 err
|= __put_user(mask
->sig
[0], &frame
->sc
.oldmask
);
232 err
|= __copy_to_user(&frame
->extramask
, &mask
->sig
[1],
233 sizeof(frame
->extramask
));
236 * This is popl %eax ; movl $,%eax ; int $0x80
238 * WE DO NOT USE IT ANY MORE! It's only left here for historical
239 * reasons and because gdb uses it as a signature to notice
240 * signal handler stack frames.
242 err
|= __put_user(0xb858, (short __user
*)(frame
->retcode
+0));
243 err
|= __put_user(__NR_sigreturn
, (int __user
*)(frame
->retcode
+2));
244 err
|= __put_user(0x80cd, (short __user
*)(frame
->retcode
+6));
249 PT_REGS_SP(regs
) = (unsigned long) frame
;
250 PT_REGS_IP(regs
) = (unsigned long) ka
->sa
.sa_handler
;
251 PT_REGS_EAX(regs
) = (unsigned long) sig
;
252 PT_REGS_EDX(regs
) = (unsigned long) 0;
253 PT_REGS_ECX(regs
) = (unsigned long) 0;
255 if ((current
->ptrace
& PT_DTRACE
) && (current
->ptrace
& PT_PTRACED
))
256 ptrace_notify(SIGTRAP
);
260 int setup_signal_stack_si(unsigned long stack_top
, int sig
,
261 struct k_sigaction
*ka
, struct pt_regs
*regs
,
262 siginfo_t
*info
, sigset_t
*mask
)
264 struct rt_sigframe __user
*frame
;
269 frame
= (struct rt_sigframe
*) stack_top
- 1;
270 if (!access_ok(VERIFY_WRITE
, frame
, sizeof(*frame
)))
273 restorer
= (void *) frame
->retcode
;
274 if(ka
->sa
.sa_flags
& SA_RESTORER
)
275 restorer
= ka
->sa
.sa_restorer
;
277 err
|= __put_user(restorer
, &frame
->pretcode
);
278 err
|= __put_user(sig
, &frame
->sig
);
279 err
|= __put_user(&frame
->info
, &frame
->pinfo
);
280 err
|= __put_user(&frame
->uc
, &frame
->puc
);
281 err
|= copy_siginfo_to_user(&frame
->info
, info
);
282 err
|= copy_ucontext_to_user(&frame
->uc
, &frame
->fpstate
, mask
,
286 * This is movl $,%eax ; int $0x80
288 * WE DO NOT USE IT ANY MORE! It's only left here for historical
289 * reasons and because gdb uses it as a signature to notice
290 * signal handler stack frames.
292 err
|= __put_user(0xb8, (char __user
*)(frame
->retcode
+0));
293 err
|= __put_user(__NR_rt_sigreturn
, (int __user
*)(frame
->retcode
+1));
294 err
|= __put_user(0x80cd, (short __user
*)(frame
->retcode
+5));
299 PT_REGS_SP(regs
) = (unsigned long) frame
;
300 PT_REGS_IP(regs
) = (unsigned long) ka
->sa
.sa_handler
;
301 PT_REGS_EAX(regs
) = (unsigned long) sig
;
302 PT_REGS_EDX(regs
) = (unsigned long) &frame
->info
;
303 PT_REGS_ECX(regs
) = (unsigned long) &frame
->uc
;
305 if ((current
->ptrace
& PT_DTRACE
) && (current
->ptrace
& PT_PTRACED
))
306 ptrace_notify(SIGTRAP
);
310 long sys_sigreturn(struct pt_regs regs
)
312 unsigned long sp
= PT_REGS_SP(¤t
->thread
.regs
);
313 struct sigframe __user
*frame
= (struct sigframe
*)(sp
- 8);
315 struct sigcontext __user
*sc
= &frame
->sc
;
316 unsigned long __user
*oldmask
= &sc
->oldmask
;
317 unsigned long __user
*extramask
= frame
->extramask
;
318 int sig_size
= (_NSIG_WORDS
- 1) * sizeof(unsigned long);
320 if(copy_from_user(&set
.sig
[0], oldmask
, sizeof(&set
.sig
[0])) ||
321 copy_from_user(&set
.sig
[1], extramask
, sig_size
))
324 sigdelsetmask(&set
, ~_BLOCKABLE
);
326 spin_lock_irq(¤t
->sighand
->siglock
);
327 current
->blocked
= set
;
329 spin_unlock_irq(¤t
->sighand
->siglock
);
331 if(copy_sc_from_user(¤t
->thread
.regs
, sc
))
334 /* Avoid ERESTART handling */
335 PT_REGS_SYSCALL_NR(¤t
->thread
.regs
) = -1;
336 return(PT_REGS_SYSCALL_RET(¤t
->thread
.regs
));
339 force_sig(SIGSEGV
, current
);
343 long sys_rt_sigreturn(struct pt_regs regs
)
345 unsigned long __user sp
= PT_REGS_SP(¤t
->thread
.regs
);
346 struct rt_sigframe __user
*frame
= (struct rt_sigframe
*) (sp
- 4);
348 struct ucontext __user
*uc
= &frame
->uc
;
349 int sig_size
= _NSIG_WORDS
* sizeof(unsigned long);
351 if(copy_from_user(&set
, &uc
->uc_sigmask
, sig_size
))
354 sigdelsetmask(&set
, ~_BLOCKABLE
);
356 spin_lock_irq(¤t
->sighand
->siglock
);
357 current
->blocked
= set
;
359 spin_unlock_irq(¤t
->sighand
->siglock
);
361 if(copy_sc_from_user(¤t
->thread
.regs
, &uc
->uc_mcontext
))
364 /* Avoid ERESTART handling */
365 PT_REGS_SYSCALL_NR(¤t
->thread
.regs
) = -1;
366 return(PT_REGS_SYSCALL_RET(¤t
->thread
.regs
));
369 force_sig(SIGSEGV
, current
);
374 * Overrides for Emacs so that we follow Linus's tabbing style.
375 * Emacs will notice this stuff at the end of the file and automatically
376 * adjust the settings for this buffer only. This must remain at the end
378 * ---------------------------------------------------------------------------
380 * c-file-style: "linux"