diff --git a/bsps/aarch64/include/bsp/aarch64-mmu.h b/bsps/aarch64/include/bsp/aarch64-mmu.h index c2a16649cc..6f24de761a 100644 --- a/bsps/aarch64/include/bsp/aarch64-mmu.h +++ b/bsps/aarch64/include/bsp/aarch64-mmu.h @@ -117,13 +117,9 @@ typedef struct { .end = (uintptr_t) bsp_translation_table_end, \ .flags = AARCH64_MMU_DATA_RW_CACHED \ }, { \ -/* - * The vector table must be in writable and executable memory as it stores both - * exception code and the mutable pointer to which it jumps - */ \ .begin = (uintptr_t) bsp_start_vector_table_begin, \ .end = (uintptr_t) bsp_start_vector_table_end, \ - .flags = AARCH64_MMU_CODE_RW_CACHED \ + .flags = AARCH64_MMU_CODE_CACHED \ } /** diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-default.S b/cpukit/score/cpu/aarch64/aarch64-exception-default.S index c7c9d03465..778b68d3a6 100644 --- a/cpukit/score/cpu/aarch64/aarch64-exception-default.S +++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.S @@ -44,11 +44,29 @@ #include .extern _AArch64_Exception_default +.extern aarch64_exception_sp0_synchronous +.extern aarch64_exception_sp0_irq +.extern aarch64_exception_sp0_fiq +.extern aarch64_exception_sp0_serror +.extern aarch64_exception_spx_synchronous +.extern aarch64_exception_spx_irq +.extern aarch64_exception_spx_fiq +.extern aarch64_exception_spx_serror +.extern aarch64_exception_lel64_synchronous +.extern aarch64_exception_lel64_irq +.extern aarch64_exception_lel64_fiq +.extern aarch64_exception_lel64_serror +.extern aarch64_exception_lel32_synchronous +.extern aarch64_exception_lel32_irq +.extern aarch64_exception_lel32_fiq +.extern aarch64_exception_lel32_serror .globl bsp_start_vector_table_begin .globl bsp_start_vector_table_end .globl bsp_start_vector_table_size .globl bsp_vector_table_size +.globl aarch64_exception_dump_sp0 +.globl aarch64_exception_dump_spx .section ".text" @@ -72,64 +90,24 @@ * * The exception returns to the previous execution state */ +#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 +#define JUMP_REG(reg_num) w##reg_num +#else +#define JUMP_REG(reg_num) x##reg_num +#endif + .macro JUMP_HANDLER -/* Mask to use in BIC, lower 7 bits */ - mov x0, #0x7f -/* LR contains PC, mask off to the base of the current vector */ - bic x0, lr, x0 -/* Load address from the last word in the vector */ - ldr x0, [x0, #0x78] +/* x0 holds the address of the variable that holds the jump target */ + ldr JUMP_REG(0), [x0] /* * Branch and link to the address in x0. There is no reason to save the current - * LR since it has already been saved and the current contents are junk. + * LR since it has already been saved. */ blr x0 /* Pop x0,lr from stack */ ldp x0, lr, [sp], #0x10 /* Return from exception */ eret - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - .endm - - .macro JUMP_TARGET_SP0 -/* Takes up the space of 2 instructions */ -#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 - .word .print_exception_dump_sp0 - .word 0x0 -#else - .dword .print_exception_dump_sp0 -#endif - .endm - - .macro JUMP_TARGET_SPx -/* Takes up the space of 2 instructions */ -#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 - .word .print_exception_dump_spx - .word 0x0 -#else - .dword .print_exception_dump_spx -#endif .endm bsp_start_vector_table_begin: @@ -152,7 +130,8 @@ curr_el_sp0_sync: curr_el_sp0_sync_get_pc: /* The current PC is now in LR */ mov x0, #0x7f /* Mask to use in BIC, lower 7 bits */ bic x0, lr, x0 /* Mask LR to base of current vector */ - ldr x1, [x0, #0x78] /* Load target from last word in vector */ + ldr JUMP_REG(1), =aarch64_exception_sp0_synchronous + ldr JUMP_REG(1), [x1] and lr, lr, #0x780 /* Mask off bits for vector number */ lsr lr, lr, #7 /* Shift the vector bits down */ /* Store the vector */ @@ -160,44 +139,18 @@ curr_el_sp0_sync_get_pc: /* The current PC is now in LR */ mov x0, sp blr x1 b twiddle - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop -/* Takes up the space of 2 instructions */ -#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 - .word _AArch64_Exception_default - .word 0x0 -#else - .dword _AArch64_Exception_default -#endif .balign 0x80 /* The exception handler for IRQ exceptions from the current EL using SP0. */ curr_el_sp0_irq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_sp0_irq_get_pc /* Get current execution address */ -curr_el_sp0_irq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_sp0_synchronous JUMP_HANDLER - JUMP_TARGET_SP0 .balign 0x80 /* The exception handler for FIQ exceptions from the current EL using SP0. */ curr_el_sp0_fiq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_sp0_fiq_get_pc /* Get current execution address */ -curr_el_sp0_fiq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_sp0_fiq JUMP_HANDLER - JUMP_TARGET_SP0 .balign 0x80 /* * The exception handler for system error exceptions from the current EL using @@ -205,10 +158,8 @@ curr_el_sp0_fiq_get_pc: /* The current PC is now in LR */ */ curr_el_sp0_serror: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_sp0_serror_get_pc /* Get current execution address */ -curr_el_sp0_serror_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_sp0_serror JUMP_HANDLER - JUMP_TARGET_SP0 .balign 0x80 /* * The exception handler for synchronous exceptions from the current EL using @@ -230,7 +181,8 @@ curr_el_spx_sync: curr_el_spx_sync_get_pc: /* The current PC is now in LR */ mov x0, #0x7f /* Mask to use in BIC, lower 7 bits */ bic x0, lr, x0 /* Mask LR to base of current vector */ - ldr x1, [x0, #0x78] /* Load target from last word in vector */ + ldr JUMP_REG(1), =aarch64_exception_spx_synchronous + ldr JUMP_REG(1), [x1] and lr, lr, #0x780 /* Mask off bits for vector number */ lsr lr, lr, #7 /* Shift the vector bits down */ /* Store the vector */ @@ -238,25 +190,6 @@ curr_el_spx_sync_get_pc: /* The current PC is now in LR */ mov x0, sp blr x1 b twiddle - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop -/* Takes up the space of 2 instructions */ -#ifdef AARCH64_MULTILIB_ARCH_V8_ILP32 - .word _AArch64_Exception_default - .word 0x0 -#else - .dword _AArch64_Exception_default -#endif .balign 0x80 /* * The exception handler for IRQ exceptions from the current EL using the @@ -264,10 +197,8 @@ curr_el_spx_sync_get_pc: /* The current PC is now in LR */ */ curr_el_spx_irq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_spx_irq_get_pc /* Get current execution address */ -curr_el_spx_irq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_spx_irq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for FIQ exceptions from the current EL using the @@ -275,10 +206,8 @@ curr_el_spx_irq_get_pc: /* The current PC is now in LR */ */ curr_el_spx_fiq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_spx_fiq_get_pc /* Get current execution address */ -curr_el_spx_fiq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_spx_fiq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for system error exceptions from the current EL using @@ -286,36 +215,28 @@ curr_el_spx_fiq_get_pc: /* The current PC is now in LR */ */ curr_el_spx_serror: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl curr_el_spx_serror_get_pc /* Get current execution address */ -curr_el_spx_serror_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_spx_serror JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for synchronous exceptions from a lower EL (AArch64). */ lower_el_aarch64_sync: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch64_sync_get_pc /* Get current execution address */ -lower_el_aarch64_sync_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel64_synchronous JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* The exception handler for IRQ exceptions from a lower EL (AArch64). */ lower_el_aarch64_irq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch64_irq_get_pc /* Get current execution address */ -lower_el_aarch64_irq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel64_irq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* The exception handler for FIQ exceptions from a lower EL (AArch64). */ lower_el_aarch64_fiq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch64_fiq_get_pc /* Get current execution address */ -lower_el_aarch64_fiq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel64_fiq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for system error exceptions from a lower EL(AArch64). @@ -323,37 +244,28 @@ lower_el_aarch64_fiq_get_pc: /* The current PC is now in LR */ lower_el_aarch64_serror: /* Push x0,lr on to the stack */ stp x0, lr, [sp, #-0x10]! -/* Get current execution address */ - bl lower_el_aarch64_serror_get_pc -lower_el_aarch64_serror_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel64_serror JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for the synchronous exception from a lower EL(AArch32). */ lower_el_aarch32_sync: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch32_sync_get_pc /* Get current execution address */ -lower_el_aarch32_sync_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel32_synchronous JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* The exception handler for the IRQ exception from a lower EL (AArch32). */ lower_el_aarch32_irq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch32_irq_get_pc /* Get current execution address */ -lower_el_aarch32_irq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel32_irq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* The exception handler for the FIQ exception from a lower EL (AArch32). */ lower_el_aarch32_fiq: stp x0, lr, [sp, #-0x10]! /* Push x0,lr on to the stack */ - bl lower_el_aarch32_fiq_get_pc /* Get current execution address */ -lower_el_aarch32_fiq_get_pc: /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel32_fiq JUMP_HANDLER - JUMP_TARGET_SPx .balign 0x80 /* * The exception handler for the system error exception from a lower EL @@ -362,11 +274,8 @@ lower_el_aarch32_fiq_get_pc: /* The current PC is now in LR */ lower_el_aarch32_serror: /* Push x0,lr on to the stack */ stp x0, lr, [sp, #-0x10]! -/* Get current execution address */ - bl lower_el_aarch32_serror_get_pc -lower_el_aarch32_serror_get_pc : /* The current PC is now in LR */ + ldr JUMP_REG(0), =aarch64_exception_lel32_fiq JUMP_HANDLER - JUMP_TARGET_SPx bsp_start_vector_table_end: @@ -378,7 +287,7 @@ bsp_start_vector_table_end: * and need to be retrieved while the lr upon entry contains the pointer into * the AArch64 vector table */ -.print_exception_dump_spx: +aarch64_exception_dump_spx: /* Switch to exception stack (SP0) */ msr spsel, #0 /* Save space for exception context */ @@ -416,7 +325,7 @@ bsp_start_vector_table_end: /* Just in case */ b twiddle -.print_exception_dump_sp0: +aarch64_exception_dump_sp0: /* Save space for exception context */ sub sp, sp, #AARCH64_EXCEPTION_FRAME_SIZE /* diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-targets.c b/cpukit/score/cpu/aarch64/aarch64-exception-targets.c new file mode 100644 index 0000000000..02eda6d993 --- /dev/null +++ b/cpukit/score/cpu/aarch64/aarch64-exception-targets.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreCPUAArch64 + * + * @brief This source file contains the jump targets for AArch64 exceptions. + */ + +/* + * Copyright (C) 2025 On-Line Applications Research Corporation (OAR) + * Written by Kinsey Moore + * + * 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 +#include + +void aarch64_exception_dump_sp0(void); +void aarch64_exception_dump_spx(void); + +AArch64_Exception_Handler aarch64_exception_sp0_synchronous = + (AArch64_Exception_Handler) &_AArch64_Exception_default; +AArch64_Exception_Handler aarch64_exception_sp0_irq = + &aarch64_exception_dump_sp0; +AArch64_Exception_Handler aarch64_exception_sp0_fiq = + &aarch64_exception_dump_sp0; +AArch64_Exception_Handler aarch64_exception_sp0_serror = + &aarch64_exception_dump_sp0; +AArch64_Exception_Handler aarch64_exception_spx_synchronous = + (AArch64_Exception_Handler) &_AArch64_Exception_default; +AArch64_Exception_Handler aarch64_exception_spx_irq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_spx_fiq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_spx_serror = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel64_synchronous = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel64_irq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel64_fiq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel64_serror = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel32_synchronous = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel32_irq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel32_fiq = + &aarch64_exception_dump_spx; +AArch64_Exception_Handler aarch64_exception_lel32_serror = + &aarch64_exception_dump_spx; diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h index 195919bac2..713d6acd03 100644 --- a/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpu.h @@ -407,40 +407,94 @@ typedef enum { AARCH64_EXCEPTION_MAKE_ENUM_64_BIT = INT_MAX } AArch64_symbolic_exception_name; +typedef void(*AArch64_Exception_Handler)(void); +extern AArch64_Exception_Handler aarch64_exception_sp0_synchronous; +extern AArch64_Exception_Handler aarch64_exception_sp0_irq; +extern AArch64_Exception_Handler aarch64_exception_sp0_fiq; +extern AArch64_Exception_Handler aarch64_exception_sp0_serror; +extern AArch64_Exception_Handler aarch64_exception_spx_synchronous; +extern AArch64_Exception_Handler aarch64_exception_spx_irq; +extern AArch64_Exception_Handler aarch64_exception_spx_fiq; +extern AArch64_Exception_Handler aarch64_exception_spx_serror; +extern AArch64_Exception_Handler aarch64_exception_lel64_synchronous; +extern AArch64_Exception_Handler aarch64_exception_lel64_irq; +extern AArch64_Exception_Handler aarch64_exception_lel64_fiq; +extern AArch64_Exception_Handler aarch64_exception_lel64_serror; +extern AArch64_Exception_Handler aarch64_exception_lel32_synchronous; +extern AArch64_Exception_Handler aarch64_exception_lel32_irq; +extern AArch64_Exception_Handler aarch64_exception_lel32_fiq; +extern AArch64_Exception_Handler aarch64_exception_lel32_serror; + #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( +static inline AArch64_Exception_Handler AArch64_set_exception_handler( AArch64_symbolic_exception_name exception, - void (*handler)(void) + AArch64_Exception_Handler handler ) { - /* get current table address */ - char *vbar = (char*)AArch64_get_vector_base_address(); + AArch64_Exception_Handler *target_address; + switch (exception) { + case AARCH64_EXCEPTION_SP0_SYNCHRONOUS: + target_address = &aarch64_exception_sp0_synchronous; + break; + case AARCH64_EXCEPTION_SP0_IRQ: + target_address = &aarch64_exception_sp0_irq; + break; + case AARCH64_EXCEPTION_SP0_FIQ: + target_address = &aarch64_exception_sp0_fiq; + break; + case AARCH64_EXCEPTION_SP0_SERROR: + target_address = &aarch64_exception_sp0_serror; + break; + case AARCH64_EXCEPTION_SPx_SYNCHRONOUS: + target_address = &aarch64_exception_spx_synchronous; + break; + case AARCH64_EXCEPTION_SPx_IRQ: + target_address = &aarch64_exception_spx_irq; + break; + case AARCH64_EXCEPTION_SPx_FIQ: + target_address = &aarch64_exception_spx_fiq; + break; + case AARCH64_EXCEPTION_SPx_SERROR: + target_address = &aarch64_exception_spx_serror; + break; + case AARCH64_EXCEPTION_LEL64_SYNCHRONOUS: + target_address = &aarch64_exception_lel64_synchronous; + break; + case AARCH64_EXCEPTION_LEL64_IRQ: + target_address = &aarch64_exception_lel64_irq; + break; + case AARCH64_EXCEPTION_LEL64_FIQ: + target_address = &aarch64_exception_lel64_fiq; + break; + case AARCH64_EXCEPTION_LEL64_SERROR: + target_address = &aarch64_exception_lel64_serror; + break; + case AARCH64_EXCEPTION_LEL32_SYNCHRONOUS: + target_address = &aarch64_exception_lel32_synchronous; + break; + case AARCH64_EXCEPTION_LEL32_IRQ: + target_address = &aarch64_exception_lel32_irq; + break; + case AARCH64_EXCEPTION_LEL32_FIQ: + target_address = &aarch64_exception_lel32_fiq; + break; + case AARCH64_EXCEPTION_LEL32_SERROR: + target_address = &aarch64_exception_lel32_serror; + break; + default: + return NULL; + } - /* 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; + AArch64_Exception_Handler current_vector_pointer = *target_address; /* replace vector pointer */ - *vector_address = handler; + *target_address = handler; /* return now-previous vector pointer */ - -/* - * This was put in to fix the following warning: - * warning: ISO C forbids conversion of function pointer to object pointer type. - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - return (void*)current_vector_pointer; -#pragma GCC diagnostic pop + return current_vector_pointer; } typedef struct { diff --git a/spec/build/cpukit/cpuaarch64.yml b/spec/build/cpukit/cpuaarch64.yml index 603cdeb071..1f7e697fbd 100644 --- a/spec/build/cpukit/cpuaarch64.yml +++ b/spec/build/cpukit/cpuaarch64.yml @@ -37,6 +37,7 @@ source: - cpukit/score/cpu/aarch64/aarch64-exception-frame-print.c - cpukit/score/cpu/aarch64/aarch64-exception-interrupt.S - cpukit/score/cpu/aarch64/aarch64-exception-resume.S +- cpukit/score/cpu/aarch64/aarch64-exception-targets.c - cpukit/score/cpu/aarch64/aarch64-thread-idle.c - cpukit/score/cpu/aarch64/cpu.c - cpukit/score/cpu/aarch64/cpu_asm.S