aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/signal_64.c
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-12-20 17:01:18 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-12-20 17:01:18 -0500
commitcb85f123cd2393581bcffad335bfc6bcdd58569c (patch)
tree7b0de48b2a13ca96251c02245ab906f7efa3ac18 /arch/sparc/kernel/signal_64.c
parentb79d2ff98caee60c07a7598aba3b26acd1655a99 (diff)
parentcaca6a03d365883564885f2c1da3e88dcf65d139 (diff)
Merge commit 'v3.2-rc3' into stable/for-linus-3.3
* commit 'v3.2-rc3': (412 commits) Linux 3.2-rc3 virtio-pci: make reset operation safer virtio-mmio: Correct the name of the guest features selector virtio: add HAS_IOMEM dependency to MMIO platform bus driver eCryptfs: Extend array bounds for all filename chars eCryptfs: Flush file in vma close eCryptfs: Prevent file create race condition regulator: TPS65910: Fix VDD1/2 voltage selector count i2c: Make i2cdev_notifier_call static i2c: Delete ANY_I2C_BUS i2c: Fix device name for 10-bit slave address i2c-algo-bit: Generate correct i2c address sequence for 10-bit target drm: integer overflow in drm_mode_dirtyfb_ioctl() Revert "of/irq: of_irq_find_parent: check for parent equal to child" drivers/gpu/vga/vgaarb.c: add missing kfree drm/radeon/kms/atom: unify i2c gpio table handling drm/radeon/kms: fix up gpio i2c mask bits for r4xx for real ttm: Don't return the bo reserved on error path mount_subtree() pointless use-after-free iio: fix a leak due to improper use of anon_inode_getfd() ...
Diffstat (limited to 'arch/sparc/kernel/signal_64.c')
-rw-r--r--arch/sparc/kernel/signal_64.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index a2b81598d905..f0836cd0e2f2 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
529 siginfo_t info; 529 siginfo_t info;
530 int signr; 530 int signr;
531 531
532 /* It's a lot of work and synchronization to add a new ptrace
533 * register for GDB to save and restore in order to get
534 * orig_i0 correct for syscall restarts when debugging.
535 *
536 * Although it should be the case that most of the global
537 * registers are volatile across a system call, glibc already
538 * depends upon that fact that we preserve them. So we can't
539 * just use any global register to save away the orig_i0 value.
540 *
541 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
542 * preserved across a system call trap by various pieces of
543 * code in glibc.
544 *
545 * %g7 is used as the "thread register". %g6 is not used in
546 * any fixed manner. %g6 is used as a scratch register and
547 * a compiler temporary, but it's value is never used across
548 * a system call. Therefore %g6 is usable for orig_i0 storage.
549 */
532 if (pt_regs_is_syscall(regs) && 550 if (pt_regs_is_syscall(regs) &&
533 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { 551 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
534 restart_syscall = 1; 552 regs->u_regs[UREG_G6] = orig_i0;
535 } else
536 restart_syscall = 0;
537 553
538 if (current_thread_info()->status & TS_RESTORE_SIGMASK) 554 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
539 oldset = &current->saved_sigmask; 555 oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
542 558
543#ifdef CONFIG_COMPAT 559#ifdef CONFIG_COMPAT
544 if (test_thread_flag(TIF_32BIT)) { 560 if (test_thread_flag(TIF_32BIT)) {
545 extern void do_signal32(sigset_t *, struct pt_regs *, 561 extern void do_signal32(sigset_t *, struct pt_regs *);
546 int restart_syscall, 562 do_signal32(oldset, regs);
547 unsigned long orig_i0);
548 do_signal32(oldset, regs, restart_syscall, orig_i0);
549 return; 563 return;
550 } 564 }
551#endif 565#endif
552 566
553 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 567 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
554 568
555 /* If the debugger messes with the program counter, it clears 569 restart_syscall = 0;
556 * the software "in syscall" bit, directing us to not perform 570 if (pt_regs_is_syscall(regs) &&
557 * a syscall restart. 571 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
558 */ 572 restart_syscall = 1;
559 if (restart_syscall && !pt_regs_is_syscall(regs)) 573 orig_i0 = regs->u_regs[UREG_G6];
560 restart_syscall = 0; 574 }
561 575
562 if (signr > 0) { 576 if (signr > 0) {
563 if (restart_syscall) 577 if (restart_syscall)