summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/aarch64/aarch64-exception-default.S
diff options
context:
space:
mode:
authorKinsey Moore <kinsey.moore@oarcorp.com>2020-09-22 08:31:34 -0500
committerJoel Sherrill <joel@rtems.org>2020-10-05 16:11:39 -0500
commit8387c52e476e18c42d5f3986e01cbb1916f13a2c (patch)
treeca9219330ea133ec66de05c7fe56fa59903ec3ad /cpukit/score/cpu/aarch64/aarch64-exception-default.S
parentspmsgq_err01: Use correct max values and fix 64bit (diff)
downloadrtems-8387c52e476e18c42d5f3986e01cbb1916f13a2c.tar.bz2
score: Add AArch64 port
This adds a CPU port for AArch64(ARMv8) with support for exceptions and interrupts.
Diffstat (limited to 'cpukit/score/cpu/aarch64/aarch64-exception-default.S')
-rw-r--r--cpukit/score/cpu/aarch64/aarch64-exception-default.S488
1 files changed, 488 insertions, 0 deletions
diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-default.S b/cpukit/score/cpu/aarch64/aarch64-exception-default.S
new file mode 100644
index 0000000000..3d311df280
--- /dev/null
+++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.S
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreCPUAArch64
+ *
+ * @brief Implementation of AArch64 exception vector table.
+ *
+ * This file implements the AArch64 exception vector table and its embedded
+ * jump handlers along with the code necessary to call higher level C handlers.
+ */
+
+/*
+ * Copyright (C) 2020 On-Line Applications Research Corporation (OAR)
+ * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/asm.h>
+
+.extern _AArch64_Exception_default
+
+.globl bsp_start_vector_table_begin
+.globl bsp_start_vector_table_end
+.globl bsp_start_vector_table_size
+.globl bsp_vector_table_size
+
+.section ".text"
+
+/*
+ * This is the exception vector table and the pointers to the default
+ * exceptions handlers.
+ */
+
+/*
+ * TODO(kmoore) The current implementation here assumes that SP is not
+ * misaligned.
+ */
+ .macro JUMP_HANDLER
+/* Mask to use in BIC, lower 7 bits */
+ mov x0, #0x7f
+/* LR contains PC, mask off to the base of the current vector */
+ bic x0, lr, x0
+/* Load address from the last word in the vector */
+ ldr x0, [x0, #0x78]
+/*
+ * Branch and link to the address in x0. There is no reason to save the current
+ * LR since it has already been saved and the current contents are junk.
+ */
+ blr x0
+/* Pop x0,lr from stack */
+ ldp x0, lr, [sp], #16
+/* Return from exception */
+ eret
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ .endm
+
+ .macro JUMP_TARGET_SP0
+/* Takes up the space of 2 instructions */
+#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
+ .word .print_exception_dump_sp0
+ .word 0x0
+#else
+ .dword .print_exception_dump_sp0
+#endif
+ .endm
+
+ .macro JUMP_TARGET_SPx
+/* Takes up the space of 2 instructions */
+#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
+ .word .print_exception_dump_spx
+ .word 0x0
+#else
+ .dword .print_exception_dump_spx
+#endif
+ .endm
+
+bsp_start_vector_table_begin:
+.balign 0x800
+Vector_table_el3:
+/*
+ * The exception handler for synchronous exceptions from the current EL
+ * using SP0.
+ */
+curr_el_sp0_sync:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_sp0_sync_get_pc /* Get current execution address */
+curr_el_sp0_sync_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SP0
+.balign 0x80
+/* The exception handler for IRQ exceptions from the current EL using SP0. */
+curr_el_sp0_irq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_sp0_irq_get_pc /* Get current execution address */
+curr_el_sp0_irq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SP0
+.balign 0x80
+/* The exception handler for FIQ exceptions from the current EL using SP0. */
+curr_el_sp0_fiq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_sp0_fiq_get_pc /* Get current execution address */
+curr_el_sp0_fiq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SP0
+.balign 0x80
+/*
+ * The exception handler for system error exceptions from the current EL using
+ * SP0.
+ */
+curr_el_sp0_serror:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_sp0_serror_get_pc /* Get current execution address */
+curr_el_sp0_serror_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SP0
+.balign 0x80
+/*
+ * The exception handler for synchronous exceptions from the current EL using
+ * the current SP.
+ */
+curr_el_spx_sync:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_spx_sync_get_pc /* Get current execution address */
+curr_el_spx_sync_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for IRQ exceptions from the current EL using the
+ * current SP.
+ */
+curr_el_spx_irq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_spx_irq_get_pc /* Get current execution address */
+curr_el_spx_irq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for FIQ exceptions from the current EL using the
+ * current SP.
+ */
+curr_el_spx_fiq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_spx_fiq_get_pc /* Get current execution address */
+curr_el_spx_fiq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for system error exceptions from the current EL using
+ * the current SP.
+ */
+curr_el_spx_serror:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl curr_el_spx_serror_get_pc /* Get current execution address */
+curr_el_spx_serror_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for synchronous exceptions from a lower EL (AArch64).
+ */
+lower_el_aarch64_sync:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch64_sync_get_pc /* Get current execution address */
+lower_el_aarch64_sync_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/* The exception handler for IRQ exceptions from a lower EL (AArch64). */
+lower_el_aarch64_irq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch64_irq_get_pc /* Get current execution address */
+lower_el_aarch64_irq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/* The exception handler for FIQ exceptions from a lower EL (AArch64). */
+lower_el_aarch64_fiq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch64_fiq_get_pc /* Get current execution address */
+lower_el_aarch64_fiq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for system error exceptions from a lower EL(AArch64).
+ */
+lower_el_aarch64_serror:
+/* Push x0,lr on to the stack */
+ stp x0, lr, [sp, #-16]!
+/* Get current execution address */
+ bl lower_el_aarch64_serror_get_pc
+lower_el_aarch64_serror_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for the synchronous exception from a lower EL(AArch32).
+ */
+lower_el_aarch32_sync:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch32_sync_get_pc /* Get current execution address */
+lower_el_aarch32_sync_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/* The exception handler for the IRQ exception from a lower EL (AArch32). */
+lower_el_aarch32_irq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch32_irq_get_pc /* Get current execution address */
+lower_el_aarch32_irq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/* The exception handler for the FIQ exception from a lower EL (AArch32). */
+lower_el_aarch32_fiq:
+ stp x0, lr, [sp, #-16]! /* Push x0,lr on to the stack */
+ bl lower_el_aarch32_fiq_get_pc /* Get current execution address */
+lower_el_aarch32_fiq_get_pc: /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+.balign 0x80
+/*
+ * The exception handler for the system error exception from a lower EL
+ * (AArch32).
+ */
+lower_el_aarch32_serror:
+/* Push x0,lr on to the stack */
+ stp x0, lr, [sp, #-16]!
+/* Get current execution address */
+ bl lower_el_aarch32_serror_get_pc
+lower_el_aarch32_serror_get_pc : /* The current PC is now in LR */
+ JUMP_HANDLER
+ JUMP_TARGET_SPx
+
+bsp_start_vector_table_end:
+
+ .set bsp_start_vector_table_size, bsp_start_vector_table_end - bsp_start_vector_table_begin
+ .set bsp_vector_table_size, bsp_start_vector_table_size
+
+/*
+ * This involves switching a few things around. the real x0 and lr are on SPx
+ * and need to be retrieved while the lr upon entry contains the pointer into
+ * the AArch64 vector table
+ */
+.print_exception_dump_spx:
+/* Switch to exception stack (SP0) */
+ msr spsel, #0
+/* Save space for exception context */
+ sub sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE
+/*
+ * Push exception vector, LR currently points into the actual exception vector
+ * table
+ */
+ and lr, lr, #0x780
+ lsr lr, lr, #7
+ str lr, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET]
+/* Pop x0,lr from stack, saved by generic handler */
+/*
+ * This modifies the stack pointer back to the pre-vector-handler value which is
+ * safe because this will never return
+ */
+ msr spsel, #1
+ ldp x0, lr, [sp], #16
+ msr spsel, #0
+/* Save LR */
+ str lr, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET]
+/* Push the start of the context */
+ bl .push_exception_context_start
+/* Save original sp in x0 for .push_exception_context_finish */
+ msr spsel, #1
+ mov x0, sp
+ msr spsel, #0
+/* Push the remainder of the context */
+ bl .push_exception_context_finish
+/* Save sp into x0 for handler */
+ mov x0, sp
+/* Jump into the handler */
+ bl _AArch64_Exception_default
+
+ /* Just in case */
+ b twiddle
+
+.print_exception_dump_sp0:
+/* Save space for exception context */
+ sub sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE
+/*
+ * Push exception vector, LR currently points into the actual exception vector
+ */
+ and lr, lr, #0x780
+ lsr lr, lr, #7
+ str lr, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET]
+/* Get x0,lr from stack, saved by generic handler */
+ add sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE
+ ldp x0, lr, [sp]
+ sub sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE
+/* Save LR */
+ str lr, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET]
+/* Push the start of the context */
+ bl .push_exception_context_start
+/* Save original sp in x0 for .push_exception_context_finish */
+ add x0, sp, #(AARCH64_EXCEPTION_FRAME_SIZE + 16)
+/* Push the remainder of the context */
+ bl .push_exception_context_finish
+/* Save sp (exception frame) into x0 for handler */
+ mov x0, sp
+/* Jump into the handler */
+ bl _AArch64_Exception_default
+
+ /* Just in case */
+twiddle:
+ b twiddle
+
+/* Assumes SP is at the base of the context and LR has already been pushed */
+.push_exception_context_start:
+/* Push x0-x29(fp) */
+ stp x0, x1, [sp, #0x00]
+ stp x2, x3, [sp, #0x10]
+ stp x4, x5, [sp, #0x20]
+ stp x6, x7, [sp, #0x30]
+ stp x8, x9, [sp, #0x40]
+ stp x10, x11, [sp, #0x50]
+ stp x12, x13, [sp, #0x60]
+ stp x14, x15, [sp, #0x70]
+ stp x16, x17, [sp, #0x80]
+ stp x18, x19, [sp, #0x90]
+ stp x20, x21, [sp, #0xa0]
+ stp x22, x23, [sp, #0xb0]
+ stp x24, x25, [sp, #0xc0]
+ stp x26, x27, [sp, #0xd0]
+ stp x28, x29, [sp, #0xe0]
+ ret
+
+/* Expects original SP to be stored in x0 */
+.push_exception_context_finish:
+/* Get exception LR for PC */
+ mrs x1, ELR_EL1
+/* Push sp and pc */
+ stp x0, x1, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET]
+/* Get daif and spsr */
+ mrs x0, DAIF
+ mrs x1, SPSR_EL1
+/* Push daif and spsr */
+ stp x0, x1, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET]
+/* Get ESR and FAR */
+ mrs x0, ESR_EL1
+ mrs x1, FAR_EL1
+/* Push FAR and ESR */
+ stp x0, x1, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET]
+/* Get fpcr and fpsr */
+ mrs x0, FPSR
+ mrs x1, FPCR
+/* Push fpcr and fpsr */
+ stp x0, x1, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET]
+/* Push VFP registers */
+ stp q0, q1, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x000)]
+ stp q2, q3, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x020)]
+ stp q4, q5, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x040)]
+ stp q6, q7, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x060)]
+ stp q8, q9, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x080)]
+ stp q10, q11, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0a0)]
+ stp q12, q13, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0c0)]
+ stp q14, q15, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0e0)]
+ stp q16, q17, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x100)]
+ stp q18, q19, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x120)]
+ stp q20, q21, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x140)]
+ stp q22, q23, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x160)]
+ stp q24, q25, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x180)]
+ stp q26, q27, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1a0)]
+ stp q28, q29, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1c0)]
+ stp q30, q31, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1e0)]
+/* Done, return to exception handler */
+ ret
+
+/*
+ * Apply the exception frame to the current register status, SP points to the EF
+ */
+.pop_exception_context_and_ret:
+/* Pop daif and spsr */
+ ldp x2, x3, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET]
+/* Restore daif and spsr */
+ msr DAIF, x2
+ msr SPSR_EL1, x3
+/* Pop FAR and ESR */
+ ldp x2, x3, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET]
+/* Restore ESR and FAR */
+ msr ESR_EL1, x2
+ msr FAR_EL1, x3
+/* Pop fpcr and fpsr */
+ ldp x2, x3, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET]
+/* Restore fpcr and fpsr */
+ msr FPSR, x2
+ msr FPCR, x3
+/* Restore LR */
+ ldr lr, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET]
+/* Pop VFP registers */
+ ldp q0, q1, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x000)]
+ ldp q2, q3, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x020)]
+ ldp q4, q5, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x040)]
+ ldp q6, q7, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x060)]
+ ldp q8, q9, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x080)]
+ ldp q10, q11, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0a0)]
+ ldp q12, q13, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0c0)]
+ ldp q14, q15, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x0e0)]
+ ldp q16, q17, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x100)]
+ ldp q18, q19, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x120)]
+ ldp q20, q21, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x140)]
+ ldp q22, q23, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x160)]
+ ldp q24, q25, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x180)]
+ ldp q26, q27, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1a0)]
+ ldp q28, q29, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1c0)]
+ ldp q30, q31, [sp, #(AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET + 0x1e0)]
+/* Pop x0-x29(fp) */
+ ldp x2, x3, [sp, #0x10]
+ ldp x4, x5, [sp, #0x20]
+ ldp x6, x7, [sp, #0x30]
+ ldp x8, x9, [sp, #0x40]
+ ldp x10, x11, [sp, #0x50]
+ ldp x12, x13, [sp, #0x60]
+ ldp x14, x15, [sp, #0x70]
+ ldp x16, x17, [sp, #0x80]
+ ldp x18, x19, [sp, #0x90]
+ ldp x20, x21, [sp, #0xa0]
+ ldp x22, x23, [sp, #0xb0]
+ ldp x24, x25, [sp, #0xc0]
+ ldp x26, x27, [sp, #0xd0]
+ ldp x28, x29, [sp, #0xe0]
+/* Pop sp (ignored since sp should be shortly restored anyway) and ELR */
+ ldp x0, x1, [sp, #AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET]
+/* Restore exception LR */
+ msr ELR_EL1, x1
+ ldp x0, x1, [sp, #0x00]
+ add sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE
+
+/* We must clear reservations to ensure consistency with atomic operations */
+ clrex
+
+ ret