arm64: adjust el0_sync so that a function can be called
authorLarry Bassel <larry.bassel@linaro.org>
Fri, 30 May 2014 19:34:14 +0000 (20:34 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 10 Jul 2014 09:10:20 +0000 (10:10 +0100)
To implement the context tracker properly on arm64,
a function call needs to be made after debugging and
interrupts are turned on, but before the lr is changed
to point to ret_to_user(). If the function call
is made after the lr is changed the function will not
return to the correct place.

For similar reasons, defer the setting of x0 so that
it doesn't need to be saved around the function call
(save far_el1 in x26 temporarily instead).

Acked-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Larry Bassel <larry.bassel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/entry.S

index 9ce04ba6bcb0f0c99ce28e999af0de00868a5765..d7230bf68ad155144fef43e746de89ce72969e11 100644 (file)
@@ -353,7 +353,6 @@ el0_sync:
        lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
        cmp     x24, #ESR_EL1_EC_SVC64          // SVC in 64-bit state
        b.eq    el0_svc
-       adr     lr, ret_to_user
        cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
        b.eq    el0_da
        cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
@@ -382,7 +381,6 @@ el0_sync_compat:
        lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
        cmp     x24, #ESR_EL1_EC_SVC32          // SVC in 32-bit state
        b.eq    el0_svc_compat
-       adr     lr, ret_to_user
        cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
        b.eq    el0_da
        cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
@@ -425,22 +423,25 @@ el0_da:
        /*
         * Data abort handling
         */
-       mrs     x0, far_el1
-       bic     x0, x0, #(0xff << 56)
+       mrs     x26, far_el1
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
+       bic     x0, x26, #(0xff << 56)
        mov     x1, x25
        mov     x2, sp
+       adr     lr, ret_to_user
        b       do_mem_abort
 el0_ia:
        /*
         * Instruction abort handling
         */
-       mrs     x0, far_el1
+       mrs     x26, far_el1
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
+       mov     x0, x26
        orr     x1, x25, #1 << 24               // use reserved ISS bit for instruction aborts
        mov     x2, sp
+       adr     lr, ret_to_user
        b       do_mem_abort
 el0_fpsimd_acc:
        /*
@@ -449,6 +450,7 @@ el0_fpsimd_acc:
        enable_dbg
        mov     x0, x25
        mov     x1, sp
+       adr     lr, ret_to_user
        b       do_fpsimd_acc
 el0_fpsimd_exc:
        /*
@@ -457,16 +459,19 @@ el0_fpsimd_exc:
        enable_dbg
        mov     x0, x25
        mov     x1, sp
+       adr     lr, ret_to_user
        b       do_fpsimd_exc
 el0_sp_pc:
        /*
         * Stack or PC alignment exception handling
         */
-       mrs     x0, far_el1
+       mrs     x26, far_el1
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
+       mov     x0, x26
        mov     x1, x25
        mov     x2, sp
+       adr     lr, ret_to_user
        b       do_sp_pc_abort
 el0_undef:
        /*
@@ -475,6 +480,7 @@ el0_undef:
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
        mov     x0, sp
+       adr     lr, ret_to_user
        b       do_undefinstr
 el0_dbg:
        /*
@@ -492,6 +498,7 @@ el0_inv:
        mov     x0, sp
        mov     x1, #BAD_SYNC
        mrs     x2, esr_el1
+       adr     lr, ret_to_user
        b       bad_mode
 ENDPROC(el0_sync)