|
Ivan T. Ivanov |
e55d0f |
From: James Morse <james.morse@arm.com>
|
|
Ivan T. Ivanov |
e55d0f |
Date: Mon, 22 Jul 2019 16:11:48 +0100
|
|
Ivan T. Ivanov |
e55d0f |
Subject: arm64: entry: SP Alignment Fault doesn't write to FAR_EL1
|
|
Ivan T. Ivanov |
e55d0f |
Git-commit: 40ca0ce56d4bb889dc43b455c55398468115569a
|
|
Ivan T. Ivanov |
e55d0f |
Patch-mainline: v5.3-rc2
|
|
Ivan T. Ivanov |
e55d0f |
References: git-fixes
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
Comparing the arm-arm's pseudocode for AArch64.PCAlignmentFault() with
|
|
Ivan T. Ivanov |
e55d0f |
AArch64.SPAlignmentFault() shows that SP faults don't copy the faulty-SP
|
|
Ivan T. Ivanov |
e55d0f |
to FAR_EL1, but this is where we read from, and the address we provide
|
|
Ivan T. Ivanov |
e55d0f |
to user-space with the BUS_ADRALN signal.
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
For user-space this value will be UNKNOWN due to the previous ERET to
|
|
Ivan T. Ivanov |
e55d0f |
user-space. If the last value is preserved, on systems with KASLR or KPTI
|
|
Ivan T. Ivanov |
e55d0f |
this will be the user-space link-register left in FAR_EL1 by tramp_exit().
|
|
Ivan T. Ivanov |
e55d0f |
Fix this to retrieve the original sp_el0 value, and pass this to
|
|
Ivan T. Ivanov |
e55d0f |
do_sp_pc_fault().
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
SP alignment faults from EL1 will cause us to take the fault again when
|
|
Ivan T. Ivanov |
e55d0f |
trying to store the pt_regs. This eventually takes us to the overflow
|
|
Ivan T. Ivanov |
e55d0f |
stack. Remove the ESR_ELx_EC_SP_ALIGN check as we will never make it
|
|
Ivan T. Ivanov |
e55d0f |
this far.
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
Fixes: 60ffc30d5652 ("arm64: Exception handling")
|
|
Ivan T. Ivanov |
e55d0f |
Signed-off-by: James Morse <james.morse@arm.com>
|
|
Ivan T. Ivanov |
e55d0f |
[will: change label name and fleshed out comment]
|
|
Ivan T. Ivanov |
e55d0f |
Signed-off-by: Will Deacon <will@kernel.org>
|
|
Ivan T. Ivanov |
e55d0f |
Acked-by: Ivan T. Ivanov <iivanov@suse.de>
|
|
Ivan T. Ivanov |
e55d0f |
---
|
|
Ivan T. Ivanov |
e55d0f |
arch/arm64/kernel/entry.S | 22 +++++++++++++---------
|
|
Ivan T. Ivanov |
e55d0f |
1 file changed, 13 insertions(+), 9 deletions(-)
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
--- a/arch/arm64/kernel/entry.S
|
|
Ivan T. Ivanov |
e55d0f |
+++ b/arch/arm64/kernel/entry.S
|
|
Ivan T. Ivanov |
e55d0f |
@@ -568,10 +568,8 @@ el1_sync:
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el1_ia
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el1_undef
|
|
Ivan T. Ivanov |
e55d0f |
- cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
|
|
Ivan T. Ivanov |
e55d0f |
- b.eq el1_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
|
|
Ivan T. Ivanov |
e55d0f |
- b.eq el1_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
+ b.eq el1_pc
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el1_undef
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
|
|
Ivan T. Ivanov |
e55d0f |
@@ -593,9 +591,11 @@ el1_da:
|
|
Ivan T. Ivanov |
e55d0f |
bl do_mem_abort
|
|
Ivan T. Ivanov |
e55d0f |
|
|
Ivan T. Ivanov |
e55d0f |
kernel_exit 1
|
|
Ivan T. Ivanov |
e55d0f |
-el1_sp_pc:
|
|
Ivan T. Ivanov |
e55d0f |
+el1_pc:
|
|
Ivan T. Ivanov |
e55d0f |
/*
|
|
Ivan T. Ivanov |
e55d0f |
- * Stack or PC alignment exception handling
|
|
Ivan T. Ivanov |
e55d0f |
+ * PC alignment exception handling. We don't handle SP alignment faults,
|
|
Ivan T. Ivanov |
e55d0f |
+ * since we will have hit a recursive exception when trying to push the
|
|
Ivan T. Ivanov |
e55d0f |
+ * initial pt_regs.
|
|
Ivan T. Ivanov |
e55d0f |
*/
|
|
Ivan T. Ivanov |
e55d0f |
mrs x0, far_el1
|
|
Ivan T. Ivanov |
e55d0f |
inherit_daif pstate=x23, tmp=x2
|
|
Ivan T. Ivanov |
e55d0f |
@@ -687,9 +687,9 @@ el0_sync:
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el0_sys
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
|
|
Ivan T. Ivanov |
e55d0f |
- b.eq el0_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
+ b.eq el0_sp
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
|
|
Ivan T. Ivanov |
e55d0f |
- b.eq el0_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
+ b.eq el0_pc
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el0_undef
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
|
|
Ivan T. Ivanov |
e55d0f |
@@ -713,7 +713,7 @@ el0_sync_compat:
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el0_fpsimd_exc
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
|
|
Ivan T. Ivanov |
e55d0f |
- b.eq el0_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
+ b.eq el0_pc
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
|
|
Ivan T. Ivanov |
e55d0f |
b.eq el0_undef
|
|
Ivan T. Ivanov |
e55d0f |
cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
|
|
Ivan T. Ivanov |
e55d0f |
@@ -817,11 +817,15 @@ el0_fpsimd_exc:
|
|
Ivan T. Ivanov |
e55d0f |
mov x1, sp
|
|
Ivan T. Ivanov |
e55d0f |
bl do_fpsimd_exc
|
|
Ivan T. Ivanov |
e55d0f |
b ret_to_user
|
|
Ivan T. Ivanov |
e55d0f |
+el0_sp:
|
|
Ivan T. Ivanov |
e55d0f |
+ ldr x26, [sp, #S_SP]
|
|
Ivan T. Ivanov |
e55d0f |
+ b el0_sp_pc
|
|
Ivan T. Ivanov |
e55d0f |
+el0_pc:
|
|
Ivan T. Ivanov |
e55d0f |
+ mrs x26, far_el1
|
|
Ivan T. Ivanov |
e55d0f |
el0_sp_pc:
|
|
Ivan T. Ivanov |
e55d0f |
/*
|
|
Ivan T. Ivanov |
e55d0f |
* Stack or PC alignment exception handling
|
|
Ivan T. Ivanov |
e55d0f |
*/
|
|
Ivan T. Ivanov |
e55d0f |
- mrs x26, far_el1
|
|
Ivan T. Ivanov |
e55d0f |
enable_da_f
|
|
Ivan T. Ivanov |
e55d0f |
#ifdef CONFIG_TRACE_IRQFLAGS
|
|
Ivan T. Ivanov |
e55d0f |
bl trace_hardirqs_off
|