diff options
| -rw-r--r-- | arch/arm64/kernel/process.c | 18 | ||||
| -rw-r--r-- | arch/arm64/kernel/sys_compat.c | 6 |
2 files changed, 24 insertions, 0 deletions
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 1309d64aa926..29d48690f2ac 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
| @@ -230,9 +230,27 @@ void exit_thread(void) | |||
| 230 | { | 230 | { |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static void tls_thread_flush(void) | ||
| 234 | { | ||
| 235 | asm ("msr tpidr_el0, xzr"); | ||
| 236 | |||
| 237 | if (is_compat_task()) { | ||
| 238 | current->thread.tp_value = 0; | ||
| 239 | |||
| 240 | /* | ||
| 241 | * We need to ensure ordering between the shadow state and the | ||
| 242 | * hardware state, so that we don't corrupt the hardware state | ||
| 243 | * with a stale shadow state during context switch. | ||
| 244 | */ | ||
| 245 | barrier(); | ||
| 246 | asm ("msr tpidrro_el0, xzr"); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 233 | void flush_thread(void) | 250 | void flush_thread(void) |
| 234 | { | 251 | { |
| 235 | fpsimd_flush_thread(); | 252 | fpsimd_flush_thread(); |
| 253 | tls_thread_flush(); | ||
| 236 | flush_ptrace_hw_breakpoint(current); | 254 | flush_ptrace_hw_breakpoint(current); |
| 237 | } | 255 | } |
| 238 | 256 | ||
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index de2b0226e06d..dc47e53e9e28 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c | |||
| @@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs) | |||
| 79 | 79 | ||
| 80 | case __ARM_NR_compat_set_tls: | 80 | case __ARM_NR_compat_set_tls: |
| 81 | current->thread.tp_value = regs->regs[0]; | 81 | current->thread.tp_value = regs->regs[0]; |
| 82 | |||
| 83 | /* | ||
| 84 | * Protect against register corruption from context switch. | ||
| 85 | * See comment in tls_thread_flush. | ||
| 86 | */ | ||
| 87 | barrier(); | ||
| 82 | asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); | 88 | asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); |
| 83 | return 0; | 89 | return 0; |
| 84 | 90 | ||
