aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-12 07:17:07 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-12 07:17:07 -0400
commit84e9c95ad92f7afcd960342b6012b0a1b039e21b (patch)
tree455743da1af7c99168ffacf271be5eabfc4cd9d1 /arch/x86
parent206855c321adee56db3946ca09a5887cddb9d598 (diff)
parent1389ac4b976abdc0555280dfc1aa2c3abcc19641 (diff)
Merge branch 'x86/signal' into core/signal
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/ia32/ia32_signal.c31
-rw-r--r--arch/x86/kernel/signal_32.c108
-rw-r--r--arch/x86/kernel/signal_64.c84
3 files changed, 133 insertions, 90 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index e47bed2440ee..4bc02b23674b 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -351,31 +351,28 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
351 savesegment(es, tmp); 351 savesegment(es, tmp);
352 err |= __put_user(tmp, (unsigned int __user *)&sc->es); 352 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
353 353
354 err |= __put_user((u32)regs->di, &sc->di); 354 err |= __put_user(regs->di, &sc->di);
355 err |= __put_user((u32)regs->si, &sc->si); 355 err |= __put_user(regs->si, &sc->si);
356 err |= __put_user((u32)regs->bp, &sc->bp); 356 err |= __put_user(regs->bp, &sc->bp);
357 err |= __put_user((u32)regs->sp, &sc->sp); 357 err |= __put_user(regs->sp, &sc->sp);
358 err |= __put_user((u32)regs->bx, &sc->bx); 358 err |= __put_user(regs->bx, &sc->bx);
359 err |= __put_user((u32)regs->dx, &sc->dx); 359 err |= __put_user(regs->dx, &sc->dx);
360 err |= __put_user((u32)regs->cx, &sc->cx); 360 err |= __put_user(regs->cx, &sc->cx);
361 err |= __put_user((u32)regs->ax, &sc->ax); 361 err |= __put_user(regs->ax, &sc->ax);
362 err |= __put_user((u32)regs->cs, &sc->cs); 362 err |= __put_user(regs->cs, &sc->cs);
363 err |= __put_user((u32)regs->ss, &sc->ss); 363 err |= __put_user(regs->ss, &sc->ss);
364 err |= __put_user(current->thread.trap_no, &sc->trapno); 364 err |= __put_user(current->thread.trap_no, &sc->trapno);
365 err |= __put_user(current->thread.error_code, &sc->err); 365 err |= __put_user(current->thread.error_code, &sc->err);
366 err |= __put_user((u32)regs->ip, &sc->ip); 366 err |= __put_user(regs->ip, &sc->ip);
367 err |= __put_user((u32)regs->flags, &sc->flags); 367 err |= __put_user(regs->flags, &sc->flags);
368 err |= __put_user((u32)regs->sp, &sc->sp_at_signal); 368 err |= __put_user(regs->sp, &sc->sp_at_signal);
369 369
370 tmp = save_i387_xstate_ia32(fpstate); 370 tmp = save_i387_xstate_ia32(fpstate);
371 if (tmp < 0) 371 if (tmp < 0)
372 err = -EFAULT; 372 err = -EFAULT;
373 else { 373 else
374 clear_used_math();
375 stts();
376 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), 374 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
377 &sc->fpstate); 375 &sc->fpstate);
378 }
379 376
380 /* non-iBCS2 extensions.. */ 377 /* non-iBCS2 extensions.. */
381 err |= __put_user(mask, &sc->oldmask); 378 err |= __put_user(mask, &sc->oldmask);
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index da3cf3270f83..d6dd057d0f22 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -113,6 +113,27 @@ asmlinkage int sys_sigaltstack(unsigned long bx)
113 return do_sigaltstack(uss, uoss, regs->sp); 113 return do_sigaltstack(uss, uoss, regs->sp);
114} 114}
115 115
116#define COPY(x) { \
117 err |= __get_user(regs->x, &sc->x); \
118}
119
120#define COPY_SEG(seg) { \
121 unsigned short tmp; \
122 err |= __get_user(tmp, &sc->seg); \
123 regs->seg = tmp; \
124}
125
126#define COPY_SEG_STRICT(seg) { \
127 unsigned short tmp; \
128 err |= __get_user(tmp, &sc->seg); \
129 regs->seg = tmp | 3; \
130}
131
132#define GET_SEG(seg) { \
133 unsigned short tmp; \
134 err |= __get_user(tmp, &sc->seg); \
135 loadsegment(seg, tmp); \
136}
116 137
117/* 138/*
118 * Do a signal return; undo the signal stack. 139 * Do a signal return; undo the signal stack.
@@ -121,28 +142,13 @@ static int
121restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, 142restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
122 unsigned long *pax) 143 unsigned long *pax)
123{ 144{
145 void __user *buf;
146 unsigned int tmpflags;
124 unsigned int err = 0; 147 unsigned int err = 0;
125 148
126 /* Always make any pending restarted system calls return -EINTR */ 149 /* Always make any pending restarted system calls return -EINTR */
127 current_thread_info()->restart_block.fn = do_no_restart_syscall; 150 current_thread_info()->restart_block.fn = do_no_restart_syscall;
128 151
129#define COPY(x) err |= __get_user(regs->x, &sc->x)
130
131#define COPY_SEG(seg) \
132 { unsigned short tmp; \
133 err |= __get_user(tmp, &sc->seg); \
134 regs->seg = tmp; }
135
136#define COPY_SEG_STRICT(seg) \
137 { unsigned short tmp; \
138 err |= __get_user(tmp, &sc->seg); \
139 regs->seg = tmp|3; }
140
141#define GET_SEG(seg) \
142 { unsigned short tmp; \
143 err |= __get_user(tmp, &sc->seg); \
144 loadsegment(seg, tmp); }
145
146 GET_SEG(gs); 152 GET_SEG(gs);
147 COPY_SEG(fs); 153 COPY_SEG(fs);
148 COPY_SEG(es); 154 COPY_SEG(es);
@@ -152,21 +158,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
152 COPY_SEG_STRICT(cs); 158 COPY_SEG_STRICT(cs);
153 COPY_SEG_STRICT(ss); 159 COPY_SEG_STRICT(ss);
154 160
155 { 161 err |= __get_user(tmpflags, &sc->flags);
156 unsigned int tmpflags; 162 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
157 163 regs->orig_ax = -1; /* disable syscall checks */
158 err |= __get_user(tmpflags, &sc->flags);
159 regs->flags = (regs->flags & ~FIX_EFLAGS) |
160 (tmpflags & FIX_EFLAGS);
161 regs->orig_ax = -1; /* disable syscall checks */
162 }
163
164 {
165 void __user *buf;
166 164
167 err |= __get_user(buf, &sc->fpstate); 165 err |= __get_user(buf, &sc->fpstate);
168 err |= restore_i387_xstate(buf); 166 err |= restore_i387_xstate(buf);
169 }
170 167
171 err |= __get_user(*pax, &sc->ax); 168 err |= __get_user(*pax, &sc->ax);
172 return err; 169 return err;
@@ -482,24 +479,34 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
482/* 479/*
483 * OK, we're invoking a handler: 480 * OK, we're invoking a handler:
484 */ 481 */
482static int signr_convert(int sig)
483{
484 struct thread_info *info = current_thread_info();
485
486 if (info->exec_domain && info->exec_domain->signal_invmap && sig < 32)
487 return info->exec_domain->signal_invmap[sig];
488 return sig;
489}
490
491#define is_ia32 1
492#define ia32_setup_frame __setup_frame
493#define ia32_setup_rt_frame __setup_rt_frame
494
485static int 495static int
486setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 496setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
487 sigset_t *set, struct pt_regs *regs) 497 sigset_t *set, struct pt_regs *regs)
488{ 498{
499 int usig = signr_convert(sig);
489 int ret; 500 int ret;
490 int usig;
491
492 usig = current_thread_info()->exec_domain
493 && current_thread_info()->exec_domain->signal_invmap
494 && sig < 32
495 ? current_thread_info()->exec_domain->signal_invmap[sig]
496 : sig;
497 501
498 /* Set up the stack frame */ 502 /* Set up the stack frame */
499 if (ka->sa.sa_flags & SA_SIGINFO) 503 if (is_ia32) {
500 ret = __setup_rt_frame(usig, ka, info, set, regs); 504 if (ka->sa.sa_flags & SA_SIGINFO)
501 else 505 ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
502 ret = __setup_frame(usig, ka, set, regs); 506 else
507 ret = ia32_setup_frame(usig, ka, set, regs);
508 } else
509 ret = __setup_rt_frame(sig, ka, info, set, regs);
503 510
504 if (ret) { 511 if (ret) {
505 force_sigsegv(sig, current); 512 force_sigsegv(sig, current);
@@ -550,6 +557,15 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
550 if (ret) 557 if (ret)
551 return ret; 558 return ret;
552 559
560#ifdef CONFIG_X86_64
561 /*
562 * This has nothing to do with segment registers,
563 * despite the name. This magic affects uaccess.h
564 * macros' behavior. Reset it to the normal setting.
565 */
566 set_fs(USER_DS);
567#endif
568
553 /* 569 /*
554 * Clear the direction flag as per the ABI for function entry. 570 * Clear the direction flag as per the ABI for function entry.
555 */ 571 */
@@ -663,6 +679,12 @@ static void do_signal(struct pt_regs *regs)
663void 679void
664do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) 680do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
665{ 681{
682#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
683 /* notify userspace of pending MCEs */
684 if (thread_info_flags & _TIF_MCE_NOTIFY)
685 mce_notify_user();
686#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
687
666 /* deal with pending signal delivery */ 688 /* deal with pending signal delivery */
667 if (thread_info_flags & _TIF_SIGPENDING) 689 if (thread_info_flags & _TIF_SIGPENDING)
668 do_signal(regs); 690 do_signal(regs);
@@ -672,7 +694,9 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
672 tracehook_notify_resume(regs); 694 tracehook_notify_resume(regs);
673 } 695 }
674 696
697#ifdef CONFIG_X86_32
675 clear_thread_flag(TIF_IRET); 698 clear_thread_flag(TIF_IRET);
699#endif /* CONFIG_X86_32 */
676} 700}
677 701
678void signal_fault(struct pt_regs *regs, void __user *frame, char *where) 702void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index bf77d4789a2d..a5c9627f4db9 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
52 return do_sigaltstack(uss, uoss, regs->sp); 52 return do_sigaltstack(uss, uoss, regs->sp);
53} 53}
54 54
55#define COPY(x) { \
56 err |= __get_user(regs->x, &sc->x); \
57}
58
59#define COPY_SEG_STRICT(seg) { \
60 unsigned short tmp; \
61 err |= __get_user(tmp, &sc->seg); \
62 regs->seg = tmp | 3; \
63}
64
55/* 65/*
56 * Do a signal return; undo the signal stack. 66 * Do a signal return; undo the signal stack.
57 */ 67 */
@@ -59,13 +69,13 @@ static int
59restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, 69restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
60 unsigned long *pax) 70 unsigned long *pax)
61{ 71{
72 void __user *buf;
73 unsigned int tmpflags;
62 unsigned int err = 0; 74 unsigned int err = 0;
63 75
64 /* Always make any pending restarted system calls return -EINTR */ 76 /* Always make any pending restarted system calls return -EINTR */
65 current_thread_info()->restart_block.fn = do_no_restart_syscall; 77 current_thread_info()->restart_block.fn = do_no_restart_syscall;
66 78
67#define COPY(x) (err |= __get_user(regs->x, &sc->x))
68
69 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 79 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
70 COPY(dx); COPY(cx); COPY(ip); 80 COPY(dx); COPY(cx); COPY(ip);
71 COPY(r8); 81 COPY(r8);
@@ -80,25 +90,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
80 /* Kernel saves and restores only the CS segment register on signals, 90 /* Kernel saves and restores only the CS segment register on signals,
81 * which is the bare minimum needed to allow mixed 32/64-bit code. 91 * which is the bare minimum needed to allow mixed 32/64-bit code.
82 * App's signal handler can save/restore other segments if needed. */ 92 * App's signal handler can save/restore other segments if needed. */
83 { 93 COPY_SEG_STRICT(cs);
84 unsigned cs;
85 err |= __get_user(cs, &sc->cs);
86 regs->cs = cs | 3; /* Force into user mode */
87 }
88 94
89 { 95 err |= __get_user(tmpflags, &sc->flags);
90 unsigned int tmpflags; 96 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
91 err |= __get_user(tmpflags, &sc->flags); 97 regs->orig_ax = -1; /* disable syscall checks */
92 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
93 regs->orig_ax = -1; /* disable syscall checks */
94 }
95
96 {
97 void __user *buf;
98 98
99 err |= __get_user(buf, &sc->fpstate); 99 err |= __get_user(buf, &sc->fpstate);
100 err |= restore_i387_xstate(buf); 100 err |= restore_i387_xstate(buf);
101 }
102 101
103 err |= __get_user(*pax, &sc->ax); 102 err |= __get_user(*pax, &sc->ax);
104 return err; 103 return err;
@@ -281,21 +280,32 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
281/* 280/*
282 * OK, we're invoking a handler 281 * OK, we're invoking a handler
283 */ 282 */
283static int signr_convert(int sig)
284{
285 return sig;
286}
287
288#ifdef CONFIG_IA32_EMULATION
289#define is_ia32 test_thread_flag(TIF_IA32)
290#else
291#define is_ia32 0
292#endif
293
284static int 294static int
285setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 295setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
286 sigset_t *set, struct pt_regs *regs) 296 sigset_t *set, struct pt_regs *regs)
287{ 297{
298 int usig = signr_convert(sig);
288 int ret; 299 int ret;
289 300
290#ifdef CONFIG_IA32_EMULATION 301 /* Set up the stack frame */
291 if (test_thread_flag(TIF_IA32)) { 302 if (is_ia32) {
292 if (ka->sa.sa_flags & SA_SIGINFO) 303 if (ka->sa.sa_flags & SA_SIGINFO)
293 ret = ia32_setup_rt_frame(sig, ka, info, set, regs); 304 ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
294 else 305 else
295 ret = ia32_setup_frame(sig, ka, set, regs); 306 ret = ia32_setup_frame(usig, ka, set, regs);
296 } else 307 } else
297#endif 308 ret = __setup_rt_frame(sig, ka, info, set, regs);
298 ret = __setup_rt_frame(sig, ka, info, set, regs);
299 309
300 if (ret) { 310 if (ret) {
301 force_sigsegv(sig, current); 311 force_sigsegv(sig, current);
@@ -346,12 +356,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
346 if (ret) 356 if (ret)
347 return ret; 357 return ret;
348 358
359#ifdef CONFIG_X86_64
349 /* 360 /*
350 * This has nothing to do with segment registers, 361 * This has nothing to do with segment registers,
351 * despite the name. This magic affects uaccess.h 362 * despite the name. This magic affects uaccess.h
352 * macros' behavior. Reset it to the normal setting. 363 * macros' behavior. Reset it to the normal setting.
353 */ 364 */
354 set_fs(USER_DS); 365 set_fs(USER_DS);
366#endif
355 367
356 /* 368 /*
357 * Clear the direction flag as per the ABI for function entry. 369 * Clear the direction flag as per the ABI for function entry.
@@ -410,7 +422,8 @@ static void do_signal(struct pt_regs *regs)
410 422
411 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 423 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
412 if (signr > 0) { 424 if (signr > 0) {
413 /* Re-enable any watchpoints before delivering the 425 /*
426 * Re-enable any watchpoints before delivering the
414 * signal to user space. The processor register will 427 * signal to user space. The processor register will
415 * have been cleared if the watchpoint triggered 428 * have been cleared if the watchpoint triggered
416 * inside the kernel. 429 * inside the kernel.
@@ -418,7 +431,7 @@ static void do_signal(struct pt_regs *regs)
418 if (current->thread.debugreg7) 431 if (current->thread.debugreg7)
419 set_debugreg(current->thread.debugreg7, 7); 432 set_debugreg(current->thread.debugreg7, 7);
420 433
421 /* Whee! Actually deliver the signal. */ 434 /* Whee! Actually deliver the signal. */
422 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { 435 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
423 /* 436 /*
424 * A signal was successfully delivered; the saved 437 * A signal was successfully delivered; the saved
@@ -441,6 +454,7 @@ static void do_signal(struct pt_regs *regs)
441 regs->ax = regs->orig_ax; 454 regs->ax = regs->orig_ax;
442 regs->ip -= 2; 455 regs->ip -= 2;
443 break; 456 break;
457
444 case -ERESTART_RESTARTBLOCK: 458 case -ERESTART_RESTARTBLOCK:
445 regs->ax = NR_restart_syscall; 459 regs->ax = NR_restart_syscall;
446 regs->ip -= 2; 460 regs->ip -= 2;
@@ -458,14 +472,18 @@ static void do_signal(struct pt_regs *regs)
458 } 472 }
459} 473}
460 474
461void do_notify_resume(struct pt_regs *regs, void *unused, 475/*
462 __u32 thread_info_flags) 476 * notification of userspace execution resumption
477 * - triggered by the TIF_WORK_MASK flags
478 */
479void
480do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
463{ 481{
464#ifdef CONFIG_X86_MCE 482#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
465 /* notify userspace of pending MCEs */ 483 /* notify userspace of pending MCEs */
466 if (thread_info_flags & _TIF_MCE_NOTIFY) 484 if (thread_info_flags & _TIF_MCE_NOTIFY)
467 mce_notify_user(); 485 mce_notify_user();
468#endif /* CONFIG_X86_MCE */ 486#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
469 487
470 /* deal with pending signal delivery */ 488 /* deal with pending signal delivery */
471 if (thread_info_flags & _TIF_SIGPENDING) 489 if (thread_info_flags & _TIF_SIGPENDING)
@@ -475,6 +493,10 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
475 clear_thread_flag(TIF_NOTIFY_RESUME); 493 clear_thread_flag(TIF_NOTIFY_RESUME);
476 tracehook_notify_resume(regs); 494 tracehook_notify_resume(regs);
477 } 495 }
496
497#ifdef CONFIG_X86_32
498 clear_thread_flag(TIF_IRET);
499#endif /* CONFIG_X86_32 */
478} 500}
479 501
480void signal_fault(struct pt_regs *regs, void __user *frame, char *where) 502void signal_fault(struct pt_regs *regs, void __user *frame, char *where)