aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r--arch/powerpc/kernel/signal_32.c68
1 files changed, 32 insertions, 36 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 5a2eba60dd39..d3f0b6d452fb 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -76,7 +76,6 @@
76 * registers from *regs. This is what we need 76 * registers from *regs. This is what we need
77 * to do when a signal has been delivered. 77 * to do when a signal has been delivered.
78 */ 78 */
79#define sigreturn_exit(regs) return 0
80 79
81#define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32)) 80#define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32))
82#undef __SIGNAL_FRAMESIZE 81#undef __SIGNAL_FRAMESIZE
@@ -156,9 +155,17 @@ static inline int save_general_regs(struct pt_regs *regs,
156 elf_greg_t64 *gregs = (elf_greg_t64 *)regs; 155 elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
157 int i; 156 int i;
158 157
159 for (i = 0; i <= PT_RESULT; i ++) 158 if (!FULL_REGS(regs)) {
159 set_thread_flag(TIF_SAVE_NVGPRS);
160 current_thread_info()->nvgprs_frame = frame->mc_gregs;
161 }
162
163 for (i = 0; i <= PT_RESULT; i ++) {
164 if (i == 14 && !FULL_REGS(regs))
165 i = 32;
160 if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i])) 166 if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i]))
161 return -EFAULT; 167 return -EFAULT;
168 }
162 return 0; 169 return 0;
163} 170}
164 171
@@ -179,8 +186,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
179 186
180#else /* CONFIG_PPC64 */ 187#else /* CONFIG_PPC64 */
181 188
182extern void sigreturn_exit(struct pt_regs *);
183
184#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) 189#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
185 190
186static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set) 191static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set)
@@ -214,6 +219,15 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka,
214static inline int save_general_regs(struct pt_regs *regs, 219static inline int save_general_regs(struct pt_regs *regs,
215 struct mcontext __user *frame) 220 struct mcontext __user *frame)
216{ 221{
222 if (!FULL_REGS(regs)) {
223 /* Zero out the unsaved GPRs to avoid information
224 leak, and set TIF_SAVE_NVGPRS to ensure that the
225 registers do actually get saved later. */
226 memset(&regs->gpr[14], 0, 18 * sizeof(unsigned long));
227 current_thread_info()->nvgprs_frame = &frame->mc_gregs;
228 set_thread_flag(TIF_SAVE_NVGPRS);
229 }
230
217 return __copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE); 231 return __copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE);
218} 232}
219 233
@@ -256,8 +270,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
256 while (1) { 270 while (1) {
257 current->state = TASK_INTERRUPTIBLE; 271 current->state = TASK_INTERRUPTIBLE;
258 schedule(); 272 schedule();
259 if (do_signal(&saveset, regs)) 273 if (do_signal(&saveset, regs)) {
260 sigreturn_exit(regs); 274 set_thread_flag(TIF_RESTOREALL);
275 return 0;
276 }
261 } 277 }
262} 278}
263 279
@@ -292,8 +308,10 @@ long sys_rt_sigsuspend(
292 while (1) { 308 while (1) {
293 current->state = TASK_INTERRUPTIBLE; 309 current->state = TASK_INTERRUPTIBLE;
294 schedule(); 310 schedule();
295 if (do_signal(&saveset, regs)) 311 if (do_signal(&saveset, regs)) {
296 sigreturn_exit(regs); 312 set_thread_flag(TIF_RESTOREALL);
313 return 0;
314 }
297 } 315 }
298} 316}
299 317
@@ -391,9 +409,6 @@ struct rt_sigframe {
391static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, 409static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
392 int sigret) 410 int sigret)
393{ 411{
394#ifdef CONFIG_PPC32
395 CHECK_FULL_REGS(regs);
396#endif
397 /* Make sure floating point registers are stored in regs */ 412 /* Make sure floating point registers are stored in regs */
398 flush_fp_to_thread(current); 413 flush_fp_to_thread(current);
399 414
@@ -828,12 +843,6 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
828 regs->gpr[6] = (unsigned long) rt_sf; 843 regs->gpr[6] = (unsigned long) rt_sf;
829 regs->nip = (unsigned long) ka->sa.sa_handler; 844 regs->nip = (unsigned long) ka->sa.sa_handler;
830 regs->trap = 0; 845 regs->trap = 0;
831#ifdef CONFIG_PPC64
832 regs->result = 0;
833
834 if (test_thread_flag(TIF_SINGLESTEP))
835 ptrace_notify(SIGTRAP);
836#endif
837 return 1; 846 return 1;
838 847
839badframe: 848badframe:
@@ -911,8 +920,8 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
911 */ 920 */
912 if (do_setcontext(new_ctx, regs, 0)) 921 if (do_setcontext(new_ctx, regs, 0))
913 do_exit(SIGSEGV); 922 do_exit(SIGSEGV);
914 sigreturn_exit(regs); 923
915 /* doesn't actually return back to here */ 924 set_thread_flag(TIF_RESTOREALL);
916 return 0; 925 return 0;
917} 926}
918 927
@@ -945,12 +954,11 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
945 * nobody does any... 954 * nobody does any...
946 */ 955 */
947 compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); 956 compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
948 return (int)regs->result;
949#else 957#else
950 do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); 958 do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
951 sigreturn_exit(regs); /* doesn't return here */
952 return 0;
953#endif 959#endif
960 set_thread_flag(TIF_RESTOREALL);
961 return 0;
954 962
955 bad: 963 bad:
956 force_sig(SIGSEGV, current); 964 force_sig(SIGSEGV, current);
@@ -1041,9 +1049,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
1041 */ 1049 */
1042 do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); 1050 do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
1043 1051
1044 sigreturn_exit(regs); 1052 set_thread_flag(TIF_RESTOREALL);
1045 /* doesn't actually return back to here */
1046
1047 out: 1053 out:
1048 return 0; 1054 return 0;
1049} 1055}
@@ -1107,12 +1113,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
1107 regs->gpr[4] = (unsigned long) sc; 1113 regs->gpr[4] = (unsigned long) sc;
1108 regs->nip = (unsigned long) ka->sa.sa_handler; 1114 regs->nip = (unsigned long) ka->sa.sa_handler;
1109 regs->trap = 0; 1115 regs->trap = 0;
1110#ifdef CONFIG_PPC64
1111 regs->result = 0;
1112
1113 if (test_thread_flag(TIF_SINGLESTEP))
1114 ptrace_notify(SIGTRAP);
1115#endif
1116 1116
1117 return 1; 1117 return 1;
1118 1118
@@ -1160,12 +1160,8 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
1160 || restore_user_regs(regs, sr, 1)) 1160 || restore_user_regs(regs, sr, 1))
1161 goto badframe; 1161 goto badframe;
1162 1162
1163#ifdef CONFIG_PPC64 1163 set_thread_flag(TIF_RESTOREALL);
1164 return (int)regs->result;
1165#else
1166 sigreturn_exit(regs); /* doesn't return */
1167 return 0; 1164 return 0;
1168#endif
1169 1165
1170badframe: 1166badframe:
1171 force_sig(SIGSEGV, current); 1167 force_sig(SIGSEGV, current);