diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2011-08-18 15:10:39 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2011-11-02 09:15:20 -0400 |
commit | f67aa2ffb7ce2f6d88e2e7a8069309dc2627932e (patch) | |
tree | a6ad87953f1207cc813e5ca31b4d525ce3cc7f0c /arch/x86/um | |
parent | fbe9868693d9025753427d7d28b9eed4d01cf674 (diff) |
um: merge signal_{32,64}.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/x86/um')
-rw-r--r-- | arch/x86/um/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/um/asm/ptrace_64.h | 2 | ||||
-rw-r--r-- | arch/x86/um/signal.c (renamed from arch/x86/um/signal_32.c) | 223 | ||||
-rw-r--r-- | arch/x86/um/signal_64.c | 236 | ||||
-rw-r--r-- | arch/x86/um/sys_call_table_32.S | 2 | ||||
-rw-r--r-- | arch/x86/um/sysrq_64.c | 2 |
6 files changed, 189 insertions, 278 deletions
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index df419896693..ffe1008a3f4 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile | |||
@@ -9,7 +9,7 @@ else | |||
9 | endif | 9 | endif |
10 | 10 | ||
11 | obj-y = bug.o bugs_$(BITS).o delay_$(BITS).o fault.o ksyms.o ldt.o \ | 11 | obj-y = bug.o bugs_$(BITS).o delay_$(BITS).o fault.o ksyms.o ldt.o \ |
12 | ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal_$(BITS).o \ | 12 | ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \ |
13 | stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \ | 13 | stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \ |
14 | sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \ | 14 | sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \ |
15 | mem_$(BITS).o subarch.o os-$(OS)/ | 15 | mem_$(BITS).o subarch.o os-$(OS)/ |
diff --git a/arch/x86/um/asm/ptrace_64.h b/arch/x86/um/asm/ptrace_64.h index 83d8c473b90..706a0d80545 100644 --- a/arch/x86/um/asm/ptrace_64.h +++ b/arch/x86/um/asm/ptrace_64.h | |||
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | #define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs) | 41 | #define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs) |
42 | #define PT_REGS_RIP(r) UPT_IP(&(r)->regs) | 42 | #define PT_REGS_RIP(r) UPT_IP(&(r)->regs) |
43 | #define PT_REGS_RSP(r) UPT_SP(&(r)->regs) | 43 | #define PT_REGS_SP(r) UPT_SP(&(r)->regs) |
44 | 44 | ||
45 | #define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) | 45 | #define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) |
46 | 46 | ||
diff --git a/arch/x86/um/signal_32.c b/arch/x86/um/signal.c index 7a206d8f228..4883b954601 100644 --- a/arch/x86/um/signal_32.c +++ b/arch/x86/um/signal.c | |||
@@ -1,15 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 2 | * Copyright (C) 2003 PathScale, Inc. |
3 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | 4 | * Licensed under the GPL |
4 | */ | 5 | */ |
5 | 6 | ||
7 | |||
8 | #include <linux/personality.h> | ||
6 | #include <linux/ptrace.h> | 9 | #include <linux/ptrace.h> |
10 | #include <linux/kernel.h> | ||
7 | #include <asm/unistd.h> | 11 | #include <asm/unistd.h> |
8 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
9 | #include <asm/ucontext.h> | 13 | #include <asm/ucontext.h> |
10 | #include "frame_kern.h" | 14 | #include "frame_kern.h" |
11 | #include "skas.h" | 15 | #include "skas.h" |
12 | 16 | ||
17 | #ifdef CONFIG_X86_32 | ||
18 | |||
13 | /* | 19 | /* |
14 | * FPU tag word conversions. | 20 | * FPU tag word conversions. |
15 | */ | 21 | */ |
@@ -142,6 +148,8 @@ static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, | |||
142 | 148 | ||
143 | extern int have_fpx_regs; | 149 | extern int have_fpx_regs; |
144 | 150 | ||
151 | #endif | ||
152 | |||
145 | static int copy_sc_from_user(struct pt_regs *regs, | 153 | static int copy_sc_from_user(struct pt_regs *regs, |
146 | struct sigcontext __user *from) | 154 | struct sigcontext __user *from) |
147 | { | 155 | { |
@@ -152,14 +160,14 @@ static int copy_sc_from_user(struct pt_regs *regs, | |||
152 | if (err) | 160 | if (err) |
153 | return err; | 161 | return err; |
154 | 162 | ||
155 | pid = userspace_pid[current_thread_info()->cpu]; | ||
156 | |||
157 | #define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname | 163 | #define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname |
158 | 164 | ||
165 | #ifdef CONFIG_X86_32 | ||
159 | GETREG(GS, gs); | 166 | GETREG(GS, gs); |
160 | GETREG(FS, fs); | 167 | GETREG(FS, fs); |
161 | GETREG(ES, es); | 168 | GETREG(ES, es); |
162 | GETREG(DS, ds); | 169 | GETREG(DS, ds); |
170 | #endif | ||
163 | GETREG(DI, di); | 171 | GETREG(DI, di); |
164 | GETREG(SI, si); | 172 | GETREG(SI, si); |
165 | GETREG(BP, bp); | 173 | GETREG(BP, bp); |
@@ -169,11 +177,28 @@ static int copy_sc_from_user(struct pt_regs *regs, | |||
169 | GETREG(CX, cx); | 177 | GETREG(CX, cx); |
170 | GETREG(AX, ax); | 178 | GETREG(AX, ax); |
171 | GETREG(IP, ip); | 179 | GETREG(IP, ip); |
180 | |||
181 | #ifdef CONFIG_X86_64 | ||
182 | GETREG(R8, r8); | ||
183 | GETREG(R9, r9); | ||
184 | GETREG(R10, r10); | ||
185 | GETREG(R11, r11); | ||
186 | GETREG(R12, r12); | ||
187 | GETREG(R13, r13); | ||
188 | GETREG(R14, r14); | ||
189 | GETREG(R15, r15); | ||
190 | #endif | ||
191 | |||
172 | GETREG(CS, cs); | 192 | GETREG(CS, cs); |
173 | GETREG(EFLAGS, flags); | 193 | GETREG(EFLAGS, flags); |
194 | #ifdef CONFIG_X86_32 | ||
174 | GETREG(SS, ss); | 195 | GETREG(SS, ss); |
196 | #endif | ||
175 | 197 | ||
176 | #undef GETREG | 198 | #undef GETREG |
199 | |||
200 | pid = userspace_pid[current_thread_info()->cpu]; | ||
201 | #ifdef CONFIG_X86_32 | ||
177 | if (have_fpx_regs) { | 202 | if (have_fpx_regs) { |
178 | struct user_fxsr_struct fpx; | 203 | struct user_fxsr_struct fpx; |
179 | 204 | ||
@@ -194,7 +219,9 @@ static int copy_sc_from_user(struct pt_regs *regs, | |||
194 | -err); | 219 | -err); |
195 | return 1; | 220 | return 1; |
196 | } | 221 | } |
197 | } else { | 222 | } else |
223 | #endif | ||
224 | { | ||
198 | struct user_i387_struct fp; | 225 | struct user_i387_struct fp; |
199 | 226 | ||
200 | err = copy_from_user(&fp, sc.fpstate, | 227 | err = copy_from_user(&fp, sc.fpstate, |
@@ -210,43 +237,66 @@ static int copy_sc_from_user(struct pt_regs *regs, | |||
210 | return 1; | 237 | return 1; |
211 | } | 238 | } |
212 | } | 239 | } |
213 | |||
214 | return 0; | 240 | return 0; |
215 | } | 241 | } |
216 | 242 | ||
217 | static int copy_sc_to_user(struct sigcontext __user *to, | 243 | static int copy_sc_to_user(struct sigcontext __user *to, |
218 | struct _fpstate __user *to_fp, struct pt_regs *regs) | 244 | struct _fpstate __user *to_fp, struct pt_regs *regs, |
245 | unsigned long mask) | ||
219 | { | 246 | { |
220 | struct sigcontext sc; | 247 | struct sigcontext sc; |
221 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 248 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
222 | int err, pid; | 249 | int err, pid; |
223 | memset(&sc, 0, sizeof(struct sigcontext)); | 250 | memset(&sc, 0, sizeof(struct sigcontext)); |
224 | 251 | ||
225 | sc.gs = REGS_GS(regs->regs.gp); | 252 | #define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno] |
226 | sc.fs = REGS_FS(regs->regs.gp); | 253 | |
227 | sc.es = REGS_ES(regs->regs.gp); | 254 | #ifdef CONFIG_X86_32 |
228 | sc.ds = REGS_DS(regs->regs.gp); | 255 | PUTREG(GS, gs); |
229 | sc.di = REGS_EDI(regs->regs.gp); | 256 | PUTREG(FS, fs); |
230 | sc.si = REGS_ESI(regs->regs.gp); | 257 | PUTREG(ES, es); |
231 | sc.bp = REGS_EBP(regs->regs.gp); | 258 | PUTREG(DS, ds); |
232 | sc.sp = REGS_SP(regs->regs.gp); | 259 | #endif |
233 | sc.bx = REGS_EBX(regs->regs.gp); | 260 | PUTREG(DI, di); |
234 | sc.dx = REGS_EDX(regs->regs.gp); | 261 | PUTREG(SI, si); |
235 | sc.cx = REGS_ECX(regs->regs.gp); | 262 | PUTREG(BP, bp); |
236 | sc.ax = REGS_EAX(regs->regs.gp); | 263 | PUTREG(SP, sp); |
237 | sc.ip = REGS_IP(regs->regs.gp); | 264 | PUTREG(BX, bx); |
238 | sc.cs = REGS_CS(regs->regs.gp); | 265 | PUTREG(DX, dx); |
239 | sc.flags = REGS_EFLAGS(regs->regs.gp); | 266 | PUTREG(CX, cx); |
240 | sc.sp_at_signal = regs->regs.gp[UESP]; | 267 | PUTREG(AX, ax); |
241 | sc.ss = regs->regs.gp[SS]; | 268 | #ifdef CONFIG_X86_64 |
269 | PUTREG(R8, r8); | ||
270 | PUTREG(R9, r9); | ||
271 | PUTREG(R10, r10); | ||
272 | PUTREG(R11, r11); | ||
273 | PUTREG(R12, r12); | ||
274 | PUTREG(R13, r13); | ||
275 | PUTREG(R14, r14); | ||
276 | PUTREG(R15, r15); | ||
277 | #endif | ||
278 | |||
242 | sc.cr2 = fi->cr2; | 279 | sc.cr2 = fi->cr2; |
243 | sc.err = fi->error_code; | 280 | sc.err = fi->error_code; |
244 | sc.trapno = fi->trap_no; | 281 | sc.trapno = fi->trap_no; |
245 | 282 | PUTREG(IP, ip); | |
246 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); | 283 | PUTREG(CS, cs); |
284 | PUTREG(EFLAGS, flags); | ||
285 | #ifdef CONFIG_X86_32 | ||
286 | PUTREG(SP, sp_at_signal); | ||
287 | PUTREG(SS, ss); | ||
288 | #endif | ||
289 | #undef PUTREG | ||
290 | sc.oldmask = mask; | ||
247 | sc.fpstate = to_fp; | 291 | sc.fpstate = to_fp; |
248 | 292 | ||
293 | err = copy_to_user(to, &sc, sizeof(struct sigcontext)); | ||
294 | if (err) | ||
295 | return 1; | ||
296 | |||
249 | pid = userspace_pid[current_thread_info()->cpu]; | 297 | pid = userspace_pid[current_thread_info()->cpu]; |
298 | |||
299 | #ifdef CONFIG_X86_32 | ||
250 | if (have_fpx_regs) { | 300 | if (have_fpx_regs) { |
251 | struct user_fxsr_struct fpx; | 301 | struct user_fxsr_struct fpx; |
252 | 302 | ||
@@ -269,8 +319,9 @@ static int copy_sc_to_user(struct sigcontext __user *to, | |||
269 | if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, | 319 | if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, |
270 | sizeof(struct user_fxsr_struct))) | 320 | sizeof(struct user_fxsr_struct))) |
271 | return 1; | 321 | return 1; |
272 | } | 322 | } else |
273 | else { | 323 | #endif |
324 | { | ||
274 | struct user_i387_struct fp; | 325 | struct user_i387_struct fp; |
275 | 326 | ||
276 | err = save_fp_registers(pid, (unsigned long *) &fp); | 327 | err = save_fp_registers(pid, (unsigned long *) &fp); |
@@ -278,9 +329,10 @@ static int copy_sc_to_user(struct sigcontext __user *to, | |||
278 | return 1; | 329 | return 1; |
279 | } | 330 | } |
280 | 331 | ||
281 | return copy_to_user(to, &sc, sizeof(sc)); | 332 | return 0; |
282 | } | 333 | } |
283 | 334 | ||
335 | #ifdef CONFIG_X86_32 | ||
284 | static int copy_ucontext_to_user(struct ucontext __user *uc, | 336 | static int copy_ucontext_to_user(struct ucontext __user *uc, |
285 | struct _fpstate __user *fp, sigset_t *set, | 337 | struct _fpstate __user *fp, sigset_t *set, |
286 | unsigned long sp) | 338 | unsigned long sp) |
@@ -290,7 +342,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc, | |||
290 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); | 342 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); |
291 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); | 343 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); |
292 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); | 344 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); |
293 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs); | 345 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, 0); |
294 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); | 346 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); |
295 | return err; | 347 | return err; |
296 | } | 348 | } |
@@ -337,8 +389,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
337 | 389 | ||
338 | err |= __put_user(restorer, &frame->pretcode); | 390 | err |= __put_user(restorer, &frame->pretcode); |
339 | err |= __put_user(sig, &frame->sig); | 391 | err |= __put_user(sig, &frame->sig); |
340 | err |= copy_sc_to_user(&frame->sc, NULL, regs); | 392 | err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]); |
341 | err |= __put_user(mask->sig[0], &frame->sc.oldmask); | ||
342 | if (_NSIG_WORDS > 1) | 393 | if (_NSIG_WORDS > 1) |
343 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], | 394 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], |
344 | sizeof(frame->extramask)); | 395 | sizeof(frame->extramask)); |
@@ -418,7 +469,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
418 | return 0; | 469 | return 0; |
419 | } | 470 | } |
420 | 471 | ||
421 | long sys_sigreturn(struct pt_regs regs) | 472 | long sys_sigreturn(struct pt_regs *regs) |
422 | { | 473 | { |
423 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | 474 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); |
424 | struct sigframe __user *frame = (struct sigframe __user *)(sp - 8); | 475 | struct sigframe __user *frame = (struct sigframe __user *)(sp - 8); |
@@ -447,16 +498,103 @@ long sys_sigreturn(struct pt_regs regs) | |||
447 | return 0; | 498 | return 0; |
448 | } | 499 | } |
449 | 500 | ||
450 | long sys_rt_sigreturn(struct pt_regs regs) | 501 | #else |
502 | |||
503 | struct rt_sigframe | ||
504 | { | ||
505 | char __user *pretcode; | ||
506 | struct ucontext uc; | ||
507 | struct siginfo info; | ||
508 | struct _fpstate fpstate; | ||
509 | }; | ||
510 | |||
511 | int setup_signal_stack_si(unsigned long stack_top, int sig, | ||
512 | struct k_sigaction *ka, struct pt_regs * regs, | ||
513 | siginfo_t *info, sigset_t *set) | ||
514 | { | ||
515 | struct rt_sigframe __user *frame; | ||
516 | int err = 0; | ||
517 | struct task_struct *me = current; | ||
518 | |||
519 | frame = (struct rt_sigframe __user *) | ||
520 | round_down(stack_top - sizeof(struct rt_sigframe), 16); | ||
521 | /* Subtract 128 for a red zone and 8 for proper alignment */ | ||
522 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); | ||
523 | |||
524 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
525 | goto out; | ||
526 | |||
527 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
528 | err |= copy_siginfo_to_user(&frame->info, info); | ||
529 | if (err) | ||
530 | goto out; | ||
531 | } | ||
532 | |||
533 | /* Create the ucontext. */ | ||
534 | err |= __put_user(0, &frame->uc.uc_flags); | ||
535 | err |= __put_user(0, &frame->uc.uc_link); | ||
536 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
537 | err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), | ||
538 | &frame->uc.uc_stack.ss_flags); | ||
539 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
540 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, | ||
541 | set->sig[0]); | ||
542 | err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); | ||
543 | if (sizeof(*set) == 16) { | ||
544 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | ||
545 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | ||
546 | } | ||
547 | else | ||
548 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, | ||
549 | sizeof(*set)); | ||
550 | |||
551 | /* | ||
552 | * Set up to return from userspace. If provided, use a stub | ||
553 | * already in userspace. | ||
554 | */ | ||
555 | /* x86-64 should always use SA_RESTORER. */ | ||
556 | if (ka->sa.sa_flags & SA_RESTORER) | ||
557 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | ||
558 | else | ||
559 | /* could use a vstub here */ | ||
560 | return err; | ||
561 | |||
562 | if (err) | ||
563 | return err; | ||
564 | |||
565 | /* Set up registers for signal handler */ | ||
566 | { | ||
567 | struct exec_domain *ed = current_thread_info()->exec_domain; | ||
568 | if (unlikely(ed && ed->signal_invmap && sig < 32)) | ||
569 | sig = ed->signal_invmap[sig]; | ||
570 | } | ||
571 | |||
572 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
573 | PT_REGS_RDI(regs) = sig; | ||
574 | /* In case the signal handler was declared without prototypes */ | ||
575 | PT_REGS_RAX(regs) = 0; | ||
576 | |||
577 | /* | ||
578 | * This also works for non SA_SIGINFO handlers because they expect the | ||
579 | * next argument after the signal number on the stack. | ||
580 | */ | ||
581 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | ||
582 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | ||
583 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | ||
584 | out: | ||
585 | return err; | ||
586 | } | ||
587 | #endif | ||
588 | |||
589 | long sys_rt_sigreturn(struct pt_regs *regs) | ||
451 | { | 590 | { |
452 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | 591 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); |
453 | struct rt_sigframe __user *frame = | 592 | struct rt_sigframe __user *frame = |
454 | (struct rt_sigframe __user *) (sp - 4); | 593 | (struct rt_sigframe __user *)(sp - sizeof(long)); |
455 | sigset_t set; | ||
456 | struct ucontext __user *uc = &frame->uc; | 594 | struct ucontext __user *uc = &frame->uc; |
457 | int sig_size = _NSIG_WORDS * sizeof(unsigned long); | 595 | sigset_t set; |
458 | 596 | ||
459 | if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) | 597 | if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) |
460 | goto segfault; | 598 | goto segfault; |
461 | 599 | ||
462 | sigdelsetmask(&set, ~_BLOCKABLE); | 600 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -473,3 +611,14 @@ long sys_rt_sigreturn(struct pt_regs regs) | |||
473 | force_sig(SIGSEGV, current); | 611 | force_sig(SIGSEGV, current); |
474 | return 0; | 612 | return 0; |
475 | } | 613 | } |
614 | |||
615 | #ifdef CONFIG_X86_32 | ||
616 | long ptregs_sigreturn(void) | ||
617 | { | ||
618 | return sys_sigreturn(NULL); | ||
619 | } | ||
620 | long ptregs_rt_sigreturn(void) | ||
621 | { | ||
622 | return sys_rt_sigreturn(NULL); | ||
623 | } | ||
624 | #endif | ||
diff --git a/arch/x86/um/signal_64.c b/arch/x86/um/signal_64.c deleted file mode 100644 index 74c2598b0b3..00000000000 --- a/arch/x86/um/signal_64.c +++ /dev/null | |||
@@ -1,236 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003 PathScale, Inc. | ||
3 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <linux/personality.h> | ||
8 | #include <linux/ptrace.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <asm/unistd.h> | ||
11 | #include <asm/uaccess.h> | ||
12 | #include <asm/ucontext.h> | ||
13 | #include "frame_kern.h" | ||
14 | #include "skas.h" | ||
15 | |||
16 | static int copy_sc_from_user(struct pt_regs *regs, | ||
17 | struct sigcontext __user *from) | ||
18 | { | ||
19 | struct sigcontext sc; | ||
20 | struct user_i387_struct fp; | ||
21 | void __user *buf; | ||
22 | int err; | ||
23 | |||
24 | err = copy_from_user(&sc, from, sizeof(sc)); | ||
25 | if (err) | ||
26 | return err; | ||
27 | |||
28 | #define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname | ||
29 | |||
30 | GETREG(R8, r8); | ||
31 | GETREG(R9, r9); | ||
32 | GETREG(R10, r10); | ||
33 | GETREG(R11, r11); | ||
34 | GETREG(R12, r12); | ||
35 | GETREG(R13, r13); | ||
36 | GETREG(R14, r14); | ||
37 | GETREG(R15, r15); | ||
38 | GETREG(DI, di); | ||
39 | GETREG(SI, si); | ||
40 | GETREG(BP, bp); | ||
41 | GETREG(BX, bx); | ||
42 | GETREG(DX, dx); | ||
43 | GETREG(AX, ax); | ||
44 | GETREG(CX, cx); | ||
45 | GETREG(SP, sp); | ||
46 | GETREG(IP, ip); | ||
47 | GETREG(EFLAGS, flags); | ||
48 | GETREG(CS, cs); | ||
49 | #undef GETREG | ||
50 | |||
51 | buf = sc.fpstate; | ||
52 | |||
53 | err = copy_from_user(&fp, buf, sizeof(struct user_i387_struct)); | ||
54 | if (err) | ||
55 | return 1; | ||
56 | |||
57 | err = restore_fp_registers(userspace_pid[current_thread_info()->cpu], | ||
58 | (unsigned long *) &fp); | ||
59 | if (err < 0) { | ||
60 | printk(KERN_ERR "copy_sc_from_user - " | ||
61 | "restore_fp_registers failed, errno = %d\n", | ||
62 | -err); | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int copy_sc_to_user(struct sigcontext __user *to, | ||
70 | struct _fpstate __user *to_fp, struct pt_regs *regs, | ||
71 | unsigned long mask) | ||
72 | { | ||
73 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | ||
74 | struct sigcontext sc; | ||
75 | struct user_i387_struct fp; | ||
76 | int err = 0; | ||
77 | memset(&sc, 0, sizeof(struct sigcontext)); | ||
78 | |||
79 | #define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno] | ||
80 | |||
81 | PUTREG(DI, di); | ||
82 | PUTREG(SI, si); | ||
83 | PUTREG(BP, bp); | ||
84 | PUTREG(SP, sp); | ||
85 | PUTREG(BX, bx); | ||
86 | PUTREG(DX, dx); | ||
87 | PUTREG(CX, cx); | ||
88 | PUTREG(AX, ax); | ||
89 | PUTREG(R8, r8); | ||
90 | PUTREG(R9, r9); | ||
91 | PUTREG(R10, r10); | ||
92 | PUTREG(R11, r11); | ||
93 | PUTREG(R12, r12); | ||
94 | PUTREG(R13, r13); | ||
95 | PUTREG(R14, r14); | ||
96 | PUTREG(R15, r15); | ||
97 | PUTREG(CS, cs); /* XXX x86_64 doesn't do this */ | ||
98 | |||
99 | sc.cr2 = fi->cr2; | ||
100 | sc.err = fi->error_code; | ||
101 | sc.trapno = fi->trap_no; | ||
102 | |||
103 | PUTREG(IP, ip); | ||
104 | PUTREG(EFLAGS, flags); | ||
105 | #undef PUTREG | ||
106 | |||
107 | sc.oldmask = mask; | ||
108 | |||
109 | err = copy_to_user(to, &sc, sizeof(struct sigcontext)); | ||
110 | if (err) | ||
111 | return 1; | ||
112 | |||
113 | err = save_fp_registers(userspace_pid[current_thread_info()->cpu], | ||
114 | (unsigned long *) &fp); | ||
115 | if (err < 0) { | ||
116 | printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " | ||
117 | "failed, errno = %d\n", -err); | ||
118 | return 1; | ||
119 | } | ||
120 | |||
121 | if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) | ||
122 | return 1; | ||
123 | |||
124 | return err; | ||
125 | } | ||
126 | |||
127 | struct rt_sigframe | ||
128 | { | ||
129 | char __user *pretcode; | ||
130 | struct ucontext uc; | ||
131 | struct siginfo info; | ||
132 | struct _fpstate fpstate; | ||
133 | }; | ||
134 | |||
135 | int setup_signal_stack_si(unsigned long stack_top, int sig, | ||
136 | struct k_sigaction *ka, struct pt_regs * regs, | ||
137 | siginfo_t *info, sigset_t *set) | ||
138 | { | ||
139 | struct rt_sigframe __user *frame; | ||
140 | int err = 0; | ||
141 | struct task_struct *me = current; | ||
142 | |||
143 | frame = (struct rt_sigframe __user *) | ||
144 | round_down(stack_top - sizeof(struct rt_sigframe), 16); | ||
145 | /* Subtract 128 for a red zone and 8 for proper alignment */ | ||
146 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); | ||
147 | |||
148 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
149 | goto out; | ||
150 | |||
151 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
152 | err |= copy_siginfo_to_user(&frame->info, info); | ||
153 | if (err) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | /* Create the ucontext. */ | ||
158 | err |= __put_user(0, &frame->uc.uc_flags); | ||
159 | err |= __put_user(0, &frame->uc.uc_link); | ||
160 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
161 | err |= __put_user(sas_ss_flags(PT_REGS_RSP(regs)), | ||
162 | &frame->uc.uc_stack.ss_flags); | ||
163 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
164 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, | ||
165 | set->sig[0]); | ||
166 | err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); | ||
167 | if (sizeof(*set) == 16) { | ||
168 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | ||
169 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | ||
170 | } | ||
171 | else | ||
172 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, | ||
173 | sizeof(*set)); | ||
174 | |||
175 | /* | ||
176 | * Set up to return from userspace. If provided, use a stub | ||
177 | * already in userspace. | ||
178 | */ | ||
179 | /* x86-64 should always use SA_RESTORER. */ | ||
180 | if (ka->sa.sa_flags & SA_RESTORER) | ||
181 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | ||
182 | else | ||
183 | /* could use a vstub here */ | ||
184 | return err; | ||
185 | |||
186 | if (err) | ||
187 | return err; | ||
188 | |||
189 | /* Set up registers for signal handler */ | ||
190 | { | ||
191 | struct exec_domain *ed = current_thread_info()->exec_domain; | ||
192 | if (unlikely(ed && ed->signal_invmap && sig < 32)) | ||
193 | sig = ed->signal_invmap[sig]; | ||
194 | } | ||
195 | |||
196 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
197 | PT_REGS_RDI(regs) = sig; | ||
198 | /* In case the signal handler was declared without prototypes */ | ||
199 | PT_REGS_RAX(regs) = 0; | ||
200 | |||
201 | /* | ||
202 | * This also works for non SA_SIGINFO handlers because they expect the | ||
203 | * next argument after the signal number on the stack. | ||
204 | */ | ||
205 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | ||
206 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | ||
207 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | ||
208 | out: | ||
209 | return err; | ||
210 | } | ||
211 | |||
212 | long sys_rt_sigreturn(struct pt_regs *regs) | ||
213 | { | ||
214 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | ||
215 | struct rt_sigframe __user *frame = | ||
216 | (struct rt_sigframe __user *)(sp - 8); | ||
217 | struct ucontext __user *uc = &frame->uc; | ||
218 | sigset_t set; | ||
219 | |||
220 | if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) | ||
221 | goto segfault; | ||
222 | |||
223 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
224 | set_current_blocked(&set); | ||
225 | |||
226 | if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) | ||
227 | goto segfault; | ||
228 | |||
229 | /* Avoid ERESTART handling */ | ||
230 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; | ||
231 | return PT_REGS_SYSCALL_RET(¤t->thread.regs); | ||
232 | |||
233 | segfault: | ||
234 | force_sig(SIGSEGV, current); | ||
235 | return 0; | ||
236 | } | ||
diff --git a/arch/x86/um/sys_call_table_32.S b/arch/x86/um/sys_call_table_32.S index c3431cf5a14..a7ca80d2dce 100644 --- a/arch/x86/um/sys_call_table_32.S +++ b/arch/x86/um/sys_call_table_32.S | |||
@@ -13,10 +13,8 @@ | |||
13 | #define ptregs_execve sys_execve | 13 | #define ptregs_execve sys_execve |
14 | #define ptregs_iopl sys_iopl | 14 | #define ptregs_iopl sys_iopl |
15 | #define ptregs_vm86old sys_vm86old | 15 | #define ptregs_vm86old sys_vm86old |
16 | #define ptregs_sigreturn sys_sigreturn | ||
17 | #define ptregs_clone sys_clone | 16 | #define ptregs_clone sys_clone |
18 | #define ptregs_vm86 sys_vm86 | 17 | #define ptregs_vm86 sys_vm86 |
19 | #define ptregs_rt_sigreturn sys_rt_sigreturn | ||
20 | #define ptregs_sigaltstack sys_sigaltstack | 18 | #define ptregs_sigaltstack sys_sigaltstack |
21 | #define ptregs_vfork sys_vfork | 19 | #define ptregs_vfork sys_vfork |
22 | 20 | ||
diff --git a/arch/x86/um/sysrq_64.c b/arch/x86/um/sysrq_64.c index f4f82beb350..e8913436d7d 100644 --- a/arch/x86/um/sysrq_64.c +++ b/arch/x86/um/sysrq_64.c | |||
@@ -20,7 +20,7 @@ void __show_regs(struct pt_regs *regs) | |||
20 | current->comm, print_tainted(), init_utsname()->release); | 20 | current->comm, print_tainted(), init_utsname()->release); |
21 | printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, | 21 | printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, |
22 | PT_REGS_RIP(regs)); | 22 | PT_REGS_RIP(regs)); |
23 | printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), | 23 | printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs), |
24 | PT_REGS_EFLAGS(regs)); | 24 | PT_REGS_EFLAGS(regs)); |
25 | printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", | 25 | printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", |
26 | PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); | 26 | PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); |