[PATCH v1 2/3] aarch64: Add support for mapping exceptions

Kinsey Moore kinsey.moore at oarcorp.com
Wed Apr 14 15:46:59 UTC 2021


This adds support for mapping AArch64 machine exceptions to POSIX
signals as necessary for running Ada applications.
---
 bsps/aarch64/shared/exceptions.c              |  89 +++++++++++++++
 .../cpu/aarch64/aarch64-exception-default.S   |  81 ++-----------
 .../cpu/aarch64/aarch64-exception-interrupt.S | 106 +-----------------
 .../score/cpu/aarch64/aarch64-exception-map.S |  90 +++++++++++++++
 cpukit/score/cpu/aarch64/include/rtems/asm.h  |  97 ++++++++++++++++
 .../cpu/aarch64/include/rtems/score/cpu.h     |   5 +
 spec/build/bsps/aarch64/grp.yml               |   4 +-
 spec/build/bsps/aarch64/objexceptions.yml     |  14 +++
 spec/build/cpukit/cpuaarch64.yml              |   1 +
 9 files changed, 313 insertions(+), 174 deletions(-)
 create mode 100644 bsps/aarch64/shared/exceptions.c
 create mode 100644 cpukit/score/cpu/aarch64/aarch64-exception-map.S
 create mode 100644 spec/build/bsps/aarch64/objexceptions.yml

diff --git a/bsps/aarch64/shared/exceptions.c b/bsps/aarch64/shared/exceptions.c
new file mode 100644
index 0000000000..808a3bf62a
--- /dev/null
+++ b/bsps/aarch64/shared/exceptions.c
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSBSPsAArch64Shared
+ *
+ * @brief AArch64 machine exception to POSIX signal mapping.
+ */
+
+/*
+ * Copyright (C) 2020 On-Line Applications Research Corporation (OAR)
+ * Written by Kinsey Moore <kinsey.moore at 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.
+ */
+
+#include <unistd.h> /* getpid */
+
+#include <bsp.h>
+#include <rtems/bspIo.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <rtems/exceptions.h>
+
+/*
+ * Synchronous trap handler. Map the trap number of SIGFPE, SIGSEGV
+ * or SIGILL to generate the corresponding Ada exception.
+ */
+#include <bsp/utility.h>
+
+#define ESR_EC_GET(reg) BSP_FLD64GET(reg, 26, 31)
+
+void AArch64_map_exception( uint64_t syndrome )
+{
+  uint32_t         signal;
+  uint64_t EC = ESR_EC_GET(syndrome);
+
+  switch (EC)
+    {
+    case 0x28:			/* FPU exception */
+    case 0x2c:			/* FPU exception */
+    case 0x0A:			/* tagged arithmetic overflow */
+    case 0x82:			/* divide by zero */
+      signal = SIGFPE;
+      break;
+    case 0x20:			/* Data abort */
+    case 0x21:			/* Data abort */
+    case 0x24:			/* Instruction abort */
+    case 0x25:			/* Instruction abort */
+      signal = SIGSEGV;
+      break;
+    default:			/* Anything else ... */
+      /*
+       * Covers unknown, trapped instructions including SVC, illegal execution
+       * state, PC or SP alignment faults, debugging exceptions, etc. */
+      signal = SIGILL;
+      break;
+    }
+  kill(getpid(), signal);
+}
+
+void
+_Exception_initialize_signal_mapping(void)
+{
+  AArch64_set_exception_handler(
+    AARCH64_EXCEPTION_SPx_SYNCHRONOUS,
+    _AArch64_Exception_synchronous_map
+  );
+}
diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-default.S b/cpukit/score/cpu/aarch64/aarch64-exception-default.S
index d139fdc6a4..047eab984c 100644
--- a/cpukit/score/cpu/aarch64/aarch64-exception-default.S
+++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.S
@@ -49,6 +49,8 @@
 .globl	bsp_start_vector_table_end
 .globl	bsp_start_vector_table_size
 .globl	bsp_vector_table_size
+.globl	_AArch64_push_exception_context_start
+.globl	_AArch64_push_exception_context_finish
 
 .section ".text"
 
@@ -337,13 +339,13 @@ bsp_start_vector_table_end:
 /* 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 */
+	bl _AArch64_push_exception_context_start
+/* Save original sp in x0 for _AArch64_push_exception_context_finish */
 	msr spsel, #1
 	mov x0, sp
 	msr spsel, #0
 /* Push the remainder of the context */
