aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-09-15 11:16:08 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-09-15 11:16:08 -0400
commit74fca9da097b74117ae2cef9e5f0d9b0e28ccbb7 (patch)
treecbdb9e9b760429016a31e1dca3b115548dbebc0a /arch/tile/kernel
parente6e6c46d759cd013cb57eba112a4129a3a353c4b (diff)
arch/tile: Change struct sigcontext to be more useful
Rather than just using pt_regs, it now contains the actual saved state explicitly, similar to pt_regs. By doing it this way, we provide a cleaner API for userspace (or equivalently, we avoid the need for libc to provide its own definition of sigcontext). While we're at it, move PT_FLAGS_xxx to where they are not visible from userspace. And always pass siginfo and mcontext to signal handlers, even if they claim they don't need it, since sometimes they actually try to use it anyway in practice. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/kernel')
-rw-r--r--arch/tile/kernel/signal.c27
-rw-r--r--arch/tile/kernel/stack.c2
2 files changed, 16 insertions, 13 deletions
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index 45b66a3c991f..ce183aa1492c 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs,
61 /* Always make any pending restarted system calls return -EINTR */ 61 /* Always make any pending restarted system calls return -EINTR */
62 current_thread_info()->restart_block.fn = do_no_restart_syscall; 62 current_thread_info()->restart_block.fn = do_no_restart_syscall;
63 63
64 /*
65 * Enforce that sigcontext is like pt_regs, and doesn't mess
66 * up our stack alignment rules.
67 */
68 BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
69 BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);
70
64 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) 71 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
65 err |= __get_user(((long *)regs)[i], 72 err |= __get_user(regs->regs[i], &sc->gregs[i]);
66 &((long __user *)(&sc->regs))[i]);
67 73
68 regs->faultnum = INT_SWINT_1_SIGRETURN; 74 regs->faultnum = INT_SWINT_1_SIGRETURN;
69 75
70 err |= __get_user(*pr0, &sc->regs.regs[0]); 76 err |= __get_user(*pr0, &sc->gregs[0]);
71 return err; 77 return err;
72} 78}
73 79
@@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
112 int i, err = 0; 118 int i, err = 0;
113 119
114 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) 120 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
115 err |= __put_user(((long *)regs)[i], 121 err |= __put_user(regs->regs[i], &sc->gregs[i]);
116 &((long __user *)(&sc->regs))[i]);
117 122
118 return err; 123 return err;
119} 124}
@@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
203 * Set up registers for signal handler. 208 * Set up registers for signal handler.
204 * Registers that we don't modify keep the value they had from 209 * Registers that we don't modify keep the value they had from
205 * user-space at the time we took the signal. 210 * user-space at the time we took the signal.
211 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
212 * since some things rely on this (e.g. glibc's debug/segfault.c).
206 */ 213 */
207 regs->pc = (unsigned long) ka->sa.sa_handler; 214 regs->pc = (unsigned long) ka->sa.sa_handler;
208 regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ 215 regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
209 regs->sp = (unsigned long) frame; 216 regs->sp = (unsigned long) frame;
210 regs->lr = restorer; 217 regs->lr = restorer;
211 regs->regs[0] = (unsigned long) usig; 218 regs->regs[0] = (unsigned long) usig;
212 219 regs->regs[1] = (unsigned long) &frame->info;
213 if (ka->sa.sa_flags & SA_SIGINFO) { 220 regs->regs[2] = (unsigned long) &frame->uc;
214 /* Need extra arguments, so mark to restore caller-saves. */ 221 regs->flags |= PT_FLAGS_CALLER_SAVES;
215 regs->regs[1] = (unsigned long) &frame->info;
216 regs->regs[2] = (unsigned long) &frame->uc;
217 regs->flags |= PT_FLAGS_CALLER_SAVES;
218 }
219 222
220 /* 223 /*
221 * Notify any tracer that was single-stepping it. 224 * Notify any tracer that was single-stepping it.
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 38a68b0b4581..ea2e0ce28380 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
175 pr_err(" <received signal %d>\n", 175 pr_err(" <received signal %d>\n",
176 frame->info.si_signo); 176 frame->info.si_signo);
177 } 177 }
178 return &frame->uc.uc_mcontext.regs; 178 return (struct pt_regs *)&frame->uc.uc_mcontext;
179 } 179 }
180 return NULL; 180 return NULL;
181} 181}