diff options
Diffstat (limited to 'arch/arm64/kernel/syscall.c')
| -rw-r--r-- | arch/arm64/kernel/syscall.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 5610ac01c1ec..871c739f060a 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/syscalls.h> | 8 | #include <linux/syscalls.h> |
| 9 | 9 | ||
| 10 | #include <asm/daifflags.h> | 10 | #include <asm/daifflags.h> |
| 11 | #include <asm/debug-monitors.h> | ||
| 11 | #include <asm/fpsimd.h> | 12 | #include <asm/fpsimd.h> |
| 12 | #include <asm/syscall.h> | 13 | #include <asm/syscall.h> |
| 13 | #include <asm/thread_info.h> | 14 | #include <asm/thread_info.h> |
| @@ -60,6 +61,35 @@ static inline bool has_syscall_work(unsigned long flags) | |||
| 60 | int syscall_trace_enter(struct pt_regs *regs); | 61 | int syscall_trace_enter(struct pt_regs *regs); |
| 61 | void syscall_trace_exit(struct pt_regs *regs); | 62 | void syscall_trace_exit(struct pt_regs *regs); |
| 62 | 63 | ||
| 64 | #ifdef CONFIG_ARM64_ERRATUM_1463225 | ||
| 65 | DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); | ||
| 66 | |||
| 67 | static void cortex_a76_erratum_1463225_svc_handler(void) | ||
| 68 | { | ||
| 69 | u32 reg, val; | ||
| 70 | |||
| 71 | if (!unlikely(test_thread_flag(TIF_SINGLESTEP))) | ||
| 72 | return; | ||
| 73 | |||
| 74 | if (!unlikely(this_cpu_has_cap(ARM64_WORKAROUND_1463225))) | ||
| 75 | return; | ||
| 76 | |||
| 77 | __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 1); | ||
| 78 | reg = read_sysreg(mdscr_el1); | ||
| 79 | val = reg | DBG_MDSCR_SS | DBG_MDSCR_KDE; | ||
| 80 | write_sysreg(val, mdscr_el1); | ||
| 81 | asm volatile("msr daifclr, #8"); | ||
| 82 | isb(); | ||
| 83 | |||
| 84 | /* We will have taken a single-step exception by this point */ | ||
| 85 | |||
| 86 | write_sysreg(reg, mdscr_el1); | ||
| 87 | __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 0); | ||
| 88 | } | ||
| 89 | #else | ||
| 90 | static void cortex_a76_erratum_1463225_svc_handler(void) { } | ||
| 91 | #endif /* CONFIG_ARM64_ERRATUM_1463225 */ | ||
| 92 | |||
| 63 | static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, | 93 | static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, |
| 64 | const syscall_fn_t syscall_table[]) | 94 | const syscall_fn_t syscall_table[]) |
| 65 | { | 95 | { |
| @@ -68,6 +98,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, | |||
| 68 | regs->orig_x0 = regs->regs[0]; | 98 | regs->orig_x0 = regs->regs[0]; |
| 69 | regs->syscallno = scno; | 99 | regs->syscallno = scno; |
| 70 | 100 | ||
| 101 | cortex_a76_erratum_1463225_svc_handler(); | ||
| 71 | local_daif_restore(DAIF_PROCCTX); | 102 | local_daif_restore(DAIF_PROCCTX); |
| 72 | user_exit(); | 103 | user_exit(); |
| 73 | 104 | ||
