Commit 74fca9da097b74117ae2cef9e5f0d9b0e28ccbb7

Authored by Chris Metcalf
1 parent e6e6c46d75

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>

Showing 5 changed files with 36 additions and 27 deletions Side-by-side Diff

arch/tile/include/asm/ptrace.h
... ... @@ -51,10 +51,7 @@
51 51  
52 52 /*
53 53 * This struct defines the way the registers are stored on the stack during a
54   - * system call/exception. It should be a multiple of 8 bytes to preserve
55   - * normal stack alignment rules.
56   - *
57   - * Must track <sys/ucontext.h> and <sys/procfs.h>
  54 + * system call or exception. "struct sigcontext" has the same shape.
58 55 */
59 56 struct pt_regs {
60 57 /* Saved main processor registers; 56..63 are special. */
... ... @@ -80,11 +77,6 @@
80 77  
81 78 #endif /* __ASSEMBLY__ */
82 79  
83   -/* Flag bits in pt_regs.flags */
84   -#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
85   -#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */
86   -#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */
87   -
88 80 #define PTRACE_GETREGS 12
89 81 #define PTRACE_SETREGS 13
90 82 #define PTRACE_GETFPREGS 14
... ... @@ -100,6 +92,11 @@
100 92 #endif
101 93  
102 94 #ifdef __KERNEL__
  95 +
  96 +/* Flag bits in pt_regs.flags */
  97 +#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
  98 +#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */
  99 +#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */
103 100  
104 101 #ifndef __ASSEMBLY__
105 102  
arch/tile/include/asm/sigcontext.h
... ... @@ -15,13 +15,21 @@
15 15 #ifndef _ASM_TILE_SIGCONTEXT_H
16 16 #define _ASM_TILE_SIGCONTEXT_H
17 17  
18   -/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */
19   -#include <asm/ptrace.h>
  18 +#include <arch/abi.h>
20 19  
21   -/* Must track <sys/ucontext.h> */
22   -
  20 +/*
  21 + * struct sigcontext has the same shape as struct pt_regs,
  22 + * but is simplified since we know the fault is from userspace.
  23 + */
23 24 struct sigcontext {
24   - struct pt_regs regs;
  25 + uint_reg_t gregs[53]; /* General-purpose registers. */
  26 + uint_reg_t tp; /* Aliases gregs[TREG_TP]. */
  27 + uint_reg_t sp; /* Aliases gregs[TREG_SP]. */
  28 + uint_reg_t lr; /* Aliases gregs[TREG_LR]. */
  29 + uint_reg_t pc; /* Program counter. */
  30 + uint_reg_t ics; /* In Interrupt Critical Section? */
  31 + uint_reg_t faultnum; /* Fault number. */
  32 + uint_reg_t pad[5];
25 33 };
26 34  
27 35 #endif /* _ASM_TILE_SIGCONTEXT_H */
arch/tile/include/asm/signal.h
... ... @@ -24,6 +24,7 @@
24 24 #include <asm-generic/signal.h>
25 25  
26 26 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
  27 +struct pt_regs;
27 28 int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
28 29 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
29 30 void do_signal(struct pt_regs *regs);
arch/tile/kernel/signal.c
... ... @@ -61,13 +61,19 @@
61 61 /* Always make any pending restarted system calls return -EINTR */
62 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 71 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
65   - err |= __get_user(((long *)regs)[i],
66   - &((long __user *)(&sc->regs))[i]);
  72 + err |= __get_user(regs->regs[i], &sc->gregs[i]);
67 73  
68 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 77 return err;
72 78 }
73 79  
... ... @@ -112,8 +118,7 @@
112 118 int i, err = 0;
113 119  
114 120 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
115   - err |= __put_user(((long *)regs)[i],
116   - &((long __user *)(&sc->regs))[i]);
  121 + err |= __put_user(regs->regs[i], &sc->gregs[i]);
117 122  
118 123 return err;
119 124 }
120 125  
... ... @@ -203,19 +208,17 @@
203 208 * Set up registers for signal handler.
204 209 * Registers that we don't modify keep the value they had from
205 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 214 regs->pc = (unsigned long) ka->sa.sa_handler;
208 215 regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
209 216 regs->sp = (unsigned long) frame;
210 217 regs->lr = restorer;
211 218 regs->regs[0] = (unsigned long) usig;
212   -
213   - if (ka->sa.sa_flags & SA_SIGINFO) {
214   - /* Need extra arguments, so mark to restore 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 + regs->regs[1] = (unsigned long) &frame->info;
  220 + regs->regs[2] = (unsigned long) &frame->uc;
  221 + regs->flags |= PT_FLAGS_CALLER_SAVES;
219 222  
220 223 /*
221 224 * Notify any tracer that was single-stepping it.
arch/tile/kernel/stack.c
... ... @@ -175,7 +175,7 @@
175 175 pr_err(" <received signal %d>\n",
176 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 180 return NULL;
181 181 }