|
18 | 18 | #include <asm/switch_to.h> |
19 | 19 | #include <asm/syscall.h> |
20 | 20 | #include <asm/time.h> |
| 21 | +#include <asm/tm.h> |
21 | 22 | #include <asm/unistd.h> |
22 | 23 |
|
23 | 24 | #if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32) |
@@ -136,6 +137,48 @@ notrace long system_call_exception(long r3, long r4, long r5, |
136 | 137 | */ |
137 | 138 | irq_soft_mask_regs_set_state(regs, IRQS_ENABLED); |
138 | 139 |
|
| 140 | + /* |
| 141 | + * If system call is called with TM active, set _TIF_RESTOREALL to |
| 142 | + * prevent RFSCV being used to return to userspace, because POWER9 |
| 143 | + * TM implementation has problems with this instruction returning to |
| 144 | + * transactional state. Final register values are not relevant because |
| 145 | + * the transaction will be aborted upon return anyway. Or in the case |
| 146 | + * of unsupported_scv SIGILL fault, the return state does not much |
| 147 | + * matter because it's an edge case. |
| 148 | + */ |
| 149 | + if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && |
| 150 | + unlikely(MSR_TM_TRANSACTIONAL(regs->msr))) |
| 151 | + current_thread_info()->flags |= _TIF_RESTOREALL; |
| 152 | + |
| 153 | + /* |
| 154 | + * If the system call was made with a transaction active, doom it and |
| 155 | + * return without performing the system call. Unless it was an |
| 156 | + * unsupported scv vector, in which case it's treated like an illegal |
| 157 | + * instruction. |
| 158 | + */ |
| 159 | +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 160 | + if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) && |
| 161 | + !trap_is_unsupported_scv(regs)) { |
| 162 | + /* Enable TM in the kernel, and disable EE (for scv) */ |
| 163 | + hard_irq_disable(); |
| 164 | + mtmsr(mfmsr() | MSR_TM); |
| 165 | + |
| 166 | + /* tabort, this dooms the transaction, nothing else */ |
| 167 | + asm volatile(".long 0x7c00071d | ((%0) << 16)" |
| 168 | + :: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)); |
| 169 | + |
| 170 | + /* |
| 171 | + * Userspace will never see the return value. Execution will |
| 172 | + * resume after the tbegin. of the aborted transaction with the |
| 173 | + * checkpointed register state. A context switch could occur |
| 174 | + * or signal delivered to the process before resuming the |
| 175 | + * doomed transaction context, but that should all be handled |
| 176 | + * as expected. |
| 177 | + */ |
| 178 | + return -ENOSYS; |
| 179 | + } |
| 180 | +#endif // CONFIG_PPC_TRANSACTIONAL_MEM |
| 181 | + |
139 | 182 | local_irq_enable(); |
140 | 183 |
|
141 | 184 | if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) { |
|
0 commit comments