diff options
Diffstat (limited to 'arch/avr32/kernel/signal.c')
-rw-r--r-- | arch/avr32/kernel/signal.c | 50 |
1 files changed, 20 insertions, 30 deletions
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index b80c0b3d2bab..d309fbcc3bd6 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c | |||
@@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | static inline void __user * | 129 | static inline void __user * |
130 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) | 130 | get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize) |
131 | { | 131 | { |
132 | unsigned long sp = regs->sp; | 132 | unsigned long sp = sigsp(regs->sp, ksig); |
133 | |||
134 | if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) | ||
135 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
136 | 133 | ||
137 | return (void __user *)((sp - framesize) & ~3); | 134 | return (void __user *)((sp - framesize) & ~3); |
138 | } | 135 | } |
139 | 136 | ||
140 | static int | 137 | static int |
141 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 138 | setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
142 | sigset_t *set, struct pt_regs *regs) | ||
143 | { | 139 | { |
144 | struct rt_sigframe __user *frame; | 140 | struct rt_sigframe __user *frame; |
145 | int err = 0; | 141 | int err = 0; |
146 | 142 | ||
147 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 143 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
148 | err = -EFAULT; | 144 | err = -EFAULT; |
149 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 145 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
150 | goto out; | 146 | goto out; |
@@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
164 | err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), | 160 | err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), |
165 | &frame->retcode); | 161 | &frame->retcode); |
166 | 162 | ||
167 | err |= copy_siginfo_to_user(&frame->info, info); | 163 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
168 | 164 | ||
169 | /* Set up the ucontext */ | 165 | /* Set up the ucontext */ |
170 | err |= __put_user(0, &frame->uc.uc_flags); | 166 | err |= __put_user(0, &frame->uc.uc_flags); |
@@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
176 | if (err) | 172 | if (err) |
177 | goto out; | 173 | goto out; |
178 | 174 | ||
179 | regs->r12 = sig; | 175 | regs->r12 = ksig->sig; |
180 | regs->r11 = (unsigned long) &frame->info; | 176 | regs->r11 = (unsigned long) &frame->info; |
181 | regs->r10 = (unsigned long) &frame->uc; | 177 | regs->r10 = (unsigned long) &frame->uc; |
182 | regs->sp = (unsigned long) frame; | 178 | regs->sp = (unsigned long) frame; |
183 | if (ka->sa.sa_flags & SA_RESTORER) | 179 | if (ksig->ka.sa.sa_flags & SA_RESTORER) |
184 | regs->lr = (unsigned long)ka->sa.sa_restorer; | 180 | regs->lr = (unsigned long)ksig->ka.sa.sa_restorer; |
185 | else { | 181 | else { |
186 | printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", | 182 | printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", |
187 | current->comm, current->pid); | 183 | current->comm, current->pid); |
@@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
189 | } | 185 | } |
190 | 186 | ||
191 | pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", | 187 | pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", |
192 | current->comm, current->pid, sig, regs->sp, | 188 | current->comm, current->pid, ksig->sig, regs->sp, |
193 | regs->pc, ka->sa.sa_handler, regs->lr); | 189 | regs->pc, ksig->ka.sa.sa_handler, regs->lr); |
194 | 190 | ||
195 | regs->pc = (unsigned long) ka->sa.sa_handler; | 191 | regs->pc = (unsigned long)ksig->ka.sa.sa_handler; |
196 | 192 | ||
197 | out: | 193 | out: |
198 | return err; | 194 | return err; |
@@ -208,15 +204,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs) | |||
208 | } | 204 | } |
209 | 205 | ||
210 | static inline void | 206 | static inline void |
211 | handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | 207 | handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall) |
212 | struct pt_regs *regs, int syscall) | ||
213 | { | 208 | { |
214 | int ret; | 209 | int ret; |
215 | 210 | ||
216 | /* | 211 | /* |
217 | * Set up the stack frame | 212 | * Set up the stack frame |
218 | */ | 213 | */ |
219 | ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); | 214 | ret = setup_rt_frame(ksig, sigmask_to_save(), regs); |
220 | 215 | ||
221 | /* | 216 | /* |
222 | * Check that the resulting registers are sane | 217 | * Check that the resulting registers are sane |
@@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
226 | /* | 221 | /* |
227 | * Block the signal if we were successful. | 222 | * Block the signal if we were successful. |
228 | */ | 223 | */ |
229 | if (ret != 0) | 224 | signal_setup_done(ret, ksig, 0); |
230 | force_sigsegv(sig, current); | ||
231 | else | ||
232 | signal_delivered(sig, info, ka, regs, 0); | ||
233 | } | 225 | } |
234 | 226 | ||
235 | /* | 227 | /* |
@@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
239 | */ | 231 | */ |
240 | static void do_signal(struct pt_regs *regs, int syscall) | 232 | static void do_signal(struct pt_regs *regs, int syscall) |
241 | { | 233 | { |
242 | siginfo_t info; | 234 | struct ksignal ksig; |
243 | int signr; | ||
244 | struct k_sigaction ka; | ||
245 | 235 | ||
246 | /* | 236 | /* |
247 | * We want the common case to go fast, which is why we may in | 237 | * We want the common case to go fast, which is why we may in |
@@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
251 | if (!user_mode(regs)) | 241 | if (!user_mode(regs)) |
252 | return; | 242 | return; |
253 | 243 | ||
254 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 244 | get_signal(&ksig); |
255 | if (syscall) { | 245 | if (syscall) { |
256 | switch (regs->r12) { | 246 | switch (regs->r12) { |
257 | case -ERESTART_RESTARTBLOCK: | 247 | case -ERESTART_RESTARTBLOCK: |
258 | case -ERESTARTNOHAND: | 248 | case -ERESTARTNOHAND: |
259 | if (signr > 0) { | 249 | if (ksig.sig > 0) { |
260 | regs->r12 = -EINTR; | 250 | regs->r12 = -EINTR; |
261 | break; | 251 | break; |
262 | } | 252 | } |
263 | /* fall through */ | 253 | /* fall through */ |
264 | case -ERESTARTSYS: | 254 | case -ERESTARTSYS: |
265 | if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) { | 255 | if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) { |
266 | regs->r12 = -EINTR; | 256 | regs->r12 = -EINTR; |
267 | break; | 257 | break; |
268 | } | 258 | } |
@@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
272 | } | 262 | } |
273 | } | 263 | } |
274 | 264 | ||
275 | if (signr == 0) { | 265 | if (!ksig.sig) { |
276 | /* No signal to deliver -- put the saved sigmask back */ | 266 | /* No signal to deliver -- put the saved sigmask back */ |
277 | restore_saved_sigmask(); | 267 | restore_saved_sigmask(); |
278 | return; | 268 | return; |
279 | } | 269 | } |
280 | 270 | ||
281 | handle_signal(signr, &ka, &info, regs, syscall); | 271 | handle_signal(&ksig, regs, syscall); |
282 | } | 272 | } |
283 | 273 | ||
284 | asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) | 274 | asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) |