This adds a CPU port for AArch64(ARMv8) with support for exceptions and interrupts. --- cpukit/include/rtems/score/tls.h | 2 +- .../cpu/aarch64/aarch64-context-validate.S | 295 ++++++++++ .../aarch64-context-volatile-clobber.S | 90 +++ .../cpu/aarch64/aarch64-exception-default.S | 407 +++++++++++++ .../cpu/aarch64/aarch64-exception-default.c | 39 ++ .../aarch64/aarch64-exception-frame-print.c | 96 +++ .../cpu/aarch64/aarch64-exception-interrupt.S | 306 ++++++++++ .../score/cpu/aarch64/aarch64-thread-idle.c | 48 ++ cpukit/score/cpu/aarch64/cpu.c | 196 +++++++ cpukit/score/cpu/aarch64/cpu_asm.S | 134 +++++ .../cpu/aarch64/include/libcpu/vectors.h | 101 ++++ cpukit/score/cpu/aarch64/include/rtems/asm.h | 90 +++ .../cpu/aarch64/include/rtems/score/aarch64.h | 81 +++ .../cpu/aarch64/include/rtems/score/cpu.h | 548 ++++++++++++++++++ .../aarch64/include/rtems/score/cpuatomic.h | 34 ++ .../cpu/aarch64/include/rtems/score/cpuimpl.h | 81 +++ spec/build/cpukit/cpuaarch64.yml | 32 + spec/build/cpukit/librtemscpu.yml | 2 + 18 files changed, 2581 insertions(+), 1 deletion(-) create mode 100644 cpukit/score/cpu/aarch64/aarch64-context-validate.S create mode 100644 cpukit/score/cpu/aarch64/aarch64-context-volatile-clobber.S create mode 100644 cpukit/score/cpu/aarch64/aarch64-exception-default.S create mode 100644 cpukit/score/cpu/aarch64/aarch64-exception-default.c create mode 100644 cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c create mode 100644 cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S create mode 100644 cpukit/score/cpu/aarch64/aarch64-thread-idle.c create mode 100644 cpukit/score/cpu/aarch64/cpu.c create mode 100644 cpukit/score/cpu/aarch64/cpu_asm.S create mode 100644 cpukit/score/cpu/aarch64/include/libcpu/vectors.h create mode 100644 cpukit/score/cpu/aarch64/include/rtems/asm.h create mode 100644 cpukit/score/cpu/aarch64/include/rtems/score/aarch64.h create mode 100644 cpukit/score/cpu/aarch64/include/rtems/score/cpu.h create mode 100644 cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h create mode 100644 cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h create mode 100644 spec/build/cpukit/cpuaarch64.yml
diff --git a/cpukit/include/rtems/score/tls.h b/cpukit/include/rtems/score/tls.h index 65a49d87be..8c15eee569 100644 --- a/cpukit/include/rtems/score/tls.h +++ b/cpukit/include/rtems/score/tls.h @@ -85,7 +85,7 @@ typedef struct TLS_Thread_control_block { struct TLS_Thread_control_block *tcb; #else /* !__i386__ */ TLS_Dynamic_thread_vector *dtv; -#if CPU_SIZEOF_POINTER == 4 +#if CPU_SIZEOF_POINTER == 4 || CPU_SIZEOF_POINTER == 8 uintptr_t reserved; #endif #endif /* __i386__ */ diff --git a/cpukit/score/cpu/aarch64/aarch64-context-validate.S b/cpukit/score/cpu/aarch64/aarch64-context-validate.S new file mode 100644 index 0000000000..afd339ad85 --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-context-validate.S @@ -0,0 +1,295 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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> +#include <rtems/score/cpu.h> + +#define FRAME_OFFSET_X4 0 +#define FRAME_OFFSET_X5 8 +#define FRAME_OFFSET_X6 16 +#define FRAME_OFFSET_X7 24 +#define FRAME_OFFSET_X8 32 +#define FRAME_OFFSET_X9 40 +#define FRAME_OFFSET_X10 48 +#define FRAME_OFFSET_X11 56 +#define FRAME_OFFSET_LR 64 + +#ifdef AARCH64_MULTILIB_VFP + #define FRAME_OFFSET_V8 72 + #define FRAME_OFFSET_V9 88 + #define FRAME_OFFSET_V10 104 + #define FRAME_OFFSET_V11 120 + #define FRAME_OFFSET_V12 136 + #define FRAME_OFFSET_V13 152 + #define FRAME_OFFSET_V14 168 + #define FRAME_OFFSET_V15 184 + + #define FRAME_SIZE (FRAME_OFFSET_V15 + 16) +#else + #define FRAME_SIZE (FRAME_OFFSET_LR + 8) +#endif + + .section .text + +FUNCTION_ENTRY(_CPU_Context_validate) + + /* Save */ + + sub sp, sp, #FRAME_SIZE + + str x4, [sp, #FRAME_OFFSET_X4] + str x5, [sp, #FRAME_OFFSET_X5] + str x6, [sp, #FRAME_OFFSET_X6] + str x7, [sp, #FRAME_OFFSET_X7] + str x8, [sp, #FRAME_OFFSET_X8] + str x9, [sp, #FRAME_OFFSET_X9] + str x10, [sp, #FRAME_OFFSET_X10] + str x11, [sp, #FRAME_OFFSET_X11] + str lr, [sp, #FRAME_OFFSET_LR] + +#ifdef AARCH64_MULTILIB_VFP + str d8, [sp, #FRAME_OFFSET_V8] + str d9, [sp, #FRAME_OFFSET_V9] + str d10, [sp, #FRAME_OFFSET_V10] + str d11, [sp, #FRAME_OFFSET_V11] + str d12, [sp, #FRAME_OFFSET_V12] + str d13, [sp, #FRAME_OFFSET_V13] + str d14, [sp, #FRAME_OFFSET_V14] + str d15, [sp, #FRAME_OFFSET_V15] +#endif + + /* Fill */ + + /* R1 is used for temporary values */ + mov x1, x0 + + /* R2 contains the stack pointer */ + mov x2, sp + +.macro fill_register reg + add x1, x1, #1 + mov \reg, x1 +.endm + + +#ifdef AARCH64_MULTILIB_VFP + /* X3 contains the FPSCR */ + mrs x3, FPSR + ldr x4, =0xf000001f + bic x3, x3, x4 + and x4, x4, x0 + orr x3, x3, x4 + msr FPSR, x3 +#else + fill_register x3 +#endif + + fill_register x4 + fill_register x5 + fill_register x6 + fill_register x7 + fill_register x8 + fill_register x9 + fill_register x10 + fill_register x11 + fill_register x12 + fill_register lr + +#ifdef AARCH64_MULTILIB_VFP +.macro fill_vfp_register regnum + add x1, x1, #1 + fmov d\regnum\(), x1 + fmov v\regnum\().D[1], x1 +.endm + + fill_vfp_register 0 + fill_vfp_register 1 + fill_vfp_register 2 + fill_vfp_register 3 + fill_vfp_register 4 + fill_vfp_register 5 + fill_vfp_register 6 + fill_vfp_register 7 + fill_vfp_register 8 + fill_vfp_register 9 + fill_vfp_register 10 + fill_vfp_register 11 + fill_vfp_register 12 + fill_vfp_register 13 + fill_vfp_register 14 + fill_vfp_register 15 + fill_vfp_register 16 + fill_vfp_register 17 + fill_vfp_register 18 + fill_vfp_register 19 + fill_vfp_register 20 + fill_vfp_register 21 + fill_vfp_register 22 + fill_vfp_register 23 + fill_vfp_register 24 + fill_vfp_register 25 + fill_vfp_register 26 + fill_vfp_register 27 + fill_vfp_register 28 + fill_vfp_register 29 + fill_vfp_register 30 + fill_vfp_register 31 +#endif /* AARCH64_MULTILIB_VFP */ + + /* Check */ +check: + +.macro check_register reg + add x1, x1, #1 + cmp \reg, x1 + bne restore +.endm + + /* A compare involving the stack pointer is deprecated */ + mov x1, sp + cmp x2, x1 + bne restore + + mov x1, x0 + +#ifndef AARCH64_MULTILIB_VFP + check_register x3 +#endif + + check_register x4 + check_register x5 + check_register x6 + check_register x7 + check_register x8 + check_register x9 + check_register x10 + check_register x11 + check_register x12 + check_register lr + +#ifdef AARCH64_MULTILIB_VFP + b check_vfp +#endif + + b check + + /* Restore */ +restore: + + ldr x4, [sp, #FRAME_OFFSET_X4] + ldr x5, [sp, #FRAME_OFFSET_X5] + ldr x6, [sp, #FRAME_OFFSET_X6] + ldr x7, [sp, #FRAME_OFFSET_X7] + ldr x8, [sp, #FRAME_OFFSET_X8] + ldr x9, [sp, #FRAME_OFFSET_X9] + ldr x10, [sp, #FRAME_OFFSET_X10] + ldr x11, [sp, #FRAME_OFFSET_X11] + ldr lr, [sp, #FRAME_OFFSET_LR] + +#ifdef AARCH64_MULTILIB_VFP + ldr d8, [sp, #FRAME_OFFSET_V8] + ldr d9, [sp, #FRAME_OFFSET_V9] + ldr d10, [sp, #FRAME_OFFSET_V10] + ldr d11, [sp, #FRAME_OFFSET_V11] + ldr d12, [sp, #FRAME_OFFSET_V12] + ldr d13, [sp, #FRAME_OFFSET_V13] + ldr d14, [sp, #FRAME_OFFSET_V14] + ldr d15, [sp, #FRAME_OFFSET_V15] +#endif + + add sp, sp, #FRAME_SIZE + + ret + +FUNCTION_END(_CPU_Context_validate) + +#ifdef AARCH64_MULTILIB_VFP +check_vfp: + +.macro check_vfp_register regnum + add x1, x1, #1 + fmov x4, d\regnum + fmov x5, v\regnum\().D[1] + cmp x5, x4 + bne 1f + cmp x1, x4 + bne 1f + b 2f +1: + b restore +2: +.endm + + mrs x4, FPSR + cmp x4, x3 + bne restore + + check_vfp_register 0 + check_vfp_register 1 + check_vfp_register 2 + check_vfp_register 3 + check_vfp_register 4 + check_vfp_register 5 + check_vfp_register 6 + check_vfp_register 7 + check_vfp_register 8 + check_vfp_register 9 + check_vfp_register 10 + check_vfp_register 11 + check_vfp_register 12 + check_vfp_register 13 + check_vfp_register 14 + check_vfp_register 15 + check_vfp_register 16 + check_vfp_register 17 + check_vfp_register 18 + check_vfp_register 19 + check_vfp_register 20 + check_vfp_register 21 + check_vfp_register 22 + check_vfp_register 23 + check_vfp_register 24 + check_vfp_register 25 + check_vfp_register 26 + check_vfp_register 27 + check_vfp_register 28 + check_vfp_register 29 + check_vfp_register 30 + check_vfp_register 31 + + /* Restore x4 and x5 */ + mov x1, x0 + fill_register x4 + fill_register x5 + + b check +#endif /* AARCH64_MULTILIB_VFP */ diff --git a/cpukit/score/cpu/aarch64/aarch64-context-volatile-clobber.S b/cpukit/score/cpu/aarch64/aarch64-context-volatile-clobber.S new file mode 100644 index 0000000000..b36159c90f --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-context-volatile-clobber.S @@ -0,0 +1,90 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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> + + .section .text + +FUNCTION_ENTRY(_CPU_Context_volatile_clobber) + +.macro clobber_register reg + sub x0, x0, #1 + mov \reg, x0 +.endm + +#ifdef AARCH64_MULTILIB_VFP + mrs x1, FPCR + ldr x2, =0xf000001f + bic x1, x1, x2 + and x2, x2, x0 + orr x1, x1, x2 + msr FPCR, x1 + +.macro clobber_vfp_register reg + sub x0, x0, #1 + fmov \reg, x0 +.endm + + clobber_vfp_register d0 + clobber_vfp_register d1 + clobber_vfp_register d2 + clobber_vfp_register d3 + clobber_vfp_register d4 + clobber_vfp_register d5 + clobber_vfp_register d6 + clobber_vfp_register d7 + clobber_vfp_register d16 + clobber_vfp_register d17 + clobber_vfp_register d18 + clobber_vfp_register d19 + clobber_vfp_register d20 + clobber_vfp_register d21 + clobber_vfp_register d22 + clobber_vfp_register d23 + clobber_vfp_register d24 + clobber_vfp_register d25 + clobber_vfp_register d26 + clobber_vfp_register d27 + clobber_vfp_register d28 + clobber_vfp_register d29 + clobber_vfp_register d30 + clobber_vfp_register d31 +#endif /* AARCH64_MULTILIB_VFP */ + + clobber_register x1 + clobber_register x2 + clobber_register x3 + clobber_register x12 + + ret + +FUNCTION_END(_CPU_Context_volatile_clobber) 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..18e068cb14 --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.S @@ -0,0 +1,407 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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 + mov x0, #0x7f /* mask to use in BIC, lower 7 bits */ + bic x0, lr, x0 /* lr contains PC, mask off to the base of the current vector */ + ldr x0, [x0, #0x78] /* load address from the last word in the vector */ + blr x0 /* branch and link to address in x0, no reason to save current LR since it has already been saved and current contents are junk */ + ldp x0, lr, [sp], #16 /* pop x0,lr from stack */ + eret /* return from exception */ + 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: +curr_el_sp0_sync: // The exception handler for the synchronous exception from the current EL using SP0. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SP0 +.balign 0x80 +curr_el_sp0_irq: // The exception handler for the IRQ exception from the current EL using SP0. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SP0 +.balign 0x80 +curr_el_sp0_fiq: // The exception handler for the FIQ exception from the current EL using SP0. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SP0 +.balign 0x80 +curr_el_sp0_serror: // The exception handler for the system error exception from the current EL using SP0. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SP0 +.balign 0x80 +curr_el_spx_sync: // The exception handler for the synchronous exception from the current EL using the // current SP. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +curr_el_spx_irq: // The exception handler for IRQ exception from the current EL using the current SP. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +curr_el_spx_fiq: // The exception handler for the FIQ exception from the current EL using the current SP. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +curr_el_spx_serror: // The exception handler for the system error exception from the current EL using the // current SP. + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch64_sync: // The exception handler for the synchronous exception from a lower EL (AArch64). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch64_irq: // The exception handler for the IRQ exception from a lower EL (AArch64). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch64_fiq: // The exception handler for the FIQ exception from a lower EL (AArch64). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch64_serror: // The exception handler for the system error exception from a lower EL(AArch64). + stp x0, lr, [sp, #-16]! /* push x0,lr on to the stack */ + bl lower_el_aarch64_serror_get_pc /* get current execution address */ +lower_el_aarch64_serror_get_pc: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch32_sync: // The exception handler for the synchronous exception from a lower EL(AArch32). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch32_irq: // The exception handler for the IRQ exception from a lower EL (AArch32). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch32_fiq: // The exception handler for the FIQ exception from a lower EL (AArch32). + 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: /* current PC now in LR */ + JUMP_HANDLER + JUMP_TARGET_SPx +.balign 0x80 +lower_el_aarch32_serror: // The exception handler for the system error exception from a lower EL(AArch32). + stp x0, lr, [sp, #-16]! /* push x0,lr on to the stack */ + bl lower_el_aarch32_serror_get_pc /* get current execution address */ +lower_el_aarch32_serror_get_pc : /* current PC 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 (TODO(kmoore): ignored, factor out) 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 here to ensure consistency with atomic operations */ + clrex + + ret + + diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-default.c b/cpukit/score/cpu/aarch64/aarch64-exception-default.c new file mode 100644 index 0000000000..d71d2ac38c --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.c @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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/score/cpu.h> +#include <rtems/fatal.h> + +void _AArch64_Exception_default( CPU_Exception_frame *frame ) +{ + rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) frame ); +} diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c b/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c new file mode 100644 index 0000000000..def8a4455d --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c @@ -0,0 +1,96 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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 <inttypes.h> + +#include <rtems/score/cpu.h> +#include <rtems/bspIo.h> + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + printk( + "\n" + "X0 = 0x%016" PRIx64 " X17 = 0x%016" PRIx64 "\n" + "X1 = 0x%016" PRIx64 " X18 = 0x%016" PRIx64 "\n" + "X2 = 0x%016" PRIx64 " X19 = 0x%016" PRIx64 "\n" + "X3 = 0x%016" PRIx64 " X20 = 0x%016" PRIx64 "\n" + "X4 = 0x%016" PRIx64 " X21 = 0x%016" PRIx64 "\n" + "X5 = 0x%016" PRIx64 " X22 = 0x%016" PRIx64 "\n" + "X6 = 0x%016" PRIx64 " X23 = 0x%016" PRIx64 "\n" + "X7 = 0x%016" PRIx64 " X24 = 0x%016" PRIx64 "\n" + "X8 = 0x%016" PRIx64 " X25 = 0x%016" PRIx64 "\n" + "X9 = 0x%016" PRIx64 " X26 = 0x%016" PRIx64 "\n" + "X10 = 0x%016" PRIx64 " X27 = 0x%016" PRIx64 "\n" + "X11 = 0x%016" PRIx64 " X28 = 0x%016" PRIx64 "\n" + "X12 = 0x%016" PRIx64 " FP = 0x%016" PRIx64 "\n" + "X13 = 0x%016" PRIx64 " LR = 0x%016" PRIxPTR "\n" + "X14 = 0x%016" PRIx64 " SP = 0x%016" PRIx64 "\n" + "X15 = 0x%016" PRIx64 " PC = 0x%016" PRIxPTR "\n" + "X16 = 0x%016" PRIx64 " DAIF = 0x%016" PRIx64 "\n" + "VEC = 0x%016" PRIxPTR " CPSR = 0x%016" PRIx64 "\n" + "ESR = 0x%016" PRIx64 " FAR = 0x%016" PRIx64 "\n", + frame->register_x0, frame->register_x17, + frame->register_x1, frame->register_x18, + frame->register_x2, frame->register_x19, + frame->register_x3, frame->register_x20, + frame->register_x4, frame->register_x21, + frame->register_x5, frame->register_x22, + frame->register_x6, frame->register_x23, + frame->register_x7, frame->register_x24, + frame->register_x8, frame->register_x25, + frame->register_x9, frame->register_x26, + frame->register_x10, frame->register_x27, + frame->register_x11, frame->register_x28, + frame->register_x12, frame->register_fp, + frame->register_x13, (intptr_t)frame->register_lr, + frame->register_x14, frame->register_sp, + frame->register_x15, (intptr_t)frame->register_pc, + frame->register_x16, frame->register_daif, + (intptr_t) frame->vector, frame->register_cpsr, + frame->register_syndrome, frame->register_fault_address + ); + + const uint128_t *qx = &frame->register_q0; + int i; + + printk( + "FPCR = 0x%016" PRIx64 " FPSR = 0x%016" PRIx64 "\n", + frame->register_fpcr, frame->register_fpsr + ); + + for ( i = 0; i < 32; ++i ) { + uint64_t low = (uint64_t) qx[i]; + uint64_t high = (uint64_t) (qx[i] >> 32); + + printk( "Q%02i = 0x%016" PRIx64 "%016" PRIx64 "\n", i, high, low ); + } +} diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S b/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S new file mode 100644 index 0000000000..6d10e6b0be --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S @@ -0,0 +1,306 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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_interrupt_no_nest +.globl _AArch64_Exception_interrupt_nest + +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 + #define SELF_CPU_CONTROL_GET_REG w19 +#else + #define SELF_CPU_CONTROL_GET_REG x19 +#endif +#define SELF_CPU_CONTROL x19 +#define NON_VOLATILE_SCRATCH x20 + +/* it's understood that CPU state is saved prior to this and restored after this */ +/* 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_Interrupt_Handler: + /* Get per-CPU control of current processor */ + GET_SELF_CPU_CONTROL SELF_CPU_CONTROL_GET_REG + + /* Increment interrupt nest and thread dispatch disable level */ + ldr w2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL] + ldr w3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + add w2, w2, #1 + add w3, w3, #1 + str w2, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL] + str w3, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + + /* Save LR */ + mov x21, LR + + /* Call BSP dependent interrupt dispatcher */ + bl bsp_interrupt_dispatch + + /* Restore LR */ + mov LR, x21 + + /* Load some per-CPU variables */ + ldr w0, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + ldrb w1, [SELF_CPU_CONTROL, #PER_CPU_DISPATCH_NEEDED] + ldr w2, [SELF_CPU_CONTROL, #PER_CPU_ISR_DISPATCH_DISABLE] + ldr w3, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL] + + /* Decrement levels and determine thread dispatch state */ + eor w1, w1, w0 + sub w0, w0, #1 + orr w1, w1, w0 + orr w1, w1, w2 + sub w3, w3, #1 + + /* Store thread dispatch disable and ISR nest levels */ + str w0, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + str w3, [SELF_CPU_CONTROL, #PER_CPU_ISR_NEST_LEVEL] + + /* Return should_skip_thread_dispatch in x0 */ + mov x0, x1 + /* Return from handler */ + ret + +/* 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: + /* Get per-CPU control of current processor */ + GET_SELF_CPU_CONTROL SELF_CPU_CONTROL_GET_REG + + /* Thread dispatch */ + mrs NON_VOLATILE_SCRATCH, DAIF + +.Ldo_thread_dispatch: + + /* Set ISR dispatch disable and thread dispatch disable level to one */ + mov w0, #1 + str w0, [SELF_CPU_CONTROL, #PER_CPU_ISR_DISPATCH_DISABLE] + str w0, [SELF_CPU_CONTROL, #PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + + /* Save LR */ + mov x21, LR + + /* 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 + bl _Thread_Do_dispatch + + /* Restore LR */ + mov LR, x21 + + /* Disable interrupts */ + msr DAIF, NON_VOLATILE_SCRATCH + +#ifdef RTEMS_SMP + GET_SELF_CPU_CONTROL SELF_CPU_CONTROL_GET_REG +#endif + + /* Check if we have to do the thread dispatch again */ + ldrb w0, [SELF_CPU_CONTROL, #PER_CPU_DISPATCH_NEEDED] + cmp w0, #0 + bne .Ldo_thread_dispatch + + /* We are done with thread dispatching */ + mov w0, #0 + str w0, [SELF_CPU_CONTROL, #PER_CPU_ISR_DISPATCH_DISABLE] + + /* 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, #-16]! + stp x2, x3, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x19, [sp, #-16]! + stp x20, x21, [sp, #-16]! +/* push q0-q31 on to the stack, need everything because parts of every register are volatile/corruptible */ + stp q0, q1, [sp, #-32]! + stp q2, q3, [sp, #-32]! + stp q4, q5, [sp, #-32]! + stp q6, q7, [sp, #-32]! + stp q8, q9, [sp, #-32]! + stp q10, q11, [sp, #-32]! + stp q12, q13, [sp, #-32]! + stp q14, q15, [sp, #-32]! + stp q16, q17, [sp, #-32]! + stp q18, q19, [sp, #-32]! + stp q20, q21, [sp, #-32]! + stp q22, q23, [sp, #-32]! + stp q24, q25, [sp, #-32]! + stp q26, q27, [sp, #-32]! + stp q28, q29, [sp, #-32]! + stp q30, q31, [sp, #-32]! +/* get exception LR for PC and spsr */ + mrs x0, ELR_EL1 + mrs x1, SPSR_EL1 +/* push pc and spsr */ + stp x0, x1, [sp, #-16]! +/* get fpcr and fpsr */ + mrs x0, FPSR + mrs x1, FPCR +/* push fpcr and fpsr */ + stp x0, x1, [sp, #-16]! +.endm + +/* Must match inverse order of .push_interrupt_context */ +.macro pop_interrupt_context +/* pop fpcr and fpsr */ + ldp x0, x1, [sp], #16 +/* restore fpcr and fpsr */ + msr FPCR, x1 + msr FPSR, x0 +/* pop pc and spsr */ + ldp x0, x1, [sp], #16 +/* restore exception LR for PC and spsr */ + msr SPSR_EL1, x1 + msr ELR_EL1, x0 +/* pop q0-q31 */ + ldp q30, q31, [sp], #32 + ldp q28, q29, [sp], #32 + ldp q26, q27, [sp], #32 + ldp q24, q25, [sp], #32 + ldp q22, q23, [sp], #32 + ldp q20, q21, [sp], #32 + ldp q18, q19, [sp], #32 + ldp q16, q17, [sp], #32 + ldp q14, q15, [sp], #32 + ldp q12, q13, [sp], #32 + ldp q10, q11, [sp], #32 + ldp q8, q9, [sp], #32 + ldp q6, q7, [sp], #32 + ldp q4, q5, [sp], #32 + ldp q2, q3, [sp], #32 + ldp q0, q1, [sp], #32 +/* pop x1-x21 */ + ldp x20, x21, [sp], #16 + ldp x18, x19, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ldp x2, x3, [sp], #16 + ldp lr, x1, [sp], #16 + /* Must clear reservations here to ensure consistency with atomic operations */ + clrex +.endm + +_AArch64_Exception_interrupt_nest: + +/* basic execution template: +save volatile regs on interrupt stack +execute irq handler +restore volatile regs from interrupt stack +eret +*/ + +/* push interrupt context */ + push_interrupt_context + +/* jump into the handler, ignore return value */ + bl .AArch64_Interrupt_Handler + +/* 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 + +_AArch64_Exception_interrupt_no_nest: +/* RTEMS ARM impl does this: +save volatile registers on thread stack(some x, all q, ELR, etc.) +switch to interrupt stack +execute interrupt handler +switch to thread stack +call thread dispatch +restore volatile registers from thread stack +eret + +AArch64 implementation does: +exception handler dispatch saves x0, lr on stack +exception handler dispatch calls actual handler +exception handler dispatch pops x0, lr from stack +eret + +actual handler: +save volatile registers on thread stack(some x, all q, ELR, etc.) +switch to interrupt stack +execute interrupt handler +switch to thread stack +call thread dispatch +restore volatile registers from thread stack +ret to dispatch +*/ + + +/* push interrupt context */ + push_interrupt_context + + /* Switch to interrupt stack, interrupt dispatch may enable interrupts causing nesting */ + msr spsel, #0 + +/* jump into the handler */ + bl .AArch64_Interrupt_Handler + + /* Switch back to thread stack, interrupt dispatch should disable interrupts before returning */ + msr spsel, #1 + + /* + * Check thread dispatch necessary, ISR dispatch disable and thread + * dispatch disable level. + */ + cmp x0, #0 + bne .Lno_need_thread_dispatch + bl .AArch64_Perform_Thread_Dispatch + +.Lno_need_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/aarch64-thread-idle.c b/cpukit/score/cpu/aarch64/aarch64-thread-idle.c new file mode 100644 index 0000000000..6fab7651f5 --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-thread-idle.c @@ -0,0 +1,48 @@ +/** + * @file + * + * @brief CPU Thread Idle Body + */ + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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/score/cpu.h> + + +void *_CPU_Thread_Idle_body( uintptr_t ignored ) +{ + while ( true ) { + __asm__ volatile ("wfi"); + } +} + diff --git a/cpukit/score/cpu/aarch64/cpu.c b/cpukit/score/cpu/aarch64/cpu.c new file mode 100644 index 0000000000..4b7180d96c --- /dev/null +++ b/cpukit/score/cpu/aarch64/cpu.c @@ -0,0 +1,196 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUAArch64 + * + * @brief AArch64 architecture support implementation. + */ + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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/score/assert.h> +#include <rtems/score/cpu.h> +#include <rtems/score/thread.h> +#include <rtems/score/tls.h> + +#ifdef AARCH64_MULTILIB_VFP + RTEMS_STATIC_ASSERT( + offsetof( Context_Control, register_d8 ) == AARCH64_CONTEXT_CONTROL_D8_OFFSET, + AARCH64_CONTEXT_CONTROL_D8_OFFSET + ); +#endif + + RTEMS_STATIC_ASSERT( + offsetof( Context_Control, thread_id ) + == AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET, + AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET + ); + + RTEMS_STATIC_ASSERT( + offsetof( Context_Control, isr_dispatch_disable ) + == AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE, + AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE + ); + +#ifdef RTEMS_SMP + RTEMS_STATIC_ASSERT( + offsetof( Context_Control, is_executing ) + == AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET, + AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET + ); +#endif + +RTEMS_STATIC_ASSERT( + sizeof( CPU_Exception_frame ) == AARCH64_EXCEPTION_FRAME_SIZE, + AARCH64_EXCEPTION_FRAME_SIZE +); + +RTEMS_STATIC_ASSERT( + sizeof( CPU_Exception_frame ) % CPU_STACK_ALIGNMENT == 0, + CPU_Exception_frame_alignment +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_sp ) + == AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_lr ) + == AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_daif ) + == AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_syndrome ) + == AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, vector ) + == AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_fpsr ) + == AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET +); + +RTEMS_STATIC_ASSERT( + offsetof( CPU_Exception_frame, register_q0 ) + == AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET, + AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET +); + + +void _CPU_Context_Initialize( + Context_Control *the_context, + void *stack_area_begin, + size_t stack_area_size, + uint64_t new_level, + void (*entry_point)( void ), + bool is_fp, + void *tls_area +) +{ + (void) new_level; + + the_context->register_sp = (uintptr_t) stack_area_begin + stack_area_size; + the_context->register_lr = (uintptr_t) entry_point; + the_context->isr_dispatch_disable = 0; + + the_context->thread_id = (uintptr_t) tls_area; + + if ( tls_area != NULL ) { + _TLS_TCB_at_area_begin_initialize( tls_area ); + } +} + +void _CPU_ISR_Set_level( uint64_t level ) +{ + /* Set the mask bit if interrupts are disabled */ + level = level ? AARCH64_PSTATE_I : 0; + __asm__ volatile ( + "msr DAIF, %[level]\n" + : : [level] "r" (level) + ); +} + +uint64_t _CPU_ISR_Get_level( void ) +{ + uint64_t level; + + __asm__ volatile ( + "mrs %[level], DAIF\n" + : [level] "=&r" (level) + ); + + return level & AARCH64_PSTATE_I; +} + +void _CPU_ISR_install_vector( + uint32_t vector, + CPU_ISR_handler new_handler, + CPU_ISR_handler *old_handler +) +{ + /* Redirection table starts at the end of the vector table */ + CPU_ISR_handler *table = (CPU_ISR_handler *) (MAX_EXCEPTIONS * 4); + + CPU_ISR_handler current_handler = table [vector]; + + /* The current handler is now the old one */ + if (old_handler != NULL) { + *old_handler = current_handler; + } + + /* Write only if necessary to avoid writes to a maybe read-only memory */ + if (current_handler != new_handler) { + table [vector] = new_handler; + } +} + +void _CPU_Initialize( void ) +{ + /* Do nothing */ +} diff --git a/cpukit/score/cpu/aarch64/cpu_asm.S b/cpukit/score/cpu/aarch64/cpu_asm.S new file mode 100644 index 0000000000..9f04be7cce --- /dev/null +++ b/cpukit/score/cpu/aarch64/cpu_asm.S @@ -0,0 +1,134 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUAArch64 + * + * @brief AArch64 architecture support implementation. + */ + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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> + + .text + +/* + * void _CPU_Context_switch( run_context, heir_context ) + * void _CPU_Context_restore( run_context, heir_context ) + * + * This routine performs a normal non-FP context. + * + * X0 = run_context X1 = heir_context + * + * This function copies the current registers to where x0 points, then + * restores the ones from where x1 points. + * + */ + +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 +#define reg_2 w2 +#else +#define reg_2 x2 +#endif + +DEFINE_FUNCTION_AARCH64(_CPU_Context_switch) +/* Start saving context */ + GET_SELF_CPU_CONTROL reg_2 + ldr x3, [x2, #PER_CPU_ISR_DISPATCH_DISABLE] + + stp x19, x20, [x0] + stp x21, x22, [x0, #0x10] + stp x23, x24, [x0, #0x20] + stp x25, x26, [x0, #0x30] + stp x27, x28, [x0, #0x40] + stp fp, lr, [x0, #0x50] + mov x4, sp + str x4, [x0, #0x60] + +#ifdef AARCH64_MULTILIB_VFP + add x5, x0, #AARCH64_CONTEXT_CONTROL_D8_OFFSET + stp d8, d9, [x5] + stp d10, d11, [x5, #16] + stp d12, d13, [x5, #32] + stp d14, d15, [x5, #48] +#endif + + str x3, [x0, #AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE] + +#ifdef RTEMS_SMP +#error SMP not yet supported +#endif + +/* Start restoring context */ +.L_restore: +#if !defined(RTEMS_SMP) && defined(AARCH64_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE) + clrex +#endif + + ldr x3, [x1, #AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET] + + ldr x4, [x1, #AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE] + +#ifdef AARCH64_MULTILIB_VFP + add x5, x1, #AARCH64_CONTEXT_CONTROL_D8_OFFSET + ldp d8, d9, [x5] + ldp d10, d11, [x5, #16] + ldp d12, d13, [x5, #32] + ldp d14, d15, [x5, #48] +#endif + + msr TPIDR_EL0, x3 + + str x4, [x2, #PER_CPU_ISR_DISPATCH_DISABLE] + + ldp x19, x20, [x1] + ldp x21, x22, [x1, #0x10] + ldp x23, x24, [x1, #0x20] + ldp x25, x26, [x1, #0x30] + ldp x27, x28, [x1, #0x40] + ldp fp, lr, [x1, #0x50] + ldr x4, [x1, #0x60] + mov sp, x4 + ret + +/* + * void _CPU_Context_restore( new_context ) + * + * This function restores the registers from where x0 points. + * It must match _CPU_Context_switch() + * + */ +DEFINE_FUNCTION_AARCH64(_CPU_Context_restore) + mov x1, x0 + GET_SELF_CPU_CONTROL reg_2 + b .L_restore diff --git a/cpukit/score/cpu/aarch64/include/libcpu/vectors.h b/cpukit/score/cpu/aarch64/include/libcpu/vectors.h new file mode 100644 index 0000000000..af12efb350 --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/libcpu/vectors.h @@ -0,0 +1,101 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUAArch64 + * + * @brief ARM AArch64 Exception API. + */ + + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef LIBCPU_AARCH64_VECTORS_H +#define LIBCPU_AARCH64_VECTORS_H + +#ifndef ASM + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* VBAR, Vector Base Address Register, Security Extensions */ + +static inline void +*AArch64_get_vector_base_address(void) +{ + void *base; + + __asm__ volatile ( + "mrs %[base], VBAR_EL1\n" + : [base] "=&r" (base) + ); + + return base; +} + +static inline void +AArch64_set_vector_base_address(void *base) +{ + __asm__ volatile ( + "msr VBAR_EL1, %[base]\n" + : : [base] "r" (base) + ); +} + +static inline void +*AArch64_get_hyp_vector_base_address(void) +{ + void *base; + + __asm__ volatile ( + "mrs %[base], VBAR_EL2\n" + : [base] "=&r" (base) + ); + + return base; +} + +static inline void +AArch64_set_hyp_vector_base_address(void *base) +{ + __asm__ volatile ( + "msr VBAR_EL2, %[base]\n" + : : [base] "r" (base) + ); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ASM */ + +#endif /* LIBCPU_AARCH64_VECTORS_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/asm.h b/cpukit/score/cpu/aarch64/include/rtems/asm.h new file mode 100644 index 0000000000..21111d2559 --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/rtems/asm.h @@ -0,0 +1,90 @@ +/** + * @file + * + * @brief AArch64 Assembler Support API + * + * This include file attempts to address the problems + * caused by incompatible flavors of assemblers and + * toolsets. It primarily addresses variations in the + * use of leading underscores on symbols and the requirement + * that register names be preceded by a %. + * + * + * NOTE: The spacing in the use of these macros + * is critical to them working as advertised. + */ + + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef _RTEMS_ASM_H +#define _RTEMS_ASM_H + +/* + * Indicate we are in an assembly file and get the basic CPU definitions. + */ + +#ifndef ASM +#define ASM +#endif +#include <rtems/score/percpu.h> + +/** + * @defgroup RTEMSScoreCPUAArch64ASM AArch64 Assembler Support + * + * @ingroup RTEMSScoreCPUAArch64 + * + * @brief AArch64 Assembler Support + */ +/**@{**/ + +/* + * Following must be tailor for a particular flavor of the C compiler. + * They may need to put underscores in front of the symbols. + */ + +#define FUNCTION_ENTRY(name) \ + .align 8; \ + .globl name; \ + .type name, %function; \ + name: + +#define FUNCTION_END(name) \ + .size name, . - name + +#define DEFINE_FUNCTION_AARCH64(name) \ + .align 8 ; .globl name ; name: ; .globl name ## _aarch64 ; name ## _aarch64: + +.macro GET_SELF_CPU_CONTROL REG + ldr \REG, =_Per_CPU_Information +.endm + +/** @} */ + +#endif /* _RTEMS_ASM_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/aarch64.h b/cpukit/score/cpu/aarch64/include/rtems/score/aarch64.h new file mode 100644 index 0000000000..6fb091f7cf --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/rtems/score/aarch64.h @@ -0,0 +1,81 @@ +/** + * @file + * + * @brief ARM AArch64 Assembler Support API + */ + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef _RTEMS_SCORE_AARCH64_H +#define _RTEMS_SCORE_AARCH64_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup RTEMSScoreCPUAArch64 + */ +/**@{**/ + +#if defined(__LP64__) + #define CPU_MODEL_NAME "AArch64-LP64" + #define AARCH64_MULTILIB_ARCH_V8 +#elif defined(__ILP32__) + #define CPU_MODEL_NAME "AArch64-ILP32" + #define AARCH64_MULTILIB_ARCH_V8_ILP32 +#endif + +#define AARCH64_MULTILIB_HAS_WFI +#define AARCH64_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE +#define AARCH64_MULTILIB_HAS_BARRIER_INSTRUCTIONS +#define AARCH64_MULTILIB_HAS_CPACR + +#define AARCH64_MULTILIB_CACHE_LINE_MAX_64 + +#if defined(__ARM_NEON) + #define AARCH64_MULTILIB_VFP +#else + #error "FPU support not implemented" +#endif + + +/* + * Define the name of the CPU family. + */ + +#define CPU_NAME "AArch64" + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RTEMS_SCORE_AARCH64_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h new file mode 100644 index 0000000000..316a405a8b --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h @@ -0,0 +1,548 @@ +/** + * @file + * + * @brief AArch64 Architecture Support API + */ + + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef _RTEMS_SCORE_CPU_H +#define _RTEMS_SCORE_CPU_H + +#include <rtems/score/basedefs.h> +#if defined(RTEMS_PARAVIRT) +#include <rtems/score/paravirt.h> +#endif +#include <rtems/score/aarch64.h> +#include <libcpu/vectors.h> + +/** + * @addtogroup RTEMSScoreCPUAArch64 + * + * @{ + */ + +/** + * @name Program State Registers + */ +/**@{**/ + +#define AARCH64_PSTATE_N (1LL << 31) +#define AARCH64_PSTATE_Z (1LL << 30) +#define AARCH64_PSTATE_C (1LL << 29) +#define AARCH64_PSTATE_V (1LL << 28) +#define AARCH64_PSTATE_D (1LL << 9) +#define AARCH64_PSTATE_A (1LL << 8) +#define AARCH64_PSTATE_I (1LL << 7) +#define AARCH64_PSTATE_F (1LL << 6) + +/** @} */ + +/* + * AArch64 uses the PIC interrupt model. + */ +#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE + +#define CPU_ISR_PASSES_FRAME_POINTER FALSE + +#define CPU_HARDWARE_FP FALSE + +#define CPU_SOFTWARE_FP FALSE + +#define CPU_ALL_TASKS_ARE_FP FALSE + +#define CPU_IDLE_TASK_IS_FP FALSE + +#define CPU_USE_DEFERRED_FP_SWITCH FALSE + +#define CPU_ENABLE_ROBUST_THREAD_DISPATCH TRUE + +#define CPU_STACK_GROWS_UP FALSE + +#if defined(AARCH64_MULTILIB_CACHE_LINE_MAX_64) + #define CPU_CACHE_LINE_BYTES 64 +#else + #define CPU_CACHE_LINE_BYTES 32 +#endif + +#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES ) + +#define CPU_MODES_INTERRUPT_MASK 0x1 + +#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0 + +#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE + +#define CPU_STACK_MINIMUM_SIZE (1024 * 10) + +/* This could be either 4 or 8, depending on the ABI in use. + * Could also use __LP64__ or __ILP32__ */ +/* AAPCS64, section 5.1, Fundamental Data Types */ +#define CPU_SIZEOF_POINTER __SIZEOF_POINTER__ + +/* AAPCS64, section 5.1, Fundamental Data Types */ +#define CPU_ALIGNMENT 16 + +#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT + +/* AAPCS64, section 6.2.2, Stack constraints at a public interface */ +#define CPU_STACK_ALIGNMENT 16 + +#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES + +#define CPU_USE_GENERIC_BITFIELD_CODE TRUE + +#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE + +#define CPU_MAXIMUM_PROCESSORS 32 + +#define AARCH64_CONTEXT_CONTROL_THREAD_ID_OFFSET 112 + +#ifdef AARCH64_MULTILIB_VFP + #define AARCH64_CONTEXT_CONTROL_D8_OFFSET 120 +#endif + +#define AARCH64_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE 104 + +#ifdef RTEMS_SMP + #if defined(AARCH64_MULTILIB_VFP) + #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 112 + #else + #define AARCH64_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 48 + #endif +#endif + +#define AARCH64_EXCEPTION_FRAME_SIZE 848 + +#define AARCH64_EXCEPTION_FRAME_REGISTER_SP_OFFSET 248 +#define AARCH64_EXCEPTION_FRAME_REGISTER_LR_OFFSET 240 +#define AARCH64_EXCEPTION_FRAME_REGISTER_DAIF_OFFSET 264 +#define AARCH64_EXCEPTION_FRAME_REGISTER_SYNDROME_OFFSET 280 +#define AARCH64_EXCEPTION_FRAME_REGISTER_VECTOR_OFFSET 296 +#define AARCH64_EXCEPTION_FRAME_REGISTER_FPSR_OFFSET 312 +#define AARCH64_EXCEPTION_FRAME_REGISTER_Q0_OFFSET 336 + +#ifndef ASM + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned __int128 uint128_t; + +typedef struct { + uint64_t register_x19; + uint64_t register_x20; + uint64_t register_x21; + uint64_t register_x22; + uint64_t register_x23; + uint64_t register_x24; + uint64_t register_x25; + uint64_t register_x26; + uint64_t register_x27; + uint64_t register_x28; + uint64_t register_fp; + uint64_t register_lr; + uint64_t register_sp; + uint64_t isr_dispatch_disable; + uint64_t thread_id; +#ifdef AARCH64_MULTILIB_VFP + uint64_t register_d8; + uint64_t register_d9; + uint64_t register_d10; + uint64_t register_d11; + uint64_t register_d12; + uint64_t register_d13; + uint64_t register_d14; + uint64_t register_d15; +#endif +#ifdef RTEMS_SMP + volatile bool is_executing; +#endif +} Context_Control; + +static inline void _AARCH64_Data_memory_barrier( void ) +{ + __asm__ volatile ( "dmb LD" : : : "memory" ); +} + +static inline void _AARCH64_Data_synchronization_barrier( void ) +{ + __asm__ volatile ( "dsb LD" : : : "memory" ); +} + +static inline void _AARCH64_Instruction_synchronization_barrier( void ) +{ + __asm__ volatile ( "isb" : : : "memory" ); +} + +void _CPU_ISR_Set_level( uint64_t level ); + +uint64_t _CPU_ISR_Get_level( void ); + +#if defined(AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE) +uint64_t AArch64_interrupt_disable( void ); +void AArch64_interrupt_enable( uint64_t level ); +void AArch64_interrupt_flash( uint64_t level ); +#else +static inline uint64_t AArch64_interrupt_disable( void ) +{ + uint64_t level = _CPU_ISR_Get_level(); + __asm__ volatile ( + "msr DAIFSet, #0x2\n" + ); + return level; +} + +static inline void AArch64_interrupt_enable( uint64_t level ) +{ + __asm__ volatile ( + "msr DAIF, %[level]\n" + : : [level] "r" (level) + ); +} + +static inline void AArch64_interrupt_flash( uint64_t level ) +{ + AArch64_interrupt_enable(level); + AArch64_interrupt_disable(); +} +#endif /* !AARCH64_DISABLE_INLINE_ISR_DISABLE_ENABLE */ + +#define _CPU_ISR_Disable( _isr_cookie ) \ + do { \ + _isr_cookie = AArch64_interrupt_disable(); \ + } while (0) + +#define _CPU_ISR_Enable( _isr_cookie ) \ + AArch64_interrupt_enable( _isr_cookie ) + +#define _CPU_ISR_Flash( _isr_cookie ) \ + AArch64_interrupt_flash( _isr_cookie ) + +RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint64_t level ) +{ + return ( level & AARCH64_PSTATE_I ) == 0; +} + +void _CPU_Context_Initialize( + Context_Control *the_context, + void *stack_area_begin, + size_t stack_area_size, + uint64_t new_level, + void (*entry_point)( void ), + bool is_fp, + void *tls_area +); + +#define _CPU_Context_Get_SP( _context ) \ + (_context)->register_sp + +#ifdef RTEMS_SMP + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return context->is_executing; + } + + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + context->is_executing = is_executing; + } +#endif + +#define _CPU_Context_Restart_self( _the_context ) \ + _CPU_Context_restore( (_the_context) ); + +#define _CPU_Context_Initialize_fp( _destination ) \ + do { \ + *(*(_destination)) = _CPU_Null_fp_context; \ + } while (0) + +#define _CPU_Fatal_halt( _source, _err ) \ + do { \ + uint64_t _level; \ + uint32_t _error = _err; \ + _CPU_ISR_Disable( _level ); \ + (void) _level; \ + __asm__ volatile ("mov x0, %0\n" \ + : "=r" (_error) \ + : "0" (_error) \ + : "x0" ); \ + while (1); \ + } while (0); + +/** + * @brief CPU initialization. + */ +void _CPU_Initialize( void ); + +typedef void ( *CPU_ISR_handler )( void ); + +void _CPU_ISR_install_vector( + uint32_t vector, + CPU_ISR_handler new_handler, + CPU_ISR_handler *old_handler +); + +/** + * @brief CPU switch context. + */ +void _CPU_Context_switch( Context_Control *run, Context_Control *heir ); + +void _CPU_Context_restore( Context_Control *new_context ) + RTEMS_NO_RETURN; + +#ifdef RTEMS_SMP + uint32_t _CPU_SMP_Initialize( void ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + void _CPU_SMP_Prepare_start_multitasking( void ); + + static inline uint32_t _CPU_SMP_Get_current_processor( void ) + { + uint32_t mpidr; + + __asm__ volatile ( + "mrs %[mpidr], mpidr_el1\n" + : [mpidr] "=&r" (mpidr) + ); + + return mpidr & 0xffU; + } + + void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ); + + static inline void _AARCH64_Send_event( void ) + { + __asm__ volatile ( "sev" : : : "memory" ); + } + + static inline void _AARCH64_Wait_for_event( void ) + { + __asm__ volatile ( "wfe" : : : "memory" ); + } + + static inline void _CPU_SMP_Processor_event_broadcast( void ) + { + _AARCH64_Data_synchronization_barrier(); + _AARCH64_Send_event(); + } + + static inline void _CPU_SMP_Processor_event_receive( void ) + { + _AARCH64_Wait_for_event(); + _AARCH64_Data_memory_barrier(); + } +#endif + + +static inline uint32_t CPU_swap_u32( uint32_t value ) +{ + uint32_t tmp = value; /* make compiler warnings go away */ + __asm__ volatile ("EOR %1, %0, %0, ROR #16\n" + "BIC %1, %1, #0xff0000\n" + "MOV %0, %0, ROR #8\n" + "EOR %0, %0, %1, LSR #8\n" + : "=r" (value), "=r" (tmp) + : "0" (value), "1" (tmp)); + return value; +} + +static inline uint16_t CPU_swap_u16( uint16_t value ) +{ + return (uint16_t) (((value & 0xffU) << 8) | ((value >> 8) & 0xffU)); +} + +typedef uint32_t CPU_Counter_ticks; + +uint32_t _CPU_Counter_frequency( void ); + +CPU_Counter_ticks _CPU_Counter_read( void ); + +static inline CPU_Counter_ticks _CPU_Counter_difference( + CPU_Counter_ticks second, + CPU_Counter_ticks first +) +{ + return second - first; +} + +void *_CPU_Thread_Idle_body( uintptr_t ignored ); + +typedef enum { + AARCH64_EXCEPTION_SP0_SYNCHRONOUS = 0, + AARCH64_EXCEPTION_SP0_IRQ = 1, + AARCH64_EXCEPTION_SP0_FIQ = 2, + AARCH64_EXCEPTION_SP0_SERROR = 3, + AARCH64_EXCEPTION_SPx_SYNCHRONOUS = 4, + AARCH64_EXCEPTION_SPx_IRQ = 5, + AARCH64_EXCEPTION_SPx_FIQ = 6, + AARCH64_EXCEPTION_SPx_SERROR = 7, + AARCH64_EXCEPTION_LEL64_SYNCHRONOUS = 8, + AARCH64_EXCEPTION_LEL64_IRQ = 9, + AARCH64_EXCEPTION_LEL64_FIQ = 10, + AARCH64_EXCEPTION_LEL64_SERROR = 11, + AARCH64_EXCEPTION_LEL32_SYNCHRONOUS = 12, + AARCH64_EXCEPTION_LEL32_IRQ = 13, + AARCH64_EXCEPTION_LEL32_FIQ = 14, + AARCH64_EXCEPTION_LEL32_SERROR = 15, + MAX_EXCEPTIONS = 16, + AARCH64_EXCEPTION_MAKE_ENUM_64_BIT = 0xffffffffffffffff +} AArch64_symbolic_exception_name; + +#define VECTOR_POINTER_OFFSET 0x78 +#define VECTOR_ENTRY_SIZE 0x80 +void _AArch64_Exception_interrupt_no_nest( void ); +void _AArch64_Exception_interrupt_nest( void ); +static inline void* AArch64_set_exception_handler( + AArch64_symbolic_exception_name exception, + void (*handler)(void) +) +{ + // get current table address + char *vbar = (char*)AArch64_get_vector_base_address(); + // calculate address of vector to be replaced + char *cvector_address = vbar + VECTOR_ENTRY_SIZE * exception + VECTOR_POINTER_OFFSET; + // get current vector pointer + void (**vector_address)(void) = (void(**)(void))cvector_address; + void (*current_vector_pointer)(void); + current_vector_pointer = *vector_address; + // replace vector pointer + *vector_address = handler; + // return now-previous vector pointer + return (void*)current_vector_pointer; +} + +typedef struct { + uint64_t register_x0; + uint64_t register_x1; + uint64_t register_x2; + uint64_t register_x3; + uint64_t register_x4; + uint64_t register_x5; + uint64_t register_x6; + uint64_t register_x7; + uint64_t register_x8; + uint64_t register_x9; + uint64_t register_x10; + uint64_t register_x11; + uint64_t register_x12; + uint64_t register_x13; + uint64_t register_x14; + uint64_t register_x15; + uint64_t register_x16; + uint64_t register_x17; + uint64_t register_x18; + uint64_t register_x19; + uint64_t register_x20; + uint64_t register_x21; + uint64_t register_x22; + uint64_t register_x23; + uint64_t register_x24; + uint64_t register_x25; + uint64_t register_x26; + uint64_t register_x27; + uint64_t register_x28; + uint64_t register_fp; + void *register_lr; +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 + uint32_t _register_lr_top; +#endif + uint64_t register_sp; + void *register_pc; +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 + uint32_t _register_pc_top; +#endif + uint64_t register_daif; + uint64_t register_cpsr; + uint64_t register_syndrome; + uint64_t register_fault_address; + AArch64_symbolic_exception_name vector; + uint64_t reserved_for_stack_alignment; + uint64_t register_fpsr; + uint64_t register_fpcr; + uint128_t register_q0; + uint128_t register_q1; + uint128_t register_q2; + uint128_t register_q3; + uint128_t register_q4; + uint128_t register_q5; + uint128_t register_q6; + uint128_t register_q7; + uint128_t register_q8; + uint128_t register_q9; + uint128_t register_q10; + uint128_t register_q11; + uint128_t register_q12; + uint128_t register_q13; + uint128_t register_q14; + uint128_t register_q15; + uint128_t register_q16; + uint128_t register_q17; + uint128_t register_q18; + uint128_t register_q19; + uint128_t register_q20; + uint128_t register_q21; + uint128_t register_q22; + uint128_t register_q23; + uint128_t register_q24; + uint128_t register_q25; + uint128_t register_q26; + uint128_t register_q27; + uint128_t register_q28; + uint128_t register_q29; + uint128_t register_q30; + uint128_t register_q31; +} CPU_Exception_frame; + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ); + +void _AArch64_Exception_default( CPU_Exception_frame *frame ); + +/** Type that can store a 32-bit integer or a pointer. */ +typedef uintptr_t CPU_Uint32ptr; + +#ifdef __cplusplus +} +#endif + +#endif /* ASM */ + +/** @} */ + +#endif /* _RTEMS_SCORE_CPU_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h new file mode 100644 index 0000000000..ca9fc0c707 --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef _RTEMS_SCORE_ATOMIC_CPU_H +#define _RTEMS_SCORE_ATOMIC_CPU_H + +#include <rtems/score/cpustdatomic.h> + +#endif /* _RTEMS_SCORE_ATOMIC_CPU_H */ diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h new file mode 100644 index 0000000000..de741440df --- /dev/null +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h @@ -0,0 +1,81 @@ +/** + * @file + * + * @brief CPU Port Implementation API + */ + +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2020 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore <kinsey.mo...@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. + */ + +#ifndef _RTEMS_SCORE_CPUIMPL_H +#define _RTEMS_SCORE_CPUIMPL_H + +#include <rtems/score/cpu.h> + +/** + * @defgroup RTEMSScoreCPUAArch64 AArch64 + * + * @ingroup RTEMSScoreCPU + * + * @brief ARM AArch64 Architecture Support + * + * @{ + */ + +#define CPU_PER_CPU_CONTROL_SIZE 0 +#define CPU_INTERRUPT_FRAME_SIZE 240 + +#ifndef ASM + +#ifdef __cplusplus +extern "C" { +#endif + +void _CPU_Context_volatile_clobber( uintptr_t pattern ); + +void _CPU_Context_validate( uintptr_t pattern ); + +RTEMS_INLINE_ROUTINE void _CPU_Instruction_illegal( void ) +{ + __asm__ volatile ( ".inst 0x0" ); +} + +RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void ) +{ + __asm__ volatile ( "nop" ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ASM */ + +/** @} */ + +#endif /* _RTEMS_SCORE_CPUIMPL_H */ diff --git a/spec/build/cpukit/cpuaarch64.yml b/spec/build/cpukit/cpuaarch64.yml new file mode 100644 index 0000000000..ae10055f8b --- /dev/null +++ b/spec/build/cpukit/cpuaarch64.yml @@ -0,0 +1,32 @@ +build-type: objects +cflags: [] +cppflags: [] +cxxflags: [] +enabled-by: +- aarch64 +includes: [] +install: +- destination: ${BSP_INCLUDEDIR}/libcpu + source: + - cpukit/score/cpu/arm/include/libcpu/vectors.h +- destination: ${BSP_INCLUDEDIR}/rtems + source: + - cpukit/score/cpu/aarch64/include/rtems/asm.h +- destination: ${BSP_INCLUDEDIR}/rtems/score + source: + - cpukit/score/cpu/aarch64/include/rtems/score/cpu.h + - cpukit/score/cpu/aarch64/include/rtems/score/cpuatomic.h + - cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h + - cpukit/score/cpu/aarch64/include/rtems/score/aarch64.h +links: [] +source: +- cpukit/score/cpu/aarch64/cpu.c +- cpukit/score/cpu/aarch64/cpu_asm.S +- cpukit/score/cpu/aarch64/aarch64-context-validate.S +- cpukit/score/cpu/aarch64/aarch64-context-volatile-clobber.S +- cpukit/score/cpu/aarch64/aarch64-thread-idle.c +- cpukit/score/cpu/aarch64/aarch64-exception-default.c +- cpukit/score/cpu/aarch64/aarch64-exception-default.S +- cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S +- cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c +type: build diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml index e3606dbdc8..f835cecb45 100644 --- a/spec/build/cpukit/librtemscpu.yml +++ b/spec/build/cpukit/librtemscpu.yml @@ -456,6 +456,8 @@ install: - cpukit/include/uuid/uuid.h install-path: ${BSP_LIBDIR} links: +- role: build-dependency + uid: cpuaarch64 - role: build-dependency uid: cpuarm - role: build-dependency -- 2.20.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel