diff options
Diffstat (limited to 'arch/frv/kernel')
-rw-r--r-- | arch/frv/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/frv/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/frv/kernel/futex.c | 242 | ||||
-rw-r--r-- | arch/frv/kernel/signal.c | 155 |
4 files changed, 329 insertions, 71 deletions
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index 981c2c7dec0d..422f30ede575 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile | |||
@@ -20,3 +20,4 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o | |||
20 | obj-$(CONFIG_PM) += pm.o cmode.o | 20 | obj-$(CONFIG_PM) += pm.o cmode.o |
21 | obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o | 21 | obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o |
22 | obj-$(CONFIG_SYSCTL) += sysctl.o | 22 | obj-$(CONFIG_SYSCTL) += sysctl.o |
23 | obj-$(CONFIG_FUTEX) += futex.o | ||
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ad10ea595459..5f6548388b74 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S | |||
@@ -1076,7 +1076,7 @@ __entry_work_notifysig: | |||
1076 | LEDS 0x6410 | 1076 | LEDS 0x6410 |
1077 | ori.p gr4,#0,gr8 | 1077 | ori.p gr4,#0,gr8 |
1078 | call do_notify_resume | 1078 | call do_notify_resume |
1079 | bra __entry_return_direct | 1079 | bra __entry_resume_userspace |
1080 | 1080 | ||
1081 | # perform syscall entry tracing | 1081 | # perform syscall entry tracing |
1082 | __syscall_trace_entry: | 1082 | __syscall_trace_entry: |
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c new file mode 100644 index 000000000000..eae874a970c6 --- /dev/null +++ b/arch/frv/kernel/futex.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* futex.c: futex operations | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/futex.h> | ||
13 | #include <asm/futex.h> | ||
14 | #include <asm/errno.h> | ||
15 | #include <asm/uaccess.h> | ||
16 | |||
17 | /* | ||
18 | * the various futex operations; MMU fault checking is ignored under no-MMU | ||
19 | * conditions | ||
20 | */ | ||
21 | static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) | ||
22 | { | ||
23 | int oldval, ret; | ||
24 | |||
25 | asm("0: \n" | ||
26 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
27 | " ckeq icc3,cc7 \n" | ||
28 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
29 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
30 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
31 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
32 | " beq icc3,#0,0b \n" | ||
33 | " setlos 0,%2 \n" | ||
34 | "3: \n" | ||
35 | ".subsection 2 \n" | ||
36 | "4: setlos %5,%2 \n" | ||
37 | " bra 3b \n" | ||
38 | ".previous \n" | ||
39 | ".section __ex_table,\"a\" \n" | ||
40 | " .balign 8 \n" | ||
41 | " .long 1b,4b \n" | ||
42 | " .long 2b,4b \n" | ||
43 | ".previous" | ||
44 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
45 | : "3"(oparg), "i"(-EFAULT) | ||
46 | : "memory", "cc7", "cc3", "icc3" | ||
47 | ); | ||
48 | |||
49 | *_oldval = oldval; | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) | ||
54 | { | ||
55 | int oldval, ret; | ||
56 | |||
57 | asm("0: \n" | ||
58 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
59 | " ckeq icc3,cc7 \n" | ||
60 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
61 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
62 | " add %1,%3,%3 \n" | ||
63 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
64 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
65 | " beq icc3,#0,0b \n" | ||
66 | " setlos 0,%2 \n" | ||
67 | "3: \n" | ||
68 | ".subsection 2 \n" | ||
69 | "4: setlos %5,%2 \n" | ||
70 | " bra 3b \n" | ||
71 | ".previous \n" | ||
72 | ".section __ex_table,\"a\" \n" | ||
73 | " .balign 8 \n" | ||
74 | " .long 1b,4b \n" | ||
75 | " .long 2b,4b \n" | ||
76 | ".previous" | ||
77 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
78 | : "3"(oparg), "i"(-EFAULT) | ||
79 | : "memory", "cc7", "cc3", "icc3" | ||
80 | ); | ||
81 | |||
82 | *_oldval = oldval; | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) | ||
87 | { | ||
88 | int oldval, ret; | ||
89 | |||
90 | asm("0: \n" | ||
91 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
92 | " ckeq icc3,cc7 \n" | ||
93 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
94 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
95 | " or %1,%3,%3 \n" | ||
96 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
97 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
98 | " beq icc3,#0,0b \n" | ||
99 | " setlos 0,%2 \n" | ||
100 | "3: \n" | ||
101 | ".subsection 2 \n" | ||
102 | "4: setlos %5,%2 \n" | ||
103 | " bra 3b \n" | ||
104 | ".previous \n" | ||
105 | ".section __ex_table,\"a\" \n" | ||
106 | " .balign 8 \n" | ||
107 | " .long 1b,4b \n" | ||
108 | " .long 2b,4b \n" | ||
109 | ".previous" | ||
110 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
111 | : "3"(oparg), "i"(-EFAULT) | ||
112 | : "memory", "cc7", "cc3", "icc3" | ||
113 | ); | ||
114 | |||
115 | *_oldval = oldval; | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) | ||
120 | { | ||
121 | int oldval, ret; | ||
122 | |||
123 | asm("0: \n" | ||
124 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
125 | " ckeq icc3,cc7 \n" | ||
126 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
127 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
128 | " and %1,%3,%3 \n" | ||
129 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
130 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
131 | " beq icc3,#0,0b \n" | ||
132 | " setlos 0,%2 \n" | ||
133 | "3: \n" | ||
134 | ".subsection 2 \n" | ||
135 | "4: setlos %5,%2 \n" | ||
136 | " bra 3b \n" | ||
137 | ".previous \n" | ||
138 | ".section __ex_table,\"a\" \n" | ||
139 | " .balign 8 \n" | ||
140 | " .long 1b,4b \n" | ||
141 | " .long 2b,4b \n" | ||
142 | ".previous" | ||
143 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
144 | : "3"(oparg), "i"(-EFAULT) | ||
145 | : "memory", "cc7", "cc3", "icc3" | ||
146 | ); | ||
147 | |||
148 | *_oldval = oldval; | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) | ||
153 | { | ||
154 | int oldval, ret; | ||
155 | |||
156 | asm("0: \n" | ||
157 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
158 | " ckeq icc3,cc7 \n" | ||
159 | "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ | ||
160 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
161 | " xor %1,%3,%3 \n" | ||
162 | "2: cst.p %3,%M0 ,cc3,#1 \n" | ||
163 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ | ||
164 | " beq icc3,#0,0b \n" | ||
165 | " setlos 0,%2 \n" | ||
166 | "3: \n" | ||
167 | ".subsection 2 \n" | ||
168 | "4: setlos %5,%2 \n" | ||
169 | " bra 3b \n" | ||
170 | ".previous \n" | ||
171 | ".section __ex_table,\"a\" \n" | ||
172 | " .balign 8 \n" | ||
173 | " .long 1b,4b \n" | ||
174 | " .long 2b,4b \n" | ||
175 | ".previous" | ||
176 | : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) | ||
177 | : "3"(oparg), "i"(-EFAULT) | ||
178 | : "memory", "cc7", "cc3", "icc3" | ||
179 | ); | ||
180 | |||
181 | *_oldval = oldval; | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | /*****************************************************************************/ | ||
186 | /* | ||
187 | * do the futex operations | ||
188 | */ | ||
189 | int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | ||
190 | { | ||
191 | int op = (encoded_op >> 28) & 7; | ||
192 | int cmp = (encoded_op >> 24) & 15; | ||
193 | int oparg = (encoded_op << 8) >> 20; | ||
194 | int cmparg = (encoded_op << 20) >> 20; | ||
195 | int oldval = 0, ret; | ||
196 | |||
197 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
198 | oparg = 1 << oparg; | ||
199 | |||
200 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
201 | return -EFAULT; | ||
202 | |||
203 | inc_preempt_count(); | ||
204 | |||
205 | switch (op) { | ||
206 | case FUTEX_OP_SET: | ||
207 | ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); | ||
208 | break; | ||
209 | case FUTEX_OP_ADD: | ||
210 | ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); | ||
211 | break; | ||
212 | case FUTEX_OP_OR: | ||
213 | ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); | ||
214 | break; | ||
215 | case FUTEX_OP_ANDN: | ||
216 | ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); | ||
217 | break; | ||
218 | case FUTEX_OP_XOR: | ||
219 | ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); | ||
220 | break; | ||
221 | default: | ||
222 | ret = -ENOSYS; | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | dec_preempt_count(); | ||
227 | |||
228 | if (!ret) { | ||
229 | switch (cmp) { | ||
230 | case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; | ||
231 | case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; | ||
232 | case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; | ||
233 | case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; | ||
234 | case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; | ||
235 | case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; | ||
236 | default: ret = -ENOSYS; break; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | return ret; | ||
241 | |||
242 | } /* end futex_atomic_op_inuser() */ | ||
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d4ccc0728dfe..5b7146f54fd5 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -35,7 +35,7 @@ struct fdpic_func_descriptor { | |||
35 | unsigned long GOT; | 35 | unsigned long GOT; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | 38 | static int do_signal(sigset_t *oldset); |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Atomically swap in the new signal mask, and wait for a signal. | 41 | * Atomically swap in the new signal mask, and wait for a signal. |
@@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) | |||
55 | while (1) { | 55 | while (1) { |
56 | current->state = TASK_INTERRUPTIBLE; | 56 | current->state = TASK_INTERRUPTIBLE; |
57 | schedule(); | 57 | schedule(); |
58 | if (do_signal(__frame, &saveset)) | 58 | if (do_signal(&saveset)) |
59 | /* return the signal number as the return value of this function | 59 | /* return the signal number as the return value of this function |
60 | * - this is an utterly evil hack. syscalls should not invoke do_signal() | 60 | * - this is an utterly evil hack. syscalls should not invoke do_signal() |
61 | * as entry.S sets regs->gr8 to the return value of the system call | 61 | * as entry.S sets regs->gr8 to the return value of the system call |
@@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) | |||
91 | while (1) { | 91 | while (1) { |
92 | current->state = TASK_INTERRUPTIBLE; | 92 | current->state = TASK_INTERRUPTIBLE; |
93 | schedule(); | 93 | schedule(); |
94 | if (do_signal(__frame, &saveset)) | 94 | if (do_signal(&saveset)) |
95 | /* return the signal number as the return value of this function | 95 | /* return the signal number as the return value of this function |
96 | * - this is an utterly evil hack. syscalls should not invoke do_signal() | 96 | * - this is an utterly evil hack. syscalls should not invoke do_signal() |
97 | * as entry.S sets regs->gr8 to the return value of the system call | 97 | * as entry.S sets regs->gr8 to the return value of the system call |
@@ -276,13 +276,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) | |||
276 | * Determine which stack to use.. | 276 | * Determine which stack to use.. |
277 | */ | 277 | */ |
278 | static inline void __user *get_sigframe(struct k_sigaction *ka, | 278 | static inline void __user *get_sigframe(struct k_sigaction *ka, |
279 | struct pt_regs *regs, | ||
280 | size_t frame_size) | 279 | size_t frame_size) |
281 | { | 280 | { |
282 | unsigned long sp; | 281 | unsigned long sp; |
283 | 282 | ||
284 | /* Default to using normal stack */ | 283 | /* Default to using normal stack */ |
285 | sp = regs->sp; | 284 | sp = __frame->sp; |
286 | 285 | ||
287 | /* This is the X/Open sanctioned signal stack switching. */ | 286 | /* This is the X/Open sanctioned signal stack switching. */ |
288 | if (ka->sa.sa_flags & SA_ONSTACK) { | 287 | if (ka->sa.sa_flags & SA_ONSTACK) { |
@@ -291,18 +290,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
291 | } | 290 | } |
292 | 291 | ||
293 | return (void __user *) ((sp - frame_size) & ~7UL); | 292 | return (void __user *) ((sp - frame_size) & ~7UL); |
293 | |||
294 | } /* end get_sigframe() */ | 294 | } /* end get_sigframe() */ |
295 | 295 | ||
296 | /*****************************************************************************/ | 296 | /*****************************************************************************/ |
297 | /* | 297 | /* |
298 | * | 298 | * |
299 | */ | 299 | */ |
300 | static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) | 300 | static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) |
301 | { | 301 | { |
302 | struct sigframe __user *frame; | 302 | struct sigframe __user *frame; |
303 | int rsig; | 303 | int rsig; |
304 | 304 | ||
305 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 305 | frame = get_sigframe(ka, sizeof(*frame)); |
306 | 306 | ||
307 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 307 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
308 | goto give_sigsegv; | 308 | goto give_sigsegv; |
@@ -346,47 +346,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p | |||
346 | } | 346 | } |
347 | 347 | ||
348 | /* set up registers for signal handler */ | 348 | /* set up registers for signal handler */ |
349 | regs->sp = (unsigned long) frame; | 349 | __frame->sp = (unsigned long) frame; |
350 | regs->lr = (unsigned long) &frame->retcode; | 350 | __frame->lr = (unsigned long) &frame->retcode; |
351 | regs->gr8 = sig; | 351 | __frame->gr8 = sig; |
352 | 352 | ||
353 | if (get_personality & FDPIC_FUNCPTRS) { | 353 | if (get_personality & FDPIC_FUNCPTRS) { |
354 | struct fdpic_func_descriptor __user *funcptr = | 354 | struct fdpic_func_descriptor __user *funcptr = |
355 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; | 355 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; |
356 | __get_user(regs->pc, &funcptr->text); | 356 | __get_user(__frame->pc, &funcptr->text); |
357 | __get_user(regs->gr15, &funcptr->GOT); | 357 | __get_user(__frame->gr15, &funcptr->GOT); |
358 | } else { | 358 | } else { |
359 | regs->pc = (unsigned long) ka->sa.sa_handler; | 359 | __frame->pc = (unsigned long) ka->sa.sa_handler; |
360 | regs->gr15 = 0; | 360 | __frame->gr15 = 0; |
361 | } | 361 | } |
362 | 362 | ||
363 | set_fs(USER_DS); | 363 | set_fs(USER_DS); |
364 | 364 | ||
365 | /* the tracer may want to single-step inside the handler */ | ||
366 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
367 | ptrace_notify(SIGTRAP); | ||
368 | |||
365 | #if DEBUG_SIG | 369 | #if DEBUG_SIG |
366 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 370 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
367 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 371 | sig, current->comm, current->pid, frame, __frame->pc, |
372 | frame->pretcode); | ||
368 | #endif | 373 | #endif |
369 | 374 | ||
370 | return; | 375 | return 1; |
371 | 376 | ||
372 | give_sigsegv: | 377 | give_sigsegv: |
373 | if (sig == SIGSEGV) | ||
374 | ka->sa.sa_handler = SIG_DFL; | ||
375 | |||
376 | force_sig(SIGSEGV, current); | 378 | force_sig(SIGSEGV, current); |
379 | return 0; | ||
380 | |||
377 | } /* end setup_frame() */ | 381 | } /* end setup_frame() */ |
378 | 382 | ||
379 | /*****************************************************************************/ | 383 | /*****************************************************************************/ |
380 | /* | 384 | /* |
381 | * | 385 | * |
382 | */ | 386 | */ |
383 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 387 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
384 | sigset_t *set, struct pt_regs * regs) | 388 | sigset_t *set) |
385 | { | 389 | { |
386 | struct rt_sigframe __user *frame; | 390 | struct rt_sigframe __user *frame; |
387 | int rsig; | 391 | int rsig; |
388 | 392 | ||
389 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 393 | frame = get_sigframe(ka, sizeof(*frame)); |
390 | 394 | ||
391 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 395 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
392 | goto give_sigsegv; | 396 | goto give_sigsegv; |
@@ -409,7 +413,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
409 | if (__put_user(0, &frame->uc.uc_flags) || | 413 | if (__put_user(0, &frame->uc.uc_flags) || |
410 | __put_user(0, &frame->uc.uc_link) || | 414 | __put_user(0, &frame->uc.uc_link) || |
411 | __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || | 415 | __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || |
412 | __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || | 416 | __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || |
413 | __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) | 417 | __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) |
414 | goto give_sigsegv; | 418 | goto give_sigsegv; |
415 | 419 | ||
@@ -440,34 +444,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
440 | } | 444 | } |
441 | 445 | ||
442 | /* Set up registers for signal handler */ | 446 | /* Set up registers for signal handler */ |
443 | regs->sp = (unsigned long) frame; | 447 | __frame->sp = (unsigned long) frame; |
444 | regs->lr = (unsigned long) &frame->retcode; | 448 | __frame->lr = (unsigned long) &frame->retcode; |
445 | regs->gr8 = sig; | 449 | __frame->gr8 = sig; |
446 | regs->gr9 = (unsigned long) &frame->info; | 450 | __frame->gr9 = (unsigned long) &frame->info; |
447 | 451 | ||
448 | if (get_personality & FDPIC_FUNCPTRS) { | 452 | if (get_personality & FDPIC_FUNCPTRS) { |
449 | struct fdpic_func_descriptor *funcptr = | 453 | struct fdpic_func_descriptor *funcptr = |
450 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; | 454 | (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; |
451 | __get_user(regs->pc, &funcptr->text); | 455 | __get_user(__frame->pc, &funcptr->text); |
452 | __get_user(regs->gr15, &funcptr->GOT); | 456 | __get_user(__frame->gr15, &funcptr->GOT); |
453 | } else { | 457 | } else { |
454 | regs->pc = (unsigned long) ka->sa.sa_handler; | 458 | __frame->pc = (unsigned long) ka->sa.sa_handler; |
455 | regs->gr15 = 0; | 459 | __frame->gr15 = 0; |
456 | } | 460 | } |
457 | 461 | ||
458 | set_fs(USER_DS); | 462 | set_fs(USER_DS); |
459 | 463 | ||
464 | /* the tracer may want to single-step inside the handler */ | ||
465 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
466 | ptrace_notify(SIGTRAP); | ||
467 | |||
460 | #if DEBUG_SIG | 468 | #if DEBUG_SIG |
461 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 469 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
462 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 470 | sig, current->comm, current->pid, frame, __frame->pc, |
471 | frame->pretcode); | ||
463 | #endif | 472 | #endif |
464 | 473 | ||
465 | return; | 474 | return 1; |
466 | 475 | ||
467 | give_sigsegv: | 476 | give_sigsegv: |
468 | if (sig == SIGSEGV) | ||
469 | ka->sa.sa_handler = SIG_DFL; | ||
470 | force_sig(SIGSEGV, current); | 477 | force_sig(SIGSEGV, current); |
478 | return 0; | ||
471 | 479 | ||
472 | } /* end setup_rt_frame() */ | 480 | } /* end setup_rt_frame() */ |
473 | 481 | ||
@@ -475,43 +483,51 @@ give_sigsegv: | |||
475 | /* | 483 | /* |
476 | * OK, we're invoking a handler | 484 | * OK, we're invoking a handler |
477 | */ | 485 | */ |
478 | static void handle_signal(unsigned long sig, siginfo_t *info, | 486 | static int handle_signal(unsigned long sig, siginfo_t *info, |
479 | struct k_sigaction *ka, sigset_t *oldset, | 487 | struct k_sigaction *ka, sigset_t *oldset) |
480 | struct pt_regs *regs) | ||
481 | { | 488 | { |
489 | int ret; | ||
490 | |||
482 | /* Are we from a system call? */ | 491 | /* Are we from a system call? */ |
483 | if (in_syscall(regs)) { | 492 | if (in_syscall(__frame)) { |
484 | /* If so, check system call restarting.. */ | 493 | /* If so, check system call restarting.. */ |
485 | switch (regs->gr8) { | 494 | switch (__frame->gr8) { |
486 | case -ERESTART_RESTARTBLOCK: | 495 | case -ERESTART_RESTARTBLOCK: |
487 | case -ERESTARTNOHAND: | 496 | case -ERESTARTNOHAND: |
488 | regs->gr8 = -EINTR; | 497 | __frame->gr8 = -EINTR; |
489 | break; | 498 | break; |
490 | 499 | ||
491 | case -ERESTARTSYS: | 500 | case -ERESTARTSYS: |
492 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 501 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
493 | regs->gr8 = -EINTR; | 502 | __frame->gr8 = -EINTR; |
494 | break; | 503 | break; |
495 | } | 504 | } |
505 | |||
496 | /* fallthrough */ | 506 | /* fallthrough */ |
497 | case -ERESTARTNOINTR: | 507 | case -ERESTARTNOINTR: |
498 | regs->gr8 = regs->orig_gr8; | 508 | __frame->gr8 = __frame->orig_gr8; |
499 | regs->pc -= 4; | 509 | __frame->pc -= 4; |
500 | } | 510 | } |
501 | } | 511 | } |
502 | 512 | ||
503 | /* Set up the stack frame */ | 513 | /* Set up the stack frame */ |
504 | if (ka->sa.sa_flags & SA_SIGINFO) | 514 | if (ka->sa.sa_flags & SA_SIGINFO) |
505 | setup_rt_frame(sig, ka, info, oldset, regs); | 515 | ret = setup_rt_frame(sig, ka, info, oldset); |
506 | else | 516 | else |
507 | setup_frame(sig, ka, oldset, regs); | 517 | ret = setup_frame(sig, ka, oldset); |
518 | |||
519 | if (ret) { | ||
520 | spin_lock_irq(¤t->sighand->siglock); | ||
521 | sigorsets(¤t->blocked, ¤t->blocked, | ||
522 | &ka->sa.sa_mask); | ||
523 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
524 | sigaddset(¤t->blocked, sig); | ||
525 | recalc_sigpending(); | ||
526 | spin_unlock_irq(¤t->sighand->siglock); | ||
527 | } | ||
528 | |||
529 | return ret; | ||
508 | 530 | ||
509 | spin_lock_irq(¤t->sighand->siglock); | ||
510 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
511 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
512 | sigaddset(¤t->blocked, sig); | ||
513 | recalc_sigpending(); | ||
514 | spin_unlock_irq(¤t->sighand->siglock); | ||
515 | } /* end handle_signal() */ | 531 | } /* end handle_signal() */ |
516 | 532 | ||
517 | /*****************************************************************************/ | 533 | /*****************************************************************************/ |
@@ -520,7 +536,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
520 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 536 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
521 | * mistake. | 537 | * mistake. |
522 | */ | 538 | */ |
523 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | 539 | static int do_signal(sigset_t *oldset) |
524 | { | 540 | { |
525 | struct k_sigaction ka; | 541 | struct k_sigaction ka; |
526 | siginfo_t info; | 542 | siginfo_t info; |
@@ -532,7 +548,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
532 | * kernel mode. Just return without doing anything | 548 | * kernel mode. Just return without doing anything |
533 | * if so. | 549 | * if so. |
534 | */ | 550 | */ |
535 | if (!user_mode(regs)) | 551 | if (!user_mode(__frame)) |
536 | return 1; | 552 | return 1; |
537 | 553 | ||
538 | if (try_to_freeze()) | 554 | if (try_to_freeze()) |
@@ -541,30 +557,29 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
541 | if (!oldset) | 557 | if (!oldset) |
542 | oldset = ¤t->blocked; | 558 | oldset = ¤t->blocked; |
543 | 559 | ||
544 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 560 | signr = get_signal_to_deliver(&info, &ka, __frame, NULL); |
545 | if (signr > 0) { | 561 | if (signr > 0) |
546 | handle_signal(signr, &info, &ka, oldset, regs); | 562 | return handle_signal(signr, &info, &ka, oldset); |
547 | return 1; | ||
548 | } | ||
549 | 563 | ||
550 | no_signal: | 564 | no_signal: |
551 | /* Did we come from a system call? */ | 565 | /* Did we come from a system call? */ |
552 | if (regs->syscallno >= 0) { | 566 | if (__frame->syscallno >= 0) { |
553 | /* Restart the system call - no handlers present */ | 567 | /* Restart the system call - no handlers present */ |
554 | if (regs->gr8 == -ERESTARTNOHAND || | 568 | if (__frame->gr8 == -ERESTARTNOHAND || |
555 | regs->gr8 == -ERESTARTSYS || | 569 | __frame->gr8 == -ERESTARTSYS || |
556 | regs->gr8 == -ERESTARTNOINTR) { | 570 | __frame->gr8 == -ERESTARTNOINTR) { |
557 | regs->gr8 = regs->orig_gr8; | 571 | __frame->gr8 = __frame->orig_gr8; |
558 | regs->pc -= 4; | 572 | __frame->pc -= 4; |
559 | } | 573 | } |
560 | 574 | ||
561 | if (regs->gr8 == -ERESTART_RESTARTBLOCK){ | 575 | if (__frame->gr8 == -ERESTART_RESTARTBLOCK){ |
562 | regs->gr8 = __NR_restart_syscall; | 576 | __frame->gr8 = __NR_restart_syscall; |
563 | regs->pc -= 4; | 577 | __frame->pc -= 4; |
564 | } | 578 | } |
565 | } | 579 | } |
566 | 580 | ||
567 | return 0; | 581 | return 0; |
582 | |||
568 | } /* end do_signal() */ | 583 | } /* end do_signal() */ |
569 | 584 | ||
570 | /*****************************************************************************/ | 585 | /*****************************************************************************/ |
@@ -580,6 +595,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) | |||
580 | 595 | ||
581 | /* deal with pending signal delivery */ | 596 | /* deal with pending signal delivery */ |
582 | if (thread_info_flags & _TIF_SIGPENDING) | 597 | if (thread_info_flags & _TIF_SIGPENDING) |
583 | do_signal(__frame, NULL); | 598 | do_signal(NULL); |
584 | 599 | ||
585 | } /* end do_notify_resume() */ | 600 | } /* end do_notify_resume() */ |