summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/traps.c')
-rw-r--r--arch/arm64/kernel/traps.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 4e3e9d9c8151..ace993b5664c 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -426,6 +426,34 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
uaccess_ttbr0_disable(); \
}
+#define __user_cache_maint_ivau(insn, address, res) \
+ do { \
+ if (address >= user_addr_max()) { \
+ res = -EFAULT; \
+ } else { \
+ uaccess_ttbr0_enable(); \
+ asm volatile ( \
+ "1: " insn "\n" \
+ " mov %w0, #0\n" \
+ "2:\n" \
+ " .pushsection .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "3: mov %w0, %w2\n" \
+ " b 2b\n" \
+ " .popsection\n" \
+ _ASM_EXTABLE(1b, 3b) \
+ : "=r" (res) \
+ : "r" (address), "i" (-EFAULT)); \
+ uaccess_ttbr0_disable(); \
+ } \
+ } while (0)
+
+#ifdef CONFIG_IMX_SCU_SOC
+extern bool TKT340553_SW_WORKAROUND;
+#else
+#define TKT340553_SW_WORKAROUND 0
+#endif
+
static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
{
unsigned long address;
@@ -452,7 +480,10 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
__user_cache_maint("dc civac", address, ret);
break;
case ESR_ELx_SYS64_ISS_CRM_IC_IVAU: /* IC IVAU */
- __user_cache_maint("ic ivau", address, ret);
+ if (TKT340553_SW_WORKAROUND)
+ __user_cache_maint_ivau("ic ialluis", address, ret);
+ else
+ __user_cache_maint("ic ivau", address, ret);
break;
default:
force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc);