diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 68 |
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 | ||
182 | extern 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 | ||
186 | static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set) | 191 | static 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, | |||
214 | static inline int save_general_regs(struct pt_regs *regs, | 219 | static 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(®s->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 { | |||
391 | static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | 409 | static 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 | ||
839 | badframe: | 848 | badframe: |
@@ -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 | ||
1170 | badframe: | 1166 | badframe: |
1171 | force_sig(SIGSEGV, current); | 1167 | force_sig(SIGSEGV, current); |