From 955c045b3c66c26899d65dde744d5647588ca91c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 22 Jun 2021 15:28:13 +0200 Subject: sparc: Move ISR handler install routines Move _CPU_ISR_install_raw_handler() and _CPU_ISR_install_vector() to separate files. The goal is to make their use optional. Update #4458. Update #4459. --- cpukit/Makefile.am | 1 + cpukit/score/cpu/sparc/cpu.c | 181 ++------------------------- cpukit/score/cpu/sparc/sparc-isr-install.c | 194 +++++++++++++++++++++++++++++ spec/build/cpukit/cpusparc.yml | 1 + 4 files changed, 203 insertions(+), 174 deletions(-) create mode 100644 cpukit/score/cpu/sparc/sparc-isr-install.c diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 25382f38ca..8947d7eb5a 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -1621,6 +1621,7 @@ librtemscpu_a_SOURCES += score/cpu/sparc/sparc-access.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-validate.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-volatile-clobber.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter-asm.S +librtemscpu_a_SOURCES += score/cpu/sparc/sparc-isr-install.c librtemscpu_a_SOURCES += score/cpu/sparc/syscall.S librtemscpu_a_SOURCES += score/cpu/sparc/window.S diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c index 9f84c28fc5..a7bf7dfcaf 100644 --- a/cpukit/score/cpu/sparc/cpu.c +++ b/cpukit/score/cpu/sparc/cpu.c @@ -1,7 +1,12 @@ /** - * @file + * @file * - * @brief SPARC CPU Dependent Source + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This source file contains static assertions to ensure the consistency + * of interfaces used in C and assembler and it contains the SPARC-specific + * implementation of _CPU_Initialize(), _CPU_ISR_Get_level(), and + * _CPU_Context_Initialize(). */ /* @@ -19,11 +24,9 @@ #include "config.h" #endif -#include #include #include #include -#include #if SPARC_HAS_FPU == 1 RTEMS_STATIC_ASSERT( @@ -144,22 +147,6 @@ RTEMS_STATIC_ASSERT( CPU_Interrupt_frame_alignment ); -/* - * This initializes the set of opcodes placed in each trap - * table entry. The routine which installs a handler is responsible - * for filling in the fields for the _handler address and the _vector - * trap type. - * - * The constants following this structure are masks for the fields which - * must be filled in when the handler is installed. - */ -const CPU_Trap_table_entry _CPU_Trap_slot_template = { - 0xa1480000, /* mov %psr, %l0 */ - 0x29000000, /* sethi %hi(_handler), %l4 */ - 0x81c52000, /* jmp %l4 + %lo(_handler) */ - 0xa6102000 /* mov _vector, %l3 */ -}; - /* * _CPU_Initialize * @@ -197,160 +184,6 @@ uint32_t _CPU_ISR_Get_level( void ) return level; } -/* - * _CPU_ISR_install_raw_handler - * - * This routine installs the specified handler as a "raw" non-executive - * supported trap handler (a.k.a. interrupt service routine). - * - * Input Parameters: - * vector - trap table entry number plus synchronous - * vs. asynchronous information - * new_handler - address of the handler to be installed - * old_handler - pointer to an address of the handler previously installed - * - * Output Parameters: NONE - * *new_handler - address of the handler previously installed - * - * NOTE: - * - * On the SPARC, there are really only 256 vectors. However, the executive - * has no easy, fast, reliable way to determine which traps are synchronous - * and which are asynchronous. By default, synchronous traps return to the - * instruction which caused the interrupt. So if you install a software - * trap handler as an executive interrupt handler (which is desirable since - * RTEMS takes care of window and register issues), then the executive needs - * to know that the return address is to the trap rather than the instruction - * following the trap. - * - * So vectors 0 through 255 are treated as regular asynchronous traps which - * provide the "correct" return address. Vectors 256 through 512 are assumed - * by the executive to be synchronous and to require that the return address - * be fudged. - * - * If you use this mechanism to install a trap handler which must reexecute - * the instruction which caused the trap, then it should be installed as - * an asynchronous trap. This will avoid the executive changing the return - * address. - */ - -void _CPU_ISR_install_raw_handler( - uint32_t vector, - CPU_ISR_raw_handler new_handler, - CPU_ISR_raw_handler *old_handler -) -{ - uint32_t real_vector; - CPU_Trap_table_entry *tbr; - CPU_Trap_table_entry *slot; - uint32_t u32_tbr; - uint32_t u32_handler; - - /* - * Get the "real" trap number for this vector ignoring the synchronous - * versus asynchronous indicator included with our vector numbers. - */ - - real_vector = SPARC_REAL_TRAP_NUMBER( vector ); - - /* - * Get the current base address of the trap table and calculate a pointer - * to the slot we are interested in. - */ - - sparc_get_tbr( u32_tbr ); - - u32_tbr &= 0xfffff000; - - tbr = (CPU_Trap_table_entry *) u32_tbr; - - slot = &tbr[ real_vector ]; - - /* - * Get the address of the old_handler from the trap table. - * - * NOTE: The old_handler returned will be bogus if it does not follow - * the RTEMS model. - */ - -#define HIGH_BITS_MASK 0xFFFFFC00 -#define HIGH_BITS_SHIFT 10 -#define LOW_BITS_MASK 0x000003FF - - if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { - u32_handler = - (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) | - (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); - *old_handler = (CPU_ISR_raw_handler) u32_handler; - } else - *old_handler = 0; - - /* - * Copy the template to the slot and then fix it. - */ - - *slot = _CPU_Trap_slot_template; - - u32_handler = (uint32_t) new_handler; - - slot->mov_vector_l3 |= vector; - slot->sethi_of_handler_to_l4 |= - (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; - slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); - - /* - * There is no instruction cache snooping, so we need to invalidate - * the instruction cache to make sure that the processor sees the - * changes to the trap table. This step is required on both single- - * and multiprocessor systems. - * - * In a SMP configuration a change to the trap table might be - * missed by other cores. If the system state is up, the other - * cores can be notified using SMP messages that they need to - * flush their icache. If the up state has not been reached - * there is no need to notify other cores. They will do an - * automatic flush of the icache just after entering the up - * state, but before enabling interrupts. - */ - rtems_cache_invalidate_entire_instruction(); -} - -void _CPU_ISR_install_vector( - uint32_t vector, - CPU_ISR_handler new_handler, - CPU_ISR_handler *old_handler -) -{ - uint32_t real_vector; - CPU_ISR_raw_handler ignored; - - /* - * Get the "real" trap number for this vector ignoring the synchronous - * versus asynchronous indicator included with our vector numbers. - */ - - real_vector = SPARC_REAL_TRAP_NUMBER( vector ); - - /* - * Return the previous ISR handler. - */ - - *old_handler = _ISR_Vector_table[ real_vector ]; - - /* - * Install the wrapper so this ISR can be invoked properly. - */ - - _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored ); - - /* - * We put the actual user ISR address in '_ISR_vector_table'. This will - * be used by the _ISR_Handler so the user gets control. - */ - - _ISR_Vector_table[ real_vector ] = new_handler; -} - void _CPU_Context_Initialize( Context_Control *the_context, uint32_t *stack_base, diff --git a/cpukit/score/cpu/sparc/sparc-isr-install.c b/cpukit/score/cpu/sparc/sparc-isr-install.c new file mode 100644 index 0000000000..017173c489 --- /dev/null +++ b/cpukit/score/cpu/sparc/sparc-isr-install.c @@ -0,0 +1,194 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This source file contains the SPARC-specific implementation of + * _CPU_ISR_install_raw_handler() and _CPU_ISR_install_vector(). + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* + * This initializes the set of opcodes placed in each trap + * table entry. The routine which installs a handler is responsible + * for filling in the fields for the _handler address and the _vector + * trap type. + * + * The constants following this structure are masks for the fields which + * must be filled in when the handler is installed. + */ +const CPU_Trap_table_entry _CPU_Trap_slot_template = { + 0xa1480000, /* mov %psr, %l0 */ + 0x29000000, /* sethi %hi(_handler), %l4 */ + 0x81c52000, /* jmp %l4 + %lo(_handler) */ + 0xa6102000 /* mov _vector, %l3 */ +}; + +/* + * _CPU_ISR_install_raw_handler + * + * This routine installs the specified handler as a "raw" non-executive + * supported trap handler (a.k.a. interrupt service routine). + * + * Input Parameters: + * vector - trap table entry number plus synchronous + * vs. asynchronous information + * new_handler - address of the handler to be installed + * old_handler - pointer to an address of the handler previously installed + * + * Output Parameters: NONE + * *new_handler - address of the handler previously installed + * + * NOTE: + * + * On the SPARC, there are really only 256 vectors. However, the executive + * has no easy, fast, reliable way to determine which traps are synchronous + * and which are asynchronous. By default, synchronous traps return to the + * instruction which caused the interrupt. So if you install a software + * trap handler as an executive interrupt handler (which is desirable since + * RTEMS takes care of window and register issues), then the executive needs + * to know that the return address is to the trap rather than the instruction + * following the trap. + * + * So vectors 0 through 255 are treated as regular asynchronous traps which + * provide the "correct" return address. Vectors 256 through 512 are assumed + * by the executive to be synchronous and to require that the return address + * be fudged. + * + * If you use this mechanism to install a trap handler which must reexecute + * the instruction which caused the trap, then it should be installed as + * an asynchronous trap. This will avoid the executive changing the return + * address. + */ + +void _CPU_ISR_install_raw_handler( + uint32_t vector, + CPU_ISR_raw_handler new_handler, + CPU_ISR_raw_handler *old_handler +) +{ + uint32_t real_vector; + CPU_Trap_table_entry *tbr; + CPU_Trap_table_entry *slot; + uint32_t u32_tbr; + uint32_t u32_handler; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); + + /* + * Get the current base address of the trap table and calculate a pointer + * to the slot we are interested in. + */ + + sparc_get_tbr( u32_tbr ); + + u32_tbr &= 0xfffff000; + + tbr = (CPU_Trap_table_entry *) u32_tbr; + + slot = &tbr[ real_vector ]; + + /* + * Get the address of the old_handler from the trap table. + * + * NOTE: The old_handler returned will be bogus if it does not follow + * the RTEMS model. + */ + +#define HIGH_BITS_MASK 0xFFFFFC00 +#define HIGH_BITS_SHIFT 10 +#define LOW_BITS_MASK 0x000003FF + + if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { + u32_handler = + (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) | + (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); + *old_handler = (CPU_ISR_raw_handler) u32_handler; + } else + *old_handler = 0; + + /* + * Copy the template to the slot and then fix it. + */ + + *slot = _CPU_Trap_slot_template; + + u32_handler = (uint32_t) new_handler; + + slot->mov_vector_l3 |= vector; + slot->sethi_of_handler_to_l4 |= + (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; + slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); + + /* + * There is no instruction cache snooping, so we need to invalidate + * the instruction cache to make sure that the processor sees the + * changes to the trap table. This step is required on both single- + * and multiprocessor systems. + * + * In a SMP configuration a change to the trap table might be + * missed by other cores. If the system state is up, the other + * cores can be notified using SMP messages that they need to + * flush their icache. If the up state has not been reached + * there is no need to notify other cores. They will do an + * automatic flush of the icache just after entering the up + * state, but before enabling interrupts. + */ + rtems_cache_invalidate_entire_instruction(); +} + +void _CPU_ISR_install_vector( + uint32_t vector, + CPU_ISR_handler new_handler, + CPU_ISR_handler *old_handler +) +{ + uint32_t real_vector; + CPU_ISR_raw_handler ignored; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); + + /* + * Return the previous ISR handler. + */ + + *old_handler = _ISR_Vector_table[ real_vector ]; + + /* + * Install the wrapper so this ISR can be invoked properly. + */ + + _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored ); + + /* + * We put the actual user ISR address in '_ISR_vector_table'. This will + * be used by the _ISR_Handler so the user gets control. + */ + + _ISR_Vector_table[ real_vector ] = new_handler; +} diff --git a/spec/build/cpukit/cpusparc.yml b/spec/build/cpukit/cpusparc.yml index 85fbdc4b3c..10dabed494 100644 --- a/spec/build/cpukit/cpusparc.yml +++ b/spec/build/cpukit/cpusparc.yml @@ -37,6 +37,7 @@ source: - cpukit/score/cpu/sparc/sparc-context-validate.S - cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S - cpukit/score/cpu/sparc/sparc-counter-asm.S +- cpukit/score/cpu/sparc/sparc-isr-install.c - cpukit/score/cpu/sparc/syscall.S - cpukit/score/cpu/sparc/window.S type: build -- cgit v1.2.3