diff options
author | Paul Mackerras <paulus@samba.org> | 2014-01-29 00:33:56 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-01-29 00:58:49 -0500 |
commit | d765ff23e3181413fb1bed090c8d702165448a84 (patch) | |
tree | bc0a4f69042b3e7875b11111970e28072c70b179 | |
parent | 67bfa0ee6691f62d5e2d9602d032a19716fe7b34 (diff) |
powerpc: Fix 32-bit frames for signals delivered when transactional
Commit d31626f70b61 ("powerpc: Don't corrupt transactional state when
using FP/VMX in kernel") introduced a bug where the uc_link and uc_regs
fields of the ucontext_t that is created to hold the transactional
values of the registers in a 32-bit signal frame didn't get set
correctly. The reason is that we now clear the MSR_TS bits in the MSR
in save_tm_user_regs(), before the code that sets uc_link and uc_regs.
To fix this, we move the setting of uc_link and uc_regs into the same
if statement that selects whether to call save_tm_user_regs() or
save_user_regs().
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 6ce69e6f1fcb..a67e00aa3caa 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -1022,29 +1022,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1022 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1022 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1023 | tm_frame = &rt_sf->uc_transact.uc_mcontext; | 1023 | tm_frame = &rt_sf->uc_transact.uc_mcontext; |
1024 | if (MSR_TM_ACTIVE(regs->msr)) { | 1024 | if (MSR_TM_ACTIVE(regs->msr)) { |
1025 | if (__put_user((unsigned long)&rt_sf->uc_transact, | ||
1026 | &rt_sf->uc.uc_link) || | ||
1027 | __put_user((unsigned long)tm_frame, | ||
1028 | &rt_sf->uc_transact.uc_regs)) | ||
1029 | goto badframe; | ||
1025 | if (save_tm_user_regs(regs, frame, tm_frame, sigret)) | 1030 | if (save_tm_user_regs(regs, frame, tm_frame, sigret)) |
1026 | goto badframe; | 1031 | goto badframe; |
1027 | } | 1032 | } |
1028 | else | 1033 | else |
1029 | #endif | 1034 | #endif |
1030 | { | 1035 | { |
1036 | if (__put_user(0, &rt_sf->uc.uc_link)) | ||
1037 | goto badframe; | ||
1031 | if (save_user_regs(regs, frame, tm_frame, sigret, 1)) | 1038 | if (save_user_regs(regs, frame, tm_frame, sigret, 1)) |
1032 | goto badframe; | 1039 | goto badframe; |
1033 | } | 1040 | } |
1034 | regs->link = tramp; | 1041 | regs->link = tramp; |
1035 | 1042 | ||
1036 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1037 | if (MSR_TM_ACTIVE(regs->msr)) { | ||
1038 | if (__put_user((unsigned long)&rt_sf->uc_transact, | ||
1039 | &rt_sf->uc.uc_link) | ||
1040 | || __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs)) | ||
1041 | goto badframe; | ||
1042 | } | ||
1043 | else | ||
1044 | #endif | ||
1045 | if (__put_user(0, &rt_sf->uc.uc_link)) | ||
1046 | goto badframe; | ||
1047 | |||
1048 | current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ | 1043 | current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ |
1049 | 1044 | ||
1050 | /* create a stack frame for the caller of the handler */ | 1045 | /* create a stack frame for the caller of the handler */ |