-	bl .push_exception_context_finish
+	bl _AArch64_push_exception_context_finish
 /* Save sp into x0 for handler */
 	mov x0, sp
 /* Jump into the handler */
@@ -368,11 +370,11 @@ bsp_start_vector_table_end:
 /* 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 */
+	bl _AArch64_push_exception_context_start
+/* Save original sp in x0 for _AArch64_push_exception_context_finish */
 	add x0, sp, #(AARCH64_EXCEPTION_FRAME_SIZE + 0x10)
 /* Push the remainder of the context */
-	bl .push_exception_context_finish
+	bl _AArch64_push_exception_context_finish
 /* Save sp (exception frame) into x0 for handler */
 	mov x0, sp
 /* Jump into the handler */
@@ -383,7 +385,7 @@ twiddle:
 	b	twiddle
 
 /* Assumes SP is at the base of the context and LR has already been pushed */
-.push_exception_context_start:
+_AArch64_push_exception_context_start:
 /* Push x0-x29(fp) */
 	stp x0,  x1,  [sp, #0x00]
 	stp x2,  x3,  [sp, #0x10]
@@ -403,7 +405,7 @@ twiddle:
 	ret
 
 /* Expects original SP to be stored in x0 */
-.push_exception_context_finish:
+_AArch64_push_exception_context_finish:
 /* Get exception LR for PC */
 	mrs x1, ELR_EL1
 /* Push sp and pc */
@@ -443,67 +445,4 @@ twiddle:
 /* 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
diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S b/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S
index cb0954a29b..2def18bef7 100644
--- a/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S
+++ b/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S
@@ -45,6 +45,7 @@
 
 .globl	_AArch64_Exception_interrupt_no_nest
 .globl	_AArch64_Exception_interrupt_nest
+.globl	_AArch64_Perform_Thread_Dispatch
 
 #ifdef AARCH64_MULTILIB_ARCH_V8_ILP32
   #define SELF_CPU_CONTROL_GET_REG w19
@@ -106,7 +107,7 @@
 /* NOTE: This function does not follow the AArch64 procedure call specification
  * because all relevant state is known to be saved in the interrupt context,
  * hence the blind usage of x19, x20, and x21 */
-.AArch64_Perform_Thread_Dispatch:
+_AArch64_Perform_Thread_Dispatch:
 /* Get per-CPU control of current processor */
 	GET_SELF_CPU_CONTROL	SELF_CPU_CONTROL_GET_REG
 
@@ -125,9 +126,7 @@
 
 /* Call _Thread_Do_dispatch(), this function will enable interrupts */
 	mov	x0, SELF_CPU_CONTROL
-	mov	x1, NON_VOLATILE_SCRATCH
-	mov	x2, #0x80
-	bic	x1, x1, x2
+	mov	x1, #0x0
 	bl	_Thread_Do_dispatch
 
 /* Restore LR */
@@ -152,103 +151,6 @@
 /* Return from thread dispatch */
 	ret
 
-/*
- * Must save corruptible registers and non-corruptible registers expected to be
- * used, x0 and lr expected to be already saved on the stack
- */
-.macro	push_interrupt_context
-/*
- * Push x1-x21 on to the stack, need 19-21 because they're modified without
- * obeying PCS
- */
-	stp lr,		x1,	[sp, #-0x10]!
-	stp x2,		x3,	[sp, #-0x10]!
-	stp x4,		x5,	[sp, #-0x10]!
-	stp x6,		x7,	[sp, #-0x10]!
-	stp x8,		x9,	[sp, #-0x10]!
-	stp x10,	x11,	[sp, #-0x10]!
-	stp x12,	x13,	[sp, #-0x10]!
-	stp x14,	x15,	[sp, #-0x10]!
-	stp x16,	x17,	[sp, #-0x10]!
-	stp x18,	x19,	[sp, #-0x10]!
-	stp x20,	x21,	[sp, #-0x10]!
-/*
- * Push q0-q31 on to the stack, need everything because parts of every register
- * are volatile/corruptible
- */
-	stp q0,		q1,	[sp, #-0x20]!
-	stp q2,		q3,	[sp, #-0x20]!
-	stp q4,		q5,	[sp, #-0x20]!
-	stp q6,		q7,	[sp, #-0x20]!
-	stp q8,		q9,	[sp, #-0x20]!
-	stp q10,	q11,	[sp, #-0x20]!
-	stp q12,	q13,	[sp, #-0x20]!
-	stp q14,	q15,	[sp, #-0x20]!
-	stp q16,	q17,	[sp, #-0x20]!
-	stp q18,	q19,	[sp, #-0x20]!
-	stp q20,	q21,	[sp, #-0x20]!
-	stp q22,	q23,	[sp, #-0x20]!
-	stp q24,	q25,	[sp, #-0x20]!
-	stp q26,	q27,	[sp, #-0x20]!
-	stp q28,	q29,	[sp, #-0x20]!
-	stp q30,	q31,	[sp, #-0x20]!
-/* Get exception LR for PC and spsr */
-	mrs x0, ELR_EL1
-	mrs x1, SPSR_EL1
-/* Push pc and spsr */
-	stp x0,		x1,	[sp, #-0x10]!
-/* Get fpcr and fpsr */
-	mrs x0, FPSR
-	mrs x1, FPCR
-/* Push fpcr and fpsr */
-	stp x0,		x1,	[sp, #-0x10]!
-.endm
-
-/* Must match inverse order of .push_interrupt_context */
-.macro pop_interrupt_context
-/* Pop fpcr and fpsr */
-	ldp x0,		x1,	[sp], #0x10
-/* Restore fpcr and fpsr */
-	msr FPCR, x1
-	msr FPSR, x0
-/* Pop pc and spsr */
-	ldp x0,		x1,	[sp], #0x10
-/* Restore exception LR for PC and spsr */
-	msr SPSR_EL1, x1
-	msr ELR_EL1, x0
-/* Pop q0-q31 */
-	ldp q30,	q31,	[sp], #0x20
-	ldp q28,	q29,	[sp], #0x20
-	ldp q26,	q27,	[sp], #0x20
-	ldp q24,	q25,	[sp], #0x20
-	ldp q22,	q23,	[sp], #0x20
-	ldp q20,	q21,	[sp], #0x20
-	ldp q18,	q19,	[sp], #0x20
-	ldp q16,	q17,	[sp], #0x20
-	ldp q14,	q15,	[sp], #0x20
-	ldp q12,	q13,	[sp], #0x20
-	ldp q10,	q11,	[sp], #0x20
-	ldp q8,		q9,	[sp], #0x20
-	ldp q6,		q7,	[sp], #0x20
-	ldp q4,		q5,	[sp], #0x20
-	ldp q2,		q3,	[sp], #0x20
-	ldp q0,		q1,	[sp], #0x20
-/* Pop x1-x21 */
-	ldp x20,	x21,	[sp], #0x10
-	ldp x18,	x19,	[sp], #0x10
-	ldp x16,	x17,	[sp], #0x10
-	ldp x14,	x15,	[sp], #0x10
-	ldp x12,	x13,	[sp], #0x10
-	ldp x10,	x11,	[sp], #0x10
-	ldp x8,		x9,	[sp], #0x10
-	ldp x6,		x7,	[sp], #0x10
-	ldp x4,		x5,	[sp], #0x10
-	ldp x2,		x3,	[sp], #0x10
-	ldp lr,		x1,	[sp], #0x10
-/* Must clear reservations here to ensure consistency with atomic operations */
-	clrex
-.endm
-
 _AArch64_Exception_interrupt_nest:
 
 /* Execution template:
@@ -309,7 +211,7 @@ Return to embedded exception vector code
  */
 	cmp	x0, #0
 	bne	.Lno_need_thread_dispatch
-	bl .AArch64_Perform_Thread_Dispatch
+	bl _AArch64_Perform_Thread_Dispatch
 
 .Lno_need_thread_dispatch:
 /*
diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-map.S b/cpukit/score/cpu/aarch64/aarch64-exception-map.S
new file mode 100644
index 0000000000..da79e703c9
--- /dev/null
+++ b/cpukit/score/cpu/aarch64/aarch64-exception-map.S
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreCPUAArch64
+ *
+ * @brief Implementation of AArch64 exception map handler.
+ *
+ * This file implements the AArch64 exception map handler which maps machine
+ * exceptions to POSIX signals. For more information, see documentation for
+ * CONFIGURE_APPLICATION_NEEDS_EXCEPTION_TO_SIGNAL_MAPPING.
+ */
+
+/*
+ * Copyright (C) 2020 On-Line Applications Research Corporation (OAR)
+ * Written by Kinsey Moore <kinsey.moore at 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>
+
+.globl _AArch64_Exception_synchronous_map
+
+_AArch64_Exception_synchronous_map:
+/* Execution template:
+Save volatile registers on thread stack(some x, all q, ELR, etc.)
+Execute map handler
+Perform thread dispatch
+Restore volatile registers from thread stack
+Return to embedded exception vector code
+*/
+
+/* Push interrupt context */
+	push_interrupt_context
+
+/*
+ * Thread dispatch can occur inside the exception map and the available code
+ * paths assume that exceptions are ensabled.
+ */
+	msr	DAIFClr, #0x2
+
+/* Set x0 and jump into the handler */
+	mrs	x0, ESR_EL1
+	bl AArch64_map_exception
+
+/*
+ * Thread dispatch via the call below assumes that exceptions are disabled upon
+ * entry.
+ */
+	msr	DAIFSet, #0x2
+
+/*
+ * Perform thread dispatch. A Synchronous exception occurred and there is no
+ * other way to resolve it.
+ */
+	bl _AArch64_Perform_Thread_Dispatch
+
+/*
+ * SP should be where it was pre-handler (pointing at the exception frame)
+ * or something has leaked stack space
+ */
+/* Pop interrupt context */
+	pop_interrupt_context
+/* Return to vector for final cleanup */
+	ret
diff --git a/cpukit/score/cpu/aarch64/include/rtems/asm.h b/cpukit/score/cpu/aarch64/include/rtems/asm.h
index 35bf533c8a..fa30e45dcb 100644
--- a/cpukit/score/cpu/aarch64/include/rtems/asm.h
+++ b/cpukit/score/cpu/aarch64/include/rtems/asm.h
@@ -84,6 +84,103 @@
 	ldr	\REG, =_Per_CPU_Information
 .endm
 
+/*
+ * Must save corruptible registers and non-corruptible registers expected to be
+ * used, x0 and lr expected to be already saved on the stack
+ */
+.macro	push_interrupt_context
+/*
+ * Push x1-x21 on to the stack, need 19-21 because they're modified without
+ * obeying PCS
+ */
+	stp lr,		x1,	[sp, #-0x10]!
+	stp x2,		x3,	[sp, #-0x10]!
+	stp x4,		x5,	[sp, #-0x10]!
+	stp x6,		x7,	[sp, #-0x10]!
+	stp x8,		x9,	[sp, #-0x10]!
+	stp x10,	x11,	[sp, #-0x10]!
+	stp x12,	x13,	[sp, #-0x10]!
+	stp x14,	x15,	[sp, #-0x10]!
+	stp x16,	x17,	[sp, #-0x10]!
+	stp x18,	x19,	[sp, #-0x10]!
+	stp x20,	x21,	[sp, #-0x10]!
+/*
+ * Push q0-q31 on to the stack, need everything because parts of every register
+ * are volatile/corruptible
+ */
+	stp q0,		q1,	[sp, #-0x20]!
+	stp q2,		q3,	[sp, #-0x20]!
+	stp q4,		q5,	[sp, #-0x20]!
+	stp q6,		q7,	[sp, #-0x20]!
+	stp q8,		q9,	[sp, #-0x20]!
+	stp q10,	q11,	[sp, #-0x20]!
+	stp q12,	q13,	[sp, #-0x20]!
+	stp q14,	q15,	[sp, #-0x20]!
+	stp q16,	q17,	[sp, #-0x20]!
+	stp q18,	q19,	[sp, #-0x20]!
+	stp q20,	q21,	[sp, #-0x20]!
+	stp q22,	q23,	[sp, #-0x20]!
+	stp q24,	q25,	[sp, #-0x20]!
+	stp q26,	q27,	[sp, #-0x20]!
+	stp q28,	q29,	[sp, #-0x20]!
+	stp q30,	q31,	[sp, #-0x20]!
+/* Get exception LR for PC and spsr */
+	mrs x0, ELR_EL1
+	mrs x1, SPSR_EL1
+/* Push pc and spsr */
+	stp x0,		x1,	[sp, #-0x10]!
+/* Get fpcr and fpsr */
+	mrs x0, FPSR
+	mrs x1, FPCR
+/* Push fpcr and fpsr */
+	stp x0,		x1,	[sp, #-0x10]!
+.endm
+
+/* Must match inverse order of .push_interrupt_context */
+.macro pop_interrupt_context
+/* Pop fpcr and fpsr */
+	ldp x0,		x1,	[sp], #0x10
+/* Restore fpcr and fpsr */
+	msr FPCR, x1
+	msr FPSR, x0
+/* Pop pc and spsr */
+	ldp x0,		x1,	[sp], #0x10
+/* Restore exception LR for PC and spsr */
+	msr SPSR_EL1, x1
+	msr ELR_EL1, x0
+/* Pop q0-q31 */
+	ldp q30,	q31,	[sp], #0x20
+	ldp q28,	q29,	[sp], #0x20
+	ldp q26,	q27,	[sp], #0x20
+	ldp q24,	q25,	[sp], #0x20
+	ldp q22,	q23,	[sp], #0x20
+	ldp q20,	q21,	[sp], #0x20
+	ldp q18,	q19,	[sp], #0x20
+	ldp q16,	q17,	[sp], #0x20
+	ldp q14,	q15,	[sp], #0x20
+	ldp q12,	q13,	[sp], #0x20
+	ldp q10,	q11,	[sp], #0x20
+	ldp q8,		q9,	[sp], #0x20
+	ldp q6,		q7,	[sp], #0x20
+	ldp q4,		q5,	[sp], #0x20
+	ldp q2,		q3,	[sp], #0x20
+	ldp q0,		q1,	[sp], #0x20
+/* Pop x1-x21 */
+	ldp x20,	x21,	[sp], #0x10
+	ldp x18,	x19,	[sp], #0x10
+	ldp x16,	x17,	[sp], #0x10
+	ldp x14,	x15,	[sp], #0x10
+	ldp x12,	x13,	[sp], #0x10
+	ldp x10,	x11,	[sp], #0x10
+	ldp x8,		x9,	[sp], #0x10
+	ldp x6,		x7,	[sp], #0x10
+	ldp x4,		x5,	[sp], #0x10
+	ldp x2,		x3,	[sp], #0x10
+	ldp lr,		x1,	[sp], #0x10
+/* Must clear reservations here to ensure consistency with atomic operations */
+	clrex
+.endm
+
 /** @} */
 
 #endif /* _RTEMS_ASM_H */
diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h
index 316079a6cd..eb2206ffc7 100644
--- a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h
@@ -433,6 +433,10 @@ typedef enum {
 #define VECTOR_ENTRY_SIZE 0x80
 void _AArch64_Exception_interrupt_no_nest( void );
 void _AArch64_Exception_interrupt_nest( void );
+void _AArch64_Perform_Thread_Dispatch( void );
+void _AArch64_Exception_synchronous_map( void );
+void _AArch64_push_exception_context_start( void );
+void _AArch64_push_exception_context_finish( void );
 static inline void* AArch64_set_exception_handler(
   AArch64_symbolic_exception_name exception,
   void (*handler)(void)
@@ -545,6 +549,7 @@ typedef struct {
 void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
 
 void _AArch64_Exception_default( CPU_Exception_frame *frame );
+void AArch64_map_exception( uint64_t syndrome );
 
 /** Type that can store a 32-bit integer or a pointer. */
 typedef uintptr_t CPU_Uint32ptr;
diff --git a/spec/build/bsps/aarch64/grp.yml b/spec/build/bsps/aarch64/grp.yml
index a6bc0d5a31..24967d4841 100644
--- a/spec/build/bsps/aarch64/grp.yml
+++ b/spec/build/bsps/aarch64/grp.yml
@@ -23,7 +23,9 @@ install:
   source:
   - bsps/aarch64/shared/start/linkcmds.base
 ldflags: []
-links: []
+links:
+- role: build-dependency
+  uid: objexceptions
 type: build
 use-after: []
 use-before: []
diff --git a/spec/build/bsps/aarch64/objexceptions.yml b/spec/build/bsps/aarch64/objexceptions.yml
new file mode 100644
index 0000000000..859d837271
--- /dev/null
+++ b/spec/build/bsps/aarch64/objexceptions.yml
@@ -0,0 +1,14 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: objects
+cflags: []
+copyrights:
+- Copyright (C) 2021 On-Line Applications Research (OAR)
+cppflags: []
+cxxflags: []
+enabled-by: true
+includes: []
+install: []
+links: []
+source:
+- bsps/aarch64/shared/exceptions.c
+type: build
diff --git a/spec/build/cpukit/cpuaarch64.yml b/spec/build/cpukit/cpuaarch64.yml
index 80562756ba..a984b3ee62 100644
--- a/spec/build/cpukit/cpuaarch64.yml
+++ b/spec/build/cpukit/cpuaarch64.yml
@@ -30,6 +30,7 @@ source:
 - cpukit/score/cpu/aarch64/aarch64-exception-default.c
 - cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c
 - cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S
+- cpukit/score/cpu/aarch64/aarch64-exception-map.S
 - cpukit/score/cpu/aarch64/aarch64-thread-idle.c
 - cpukit/score/cpu/aarch64/cpu.c
 - cpukit/score/cpu/aarch64/cpu_asm.S
-- 
2.20.1



More information about the devel mailing list