SP needs to be 16-bytes aligned before accessing memory through it. When handling exceptions from EL2, there is no guarantee that SP is already aligned.
Ensure SP is aligned upon entries from EL2. Signed-off-by: Julien Thierry <julien.thie...@arm.com> Cc: kvmarm@lists.cs.columbia.edu --- arch/arm64/kvm/hyp/hyp-entry.S | 63 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index da31386..f611072 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -184,6 +184,10 @@ el2_error: ccmp x0, x1, #4, ne b.ne __hyp_panic mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT) + + /* Restore the stack */ + ldr x1, [sp] + mov sp, x1 eret ENTRY(__hyp_do_panic) @@ -221,29 +225,66 @@ ENDPROC(\label) .align 11 -.macro valid_vect target +/* + * Aligns the stack and stores the old sp value. This is what the stack + * looks like after this code: + * + * +--------+ + * | | + * |--------|--> old_sp (upon entry) + * | x1 |--> (only used for local save/restore) + * |--------|--> old_sp - 8 + * | |--> padding + * |--------|--> aligned_sp + 8 + * | old_sp | + * |--------|--> sp = aligned_sp + * | | + * +--------+ + */ +.macro align_sp_el2 + xchg_sp x0 + str x1, [x0, #-8] // save x1 + mov x1, x0 // x1 = old_sp + sub x0, x0, #0x10 // save space for x1 + old_sp + bic x0, x0, #0xf // align down to 16-bytes + xchg_sp x0 + str x1, [sp] // save old_sp + ldr x1, [x1, #-8] +.endm + +.macro valid_vect target, el=1 .align 7 + .if \el == 2 + align_sp_el2 + .endif + stp x0, x1, [sp, #-16]! b \target .endm -.macro invalid_vect target +.macro invalid_vect target, el=1 .align 7 + .if \el == 2 + align_sp_el2 + .endif + b \target + .if \el == 1 ldp x0, x1, [sp], #16 b \target + .endif .endm ENTRY(__kvm_hyp_vector) - invalid_vect el2t_sync_invalid // Synchronous EL2t - invalid_vect el2t_irq_invalid // IRQ EL2t - invalid_vect el2t_fiq_invalid // FIQ EL2t - invalid_vect el2t_error_invalid // Error EL2t - - invalid_vect el2h_sync_invalid // Synchronous EL2h - invalid_vect el2h_irq_invalid // IRQ EL2h - invalid_vect el2h_fiq_invalid // FIQ EL2h - valid_vect el2_error // Error EL2h + invalid_vect el2t_sync_invalid, 2 // Synchronous EL2t + invalid_vect el2t_irq_invalid, 2 // IRQ EL2t + invalid_vect el2t_fiq_invalid, 2 // FIQ EL2t + invalid_vect el2t_error_invalid, 2 // Error EL2t + + invalid_vect el2h_sync_invalid, 2 // Synchronous EL2h + invalid_vect el2h_irq_invalid, 2 // IRQ EL2h + invalid_vect el2h_fiq_invalid, 2 // FIQ EL2h + valid_vect el2_error, 2 // Error EL2h valid_vect el1_sync // Synchronous 64-bit EL1 valid_vect el1_irq // IRQ 64-bit EL1 -- 1.9.1 _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm