diff options
Diffstat (limited to 'cpukit/score/cpu/sparc')
23 files changed, 1821 insertions, 665 deletions
diff --git a/cpukit/score/cpu/sparc/access_le.c b/cpukit/score/cpu/sparc/access_le.c index d3a0e93adb..b1bde6da4b 100644 --- a/cpukit/score/cpu/sparc/access_le.c +++ b/cpukit/score/cpu/sparc/access_le.c @@ -1,12 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* * Little-endian access routines for SPARC * * COPYRIGHT (c) 2011 * Aeroflex Gaisler. * - * 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. + * 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 <libcpu/byteorder.h> diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c index 9f84c28fc5..c82fa935fe 100644 --- a/cpukit/score/cpu/sparc/cpu.c +++ b/cpukit/score/cpu/sparc/cpu.c @@ -1,29 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** - * @file + * @file + * + * @ingroup RTEMSScoreCPUSPARC * - * @brief SPARC CPU Dependent Source + * @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(). */ /* * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2017 embedded brains GmbH + * Copyright (c) 2017 embedded brains GmbH & Co. KG + * + * 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. * - * 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. + * 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/isr.h> #include <rtems/score/percpu.h> #include <rtems/score/tls.h> #include <rtems/score/thread.h> -#include <rtems/rtems/cache.h> #if SPARC_HAS_FPU == 1 RTEMS_STATIC_ASSERT( @@ -144,21 +166,56 @@ 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 */ -}; +#define SPARC_ASSERT_REGISTER_WINDOW_OFFSET( member, off ) \ + RTEMS_STATIC_ASSERT( \ + offsetof( SPARC_Register_window, member ) == \ + RTEMS_XCONCAT( SPARC_REGISTER_WINDOW_OFFSET_, off ), \ + SPARC_Register_window ## member \ + ) + +SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 0 ], LOCAL( 0 ) ); +SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 1 ], LOCAL( 1 ) ); +SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 0 ], INPUT( 0 ) ); +SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 1 ], INPUT( 1 ) ); + +RTEMS_STATIC_ASSERT( + sizeof( SPARC_Register_window ) == SPARC_REGISTER_WINDOW_SIZE, + SPARC_REGISTER_WINDOW_SIZE +); + +#define SPARC_ASSERT_EXCEPTION_OFFSET( member, off ) \ + RTEMS_STATIC_ASSERT( \ + offsetof( CPU_Exception_frame, member ) == \ + RTEMS_XCONCAT( SPARC_EXCEPTION_OFFSET_, off ), \ + CPU_Exception_frame_offset_ ## member \ + ) + +SPARC_ASSERT_EXCEPTION_OFFSET( psr, PSR ); +SPARC_ASSERT_EXCEPTION_OFFSET( pc, PC ); +SPARC_ASSERT_EXCEPTION_OFFSET( npc, NPC ); +SPARC_ASSERT_EXCEPTION_OFFSET( trap, TRAP ); +SPARC_ASSERT_EXCEPTION_OFFSET( wim, WIM ); +SPARC_ASSERT_EXCEPTION_OFFSET( y, Y ); +SPARC_ASSERT_EXCEPTION_OFFSET( global[ 0 ], GLOBAL( 0 ) ); +SPARC_ASSERT_EXCEPTION_OFFSET( global[ 1 ], GLOBAL( 1 ) ); +SPARC_ASSERT_EXCEPTION_OFFSET( output[ 0 ], OUTPUT( 0 ) ); +SPARC_ASSERT_EXCEPTION_OFFSET( output[ 1 ], OUTPUT( 1 ) ); + +#if SPARC_HAS_FPU == 1 +SPARC_ASSERT_EXCEPTION_OFFSET( fsr, FSR ); +SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 0 ], FP( 0 ) ); +SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 1 ], FP( 1 ) ); +#endif + +RTEMS_STATIC_ASSERT( + sizeof( CPU_Exception_frame ) == SPARC_EXCEPTION_FRAME_SIZE, + SPARC_EXCEPTION_FRAME_SIZE +); + +RTEMS_STATIC_ASSERT( + sizeof( CPU_Exception_frame ) % CPU_ALIGNMENT == 0, + CPU_Exception_frame_alignment +); /* * _CPU_Initialize @@ -197,160 +254,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, @@ -416,7 +319,7 @@ void _CPU_Context_Initialize( the_context->isr_dispatch_disable = 0; if ( tls_area != NULL ) { - void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area ); + void *tcb = _TLS_Initialize_area( tls_area ); the_context->g7 = (uintptr_t) tcb; } diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S index e884fb2f9e..fd7186b499 100644 --- a/cpukit/score/cpu/sparc/cpu_asm.S +++ b/cpukit/score/cpu/sparc/cpu_asm.S @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* cpu_asm.s * * This file contains the basic algorithms for all assembly code used @@ -7,11 +9,28 @@ * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2014, 2017 embedded brains GmbH + * Copyright (C) 2014, 2017 embedded brains GmbH & Co. KG + * + * 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. * - * 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. + * 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. * * Ported to ERC32 implementation of the SPARC by On-Line Applications * Research Corporation (OAR) under contract to the European Space @@ -25,27 +44,6 @@ #include <rtems/score/percpu.h> #include <libcpu/grlib-tn-0018.h> -#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) - #define FP_FRAME_OFFSET_FO_F1 (SPARC_MINIMUM_STACK_FRAME_SIZE + 0) - #define FP_FRAME_OFFSET_F2_F3 (FP_FRAME_OFFSET_FO_F1 + 8) - #define FP_FRAME_OFFSET_F4_F5 (FP_FRAME_OFFSET_F2_F3 + 8) - #define FP_FRAME_OFFSET_F6_F7 (FP_FRAME_OFFSET_F4_F5 + 8) - #define FP_FRAME_OFFSET_F8_F9 (FP_FRAME_OFFSET_F6_F7 + 8) - #define FP_FRAME_OFFSET_F1O_F11 (FP_FRAME_OFFSET_F8_F9 + 8) - #define FP_FRAME_OFFSET_F12_F13 (FP_FRAME_OFFSET_F1O_F11 + 8) - #define FP_FRAME_OFFSET_F14_F15 (FP_FRAME_OFFSET_F12_F13 + 8) - #define FP_FRAME_OFFSET_F16_F17 (FP_FRAME_OFFSET_F14_F15 + 8) - #define FP_FRAME_OFFSET_F18_F19 (FP_FRAME_OFFSET_F16_F17 + 8) - #define FP_FRAME_OFFSET_F2O_F21 (FP_FRAME_OFFSET_F18_F19 + 8) - #define FP_FRAME_OFFSET_F22_F23 (FP_FRAME_OFFSET_F2O_F21 + 8) - #define FP_FRAME_OFFSET_F24_F25 (FP_FRAME_OFFSET_F22_F23 + 8) - #define FP_FRAME_OFFSET_F26_F27 (FP_FRAME_OFFSET_F24_F25 + 8) - #define FP_FRAME_OFFSET_F28_F29 (FP_FRAME_OFFSET_F26_F27 + 8) - #define FP_FRAME_OFFSET_F3O_F31 (FP_FRAME_OFFSET_F28_F29 + 8) - #define FP_FRAME_OFFSET_FSR (FP_FRAME_OFFSET_F3O_F31 + 8) - #define FP_FRAME_SIZE (FP_FRAME_OFFSET_FSR + 8) -#endif - /* * void _CPU_Context_switch( * Context_Control *run, @@ -57,7 +55,9 @@ .align 4 PUBLIC(_CPU_Context_switch) + PUBLIC(_CPU_Context_switch_no_return) SYM(_CPU_Context_switch): +SYM(_CPU_Context_switch_no_return): st %g5, [%o0 + G5_OFFSET] ! save the global registers /* @@ -209,6 +209,18 @@ done_flushing: ! Try to update the is executing indicator of the heir context mov 1, %g1 +#if defined(__FIX_LEON3FT_B2BST) + /* + * This is a workaround for GRLIB-TN-0011 (Technical Note on LEON3/FT + * AHB Lock Release During Atomic Operation). Affected components are + * the GR712RC, UT699, UT699E, UT700, and LEON3FT-RTAX. Strictly, the + * workaround is only necessary if the MMU is enabled. Using the + * __FIX_LEON3FT_B2BST is not 100% appropriate, but the best thing we + * can use to enable the workaround. An alignment padding is filled + * with nops. + */ +.align 16 +#endif .Ltry_update_is_executing: swap [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET], %g1 @@ -234,6 +246,14 @@ done_flushing: mov %g1, %psr ! restore status register and ! **** ENABLE TRAPS **** + /* + * WARNING: This code does not run with the restored stack pointer. In + * SMP configurations, it uses a processor-specific stack. In + * uniprocessor configurations, it uses the stack of the caller. In + * this case, the caller shall ensure that it is not the interrupt + * stack (which is also the system initialization stack). + */ + ld [%o1 + G5_OFFSET], %g5 ! restore the global registers ld [%o1 + G7_OFFSET], %g7 @@ -254,7 +274,9 @@ done_flushing: ldd [%o1 + I4_OFFSET], %i4 ldd [%o1 + I6_FP_OFFSET], %i6 - ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the output registers + ldd [%o1 + O6_SP_OFFSET], %o6 ! restore the non-volatile output + ! registers (stack pointer, + ! link register) jmp %o7 + 8 ! return nop ! delay slot @@ -313,8 +335,25 @@ SYM(_CPU_Context_restore): ba SYM(_CPU_Context_restore_heir) mov %i0, %o1 ! in the delay slot +#if !defined(RTEMS_SMP) + .align 4 + PUBLIC(_SPARC_Start_multitasking) +SYM(_SPARC_Start_multitasking): + /* + * Restore the stack pointer right now, so that the window flushing and + * interrupts during _CPU_Context_restore_heir() use the stack of the + * heir thread. This is crucial for the interrupt handling to prevent + * a concurrent use of the interrupt stack (which is also the system + * initialization stack). + */ + ld [%o0 + O6_SP_OFFSET], %o6 + + ba SYM(_CPU_Context_restore) + nop +#endif + /* - * void _ISR_Handler() + * void _SPARC_Interrupt_trap() * * This routine provides the RTEMS interrupt management. * @@ -324,28 +363,14 @@ SYM(_CPU_Context_restore): * l0 = PSR * l1 = PC * l2 = nPC - * l3 = trap type + * l3 = interrupt vector number (this is not the trap type) * - * NOTE: By an executive defined convention, trap type is between 0 and 255 if - * it is an asynchonous trap and 256 and 511 if it is synchronous. + * NOTE: This trap handler is intended to service external interrupts. */ .align 4 - PUBLIC(_ISR_Handler) -SYM(_ISR_Handler): - /* - * Fix the return address for synchronous traps. - */ - - andcc %l3, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0 - ! Is this a synchronous trap? - be,a win_ovflow ! No, then skip the adjustment - nop ! DELAY - mov %l1, %l6 ! save trapped pc for debug info - mov %l2, %l1 ! do not return to the instruction - add %l2, 4, %l2 ! indicated - -win_ovflow: + PUBLIC(_SPARC_Interrupt_trap) +SYM(_SPARC_Interrupt_trap): /* * Save the globals this block uses. * @@ -432,7 +457,7 @@ dont_do_the_window: * includes a regular minimum stack frame which will be used if * needed by register window overflow and underflow handlers. * - * REGISTERS SAME AS AT _ISR_Handler + * REGISTERS SAME AS AT _SPARC_Interrupt_trap() */ sub %fp, CPU_INTERRUPT_FRAME_SIZE, %sp @@ -458,9 +483,6 @@ dont_do_the_window: rd %y, %g1 st %g1, [%sp + ISF_Y_OFFSET] ! save y - st %l6, [%sp + ISF_TPC_OFFSET] ! save real trapped pc - - mov %sp, %o1 ! 2nd arg to ISR Handler /* * Increment ISR nest level and Thread dispatch disable level. @@ -501,9 +523,7 @@ dont_do_the_window: bnz dont_switch_stacks ! No, then do not switch stacks #if defined(RTEMS_PROFILING) - sethi %hi(_SPARC_Counter), %o5 - ld [%o5 + %lo(_SPARC_Counter)], %l4 - call %l4 + call SYM(_SPARC_Counter_read_ISR_disabled) nop mov %o0, %o5 #else @@ -539,26 +559,16 @@ dont_switch_stacks: sub %sp, SPARC_MINIMUM_STACK_FRAME_SIZE, %sp /* - * Check if we have an external interrupt (trap 0x11 - 0x1f). If so, - * set the PIL in the %psr to mask off interrupts with lower priority. + * Set the PIL in the %psr to mask off interrupts with lower priority. * The original %psr in %l0 is not modified since it will be restored * when the interrupt handler returns. */ mov %l0, %g5 - and %l3, 0x0ff, %g4 - subcc %g4, 0x11, %g0 - bl dont_fix_pil - subcc %g4, 0x1f, %g0 - bg dont_fix_pil - sll %g4, 8, %g4 + sll %l3, 8, %g4 and %g4, SPARC_PSR_PIL_MASK, %g4 andn %l0, SPARC_PSR_PIL_MASK, %g5 - ba pil_fixed or %g4, %g5, %g5 -dont_fix_pil: - or %g5, SPARC_PSR_PIL_MASK, %g5 -pil_fixed: #if SPARC_HAS_FPU == 1 /* @@ -571,23 +581,10 @@ pil_fixed: wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** /* - * Vector to user's handler. - * - * NOTE: TBR may no longer have vector number in it since - * we just enabled traps. It is definitely in l3. + * Call _SPARC_Interrupt_dispatch( %l3 ) */ - - sethi %hi(SYM(_ISR_Vector_table)), %g4 - or %g4, %lo(SYM(_ISR_Vector_table)), %g4 - and %l3, 0xFF, %g5 ! remove synchronous trap indicator - sll %g5, 2, %g5 ! g5 = offset into table - ld [%g4 + %g5], %g4 ! g4 = _ISR_Vector_table[ vector ] - - - ! o1 = 2nd arg = address of the ISF - ! WAS LOADED WHEN ISF WAS SAVED!!! mov %l3, %o0 ! o0 = 1st arg = vector number - call %g4 + call SYM(_SPARC_Interrupt_dispatch) #if defined(RTEMS_PROFILING) mov %o5, %l3 ! save interrupt entry instant #else @@ -605,7 +602,7 @@ pil_fixed: cmp %l7, 0 bne profiling_not_outer_most_exit nop - call %l4 ! Call _SPARC_Counter.counter_read + call SYM(_SPARC_Counter_read_ISR_disabled) mov %g1, %l4 ! Save previous interrupt status mov %o0, %o2 ! o2 = 3rd arg = interrupt exit instant mov %l3, %o1 ! o1 = 2nd arg = interrupt entry instant @@ -705,40 +702,40 @@ isr_dispatch: * Post-switch actions (e.g. signal handlers) and context switch * extensions may safely use the floating point unit. */ - sub %sp, FP_FRAME_SIZE, %sp - std %f0, [%sp + FP_FRAME_OFFSET_FO_F1] + sub %sp, SPARC_FP_FRAME_SIZE, %sp + std %f0, [%sp + SPARC_FP_FRAME_OFFSET_FO_F1] SPARC_LEON3FT_B2BST_NOP - std %f2, [%sp + FP_FRAME_OFFSET_F2_F3] + std %f2, [%sp + SPARC_FP_FRAME_OFFSET_F2_F3] SPARC_LEON3FT_B2BST_NOP - std %f4, [%sp + FP_FRAME_OFFSET_F4_F5] + std %f4, [%sp + SPARC_FP_FRAME_OFFSET_F4_F5] SPARC_LEON3FT_B2BST_NOP - std %f6, [%sp + FP_FRAME_OFFSET_F6_F7] + std %f6, [%sp + SPARC_FP_FRAME_OFFSET_F6_F7] SPARC_LEON3FT_B2BST_NOP - std %f8, [%sp + FP_FRAME_OFFSET_F8_F9] + std %f8, [%sp + SPARC_FP_FRAME_OFFSET_F8_F9] SPARC_LEON3FT_B2BST_NOP - std %f10, [%sp + FP_FRAME_OFFSET_F1O_F11] + std %f10, [%sp + SPARC_FP_FRAME_OFFSET_F1O_F11] SPARC_LEON3FT_B2BST_NOP - std %f12, [%sp + FP_FRAME_OFFSET_F12_F13] + std %f12, [%sp + SPARC_FP_FRAME_OFFSET_F12_F13] SPARC_LEON3FT_B2BST_NOP - std %f14, [%sp + FP_FRAME_OFFSET_F14_F15] + std %f14, [%sp + SPARC_FP_FRAME_OFFSET_F14_F15] SPARC_LEON3FT_B2BST_NOP - std %f16, [%sp + FP_FRAME_OFFSET_F16_F17] + std %f16, [%sp + SPARC_FP_FRAME_OFFSET_F16_F17] SPARC_LEON3FT_B2BST_NOP - std %f18, [%sp + FP_FRAME_OFFSET_F18_F19] + std %f18, [%sp + SPARC_FP_FRAME_OFFSET_F18_F19] SPARC_LEON3FT_B2BST_NOP - std %f20, [%sp + FP_FRAME_OFFSET_F2O_F21] + std %f20, [%sp + SPARC_FP_FRAME_OFFSET_F2O_F21] SPARC_LEON3FT_B2BST_NOP - std %f22, [%sp + FP_FRAME_OFFSET_F22_F23] + std %f22, [%sp + SPARC_FP_FRAME_OFFSET_F22_F23] SPARC_LEON3FT_B2BST_NOP - std %f24, [%sp + FP_FRAME_OFFSET_F24_F25] + std %f24, [%sp + SPARC_FP_FRAME_OFFSET_F24_F25] SPARC_LEON3FT_B2BST_NOP - std %f26, [%sp + FP_FRAME_OFFSET_F26_F27] + std %f26, [%sp + SPARC_FP_FRAME_OFFSET_F26_F27] SPARC_LEON3FT_B2BST_NOP - std %f28, [%sp + FP_FRAME_OFFSET_F28_F29] + std %f28, [%sp + SPARC_FP_FRAME_OFFSET_F28_F29] SPARC_LEON3FT_B2BST_NOP - std %f30, [%sp + FP_FRAME_OFFSET_F3O_F31] + std %f30, [%sp + SPARC_FP_FRAME_OFFSET_F3O_F31] SPARC_LEON3FT_B2BST_NOP - st %fsr, [%sp + FP_FRAME_OFFSET_FSR] + st %fsr, [%sp + SPARC_FP_FRAME_OFFSET_FSR] call SYM(_Thread_Do_dispatch) mov %g6, %o0 @@ -746,25 +743,25 @@ isr_dispatch: * Restore the floating point context from stack frame and release the * stack frame. */ - ldd [%sp + FP_FRAME_OFFSET_FO_F1], %f0 - ldd [%sp + FP_FRAME_OFFSET_F2_F3], %f2 - ldd [%sp + FP_FRAME_OFFSET_F4_F5], %f4 - ldd [%sp + FP_FRAME_OFFSET_F6_F7], %f6 - ldd [%sp + FP_FRAME_OFFSET_F8_F9], %f8 - ldd [%sp + FP_FRAME_OFFSET_F1O_F11], %f10 - ldd [%sp + FP_FRAME_OFFSET_F12_F13], %f12 - ldd [%sp + FP_FRAME_OFFSET_F14_F15], %f14 - ldd [%sp + FP_FRAME_OFFSET_F16_F17], %f16 - ldd [%sp + FP_FRAME_OFFSET_F18_F19], %f18 - ldd [%sp + FP_FRAME_OFFSET_F2O_F21], %f20 - ldd [%sp + FP_FRAME_OFFSET_F22_F23], %f22 - ldd [%sp + FP_FRAME_OFFSET_F24_F25], %f24 - ldd [%sp + FP_FRAME_OFFSET_F26_F27], %f26 - ldd [%sp + FP_FRAME_OFFSET_F28_F29], %f28 - ldd [%sp + FP_FRAME_OFFSET_F3O_F31], %f30 - ld [%sp + FP_FRAME_OFFSET_FSR], %fsr + ldd [%sp + SPARC_FP_FRAME_OFFSET_FO_F1], %f0 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F2_F3], %f2 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F4_F5], %f4 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F6_F7], %f6 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F8_F9], %f8 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F1O_F11], %f10 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F12_F13], %f12 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F14_F15], %f14 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F16_F17], %f16 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F18_F19], %f18 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F2O_F21], %f20 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F22_F23], %f22 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F24_F25], %f24 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F26_F27], %f26 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F28_F29], %f28 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F3O_F31], %f30 + ld [%sp + SPARC_FP_FRAME_OFFSET_FSR], %fsr ba .Lthread_dispatch_done - add %sp, FP_FRAME_SIZE, %sp + add %sp, SPARC_FP_FRAME_SIZE, %sp .Lnon_fp_thread_dispatch: #endif @@ -799,8 +796,8 @@ isr_dispatch: * The CWP in place at this point may be different from * that which was in effect at the beginning of the ISR if we * have been context switched between the beginning of this invocation - * of _ISR_Handler and this point. Thus the CWP and WIM should - * not be changed back to their values at ISR entry time. Any + * of _SPARC_Interrupt_trap() and this point. Thus the CWP and WIM + * should not be changed back to their values at ISR entry time. Any * changes to the PSR must preserve the CWP. */ diff --git a/cpukit/score/cpu/sparc/headers.am b/cpukit/score/cpu/sparc/headers.am deleted file mode 100644 index 25eaeaa74a..0000000000 --- a/cpukit/score/cpu/sparc/headers.am +++ /dev/null @@ -1,11 +0,0 @@ -## This file was generated by "./boostrap -H". -include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/access.h -include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/byteorder.h -include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/grlib-tn-0018.h -include_machine_HEADERS += score/cpu/sparc/include/machine/elf_machdep.h -include_rtems_HEADERS += score/cpu/sparc/include/rtems/asm.h -include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/cpu.h -include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/cpuatomic.h -include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/cpuimpl.h -include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/sparc.h -include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/sparcimpl.h diff --git a/cpukit/score/cpu/sparc/include/libcpu/access.h b/cpukit/score/cpu/sparc/include/libcpu/access.h index 4f2a780895..f414d6f22f 100644 --- a/cpukit/score/cpu/sparc/include/libcpu/access.h +++ b/cpukit/score/cpu/sparc/include/libcpu/access.h @@ -1,12 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* * access.h - access routines for SPARC. SPARC is big endian only. * * COPYRIGHT (c) 2011 * Aeroflex Gaisler. * - * 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. + * 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_ACCESS_H diff --git a/cpukit/score/cpu/sparc/include/libcpu/byteorder.h b/cpukit/score/cpu/sparc/include/libcpu/byteorder.h index 6726a785f8..0c469ba36b 100644 --- a/cpukit/score/cpu/sparc/include/libcpu/byteorder.h +++ b/cpukit/score/cpu/sparc/include/libcpu/byteorder.h @@ -1,12 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* * byteorder.h - Endian conversion for SPARC. SPARC is big endian only. * * COPYRIGHT (c) 2011 * Aeroflex Gaisler. * - * 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. + * 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_BYTEORDER_H @@ -18,42 +37,42 @@ extern "C" { #endif -RTEMS_INLINE_ROUTINE uint16_t ld_le16(volatile uint16_t *addr) +static inline uint16_t ld_le16(volatile uint16_t *addr) { return CPU_swap_u16(*addr); } -RTEMS_INLINE_ROUTINE void st_le16(volatile uint16_t *addr, uint16_t val) +static inline void st_le16(volatile uint16_t *addr, uint16_t val) { *addr = CPU_swap_u16(val); } -RTEMS_INLINE_ROUTINE uint32_t ld_le32(volatile uint32_t *addr) +static inline uint32_t ld_le32(volatile uint32_t *addr) { return CPU_swap_u32(*addr); } -RTEMS_INLINE_ROUTINE void st_le32(volatile uint32_t *addr, uint32_t val) +static inline void st_le32(volatile uint32_t *addr, uint32_t val) { *addr = CPU_swap_u32(val); } -RTEMS_INLINE_ROUTINE uint16_t ld_be16(volatile uint16_t *addr) +static inline uint16_t ld_be16(volatile uint16_t *addr) { return *addr; } -RTEMS_INLINE_ROUTINE void st_be16(volatile uint16_t *addr, uint16_t val) +static inline void st_be16(volatile uint16_t *addr, uint16_t val) { *addr = val; } -RTEMS_INLINE_ROUTINE uint32_t ld_be32(volatile uint32_t *addr) +static inline uint32_t ld_be32(volatile uint32_t *addr) { return *addr; } -RTEMS_INLINE_ROUTINE void st_be32(volatile uint32_t *addr, uint32_t val) +static inline void st_be32(volatile uint32_t *addr, uint32_t val) { *addr = val; } diff --git a/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h index 62f33da6e8..10f34c6123 100644 --- a/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h +++ b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h @@ -1,7 +1,16 @@ /* SPDX-License-Identifier: BSD-2-Clause */ +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file provides interfaces of the GRLIB-TN-0018 LEON3FT + * RETT Restart Errata fixes. + */ + /* - * Copyright (C) 2020 Cobham Gailer AB + * Copyright (C) 2020 Cobham Gaisler AB * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/cpukit/score/cpu/sparc/include/rtems/asm.h b/cpukit/score/cpu/sparc/include/rtems/asm.h index de65f35d2c..ca89f8e417 100644 --- a/cpukit/score/cpu/sparc/include/rtems/asm.h +++ b/cpukit/score/cpu/sparc/include/rtems/asm.h @@ -1,8 +1,10 @@ /** * @file * - * @brief Address the Problems Caused by Incompatible Flavor of - * Assemblers and Toolsets + * @ingroup RTEMSScoreCPUSPARCASM + * + * @brief This header file provides interfaces to address problems caused by + * incompatible flavor of assemblers and toolsets. * * This include file attempts to address the problems * caused by incompatible flavors of assemblers and diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h index 8c5330b8ce..a21cef371f 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h @@ -1,19 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** * @file * - * @brief SPARC CPU Department Source + * @ingroup RTEMSScoreCPUSPARC * - * This include file contains information pertaining to the port of - * the executive to the SPARC processor. + * @brief This header file defines interfaces pertaining to the port of the + * executive to the SPARC processor. */ /* * COPYRIGHT (c) 1989-2011. * 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. + * 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 @@ -743,14 +762,13 @@ extern const CPU_Trap_table_entry _CPU_Trap_slot_template; #ifndef ASM -/* - * ISR handler macros - */ - /** - * Support routine to initialize the RTEMS vector table after it is allocated. + * @brief Dispatches the installed interrupt handlers. + * + * @param irq is the interrupt vector number of the external interrupt ranging + * from 0 to 15. This is not a trap number. */ -#define _CPU_Initialize_vectors() +void _SPARC_Interrupt_dispatch( uint32_t irq ); /** * Disable all interrupts for a critical section. The previous @@ -779,7 +797,7 @@ extern const CPU_Trap_table_entry _CPU_Trap_slot_template; #define _CPU_ISR_Is_enabled( _isr_cookie ) \ sparc_interrupt_is_enabled( _isr_cookie ) -RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint32_t level ) +static inline bool _CPU_ISR_Is_enabled( uint32_t level ) { return ( level & SPARC_PSR_PIL_MASK ) == 0; } @@ -884,17 +902,6 @@ void _CPU_Context_Initialize( do { } while ( 0 ) /* end of Context handler macros */ -/* Fatal Error manager macros */ - -/** - * This routine copies _error into a known place -- typically a stack - * location or a register, optionally disables interrupts, and - * halts/stops the CPU. - */ -RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, uint32_t error ); - -/* end of Fatal Error manager macros */ - #define CPU_USE_LIBC_INIT_FINI_ARRAY FALSE /* Bitfield handler macros */ @@ -971,6 +978,11 @@ void _CPU_Context_switch( Context_Control *heir ); +RTEMS_NO_RETURN void _CPU_Context_switch_no_return( + Context_Control *executing, + Context_Control *heir +); + /** * @brief SPARC specific context restore. * @@ -981,6 +993,25 @@ void _CPU_Context_switch( */ RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context ); +#if !defined(RTEMS_SMP) +/** + * @brief Starts multitasking in uniprocessor configurations. + * + * This function just sets the stack of the heir thread and then calls + * _CPU_Context_restore(). + * + * This is causes that the window flushing and interrupts during + * _CPU_Context_restore() use the stack of the heir thread. This is crucial + * for the interrupt handling to prevent a concurrent use of the interrupt + * stack (which is also the system initialization stack). + * + * @param[in] heir is the context of the heir thread. + */ +RTEMS_NO_RETURN void _SPARC_Start_multitasking( Context_Control *heir ); + +#define _CPU_Start_multitasking( _heir ) _SPARC_Start_multitasking( _heir ) +#endif + #if defined(RTEMS_SMP) uint32_t _CPU_SMP_Initialize( void ); @@ -1000,16 +1031,6 @@ RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context ); #endif void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ); - - static inline void _CPU_SMP_Processor_event_broadcast( void ) - { - __asm__ volatile ( "" : : : "memory" ); - } - - static inline void _CPU_SMP_Processor_event_receive( void ) - { - __asm__ volatile ( "" : : : "memory" ); - } #endif #if defined(SPARC_USE_LAZY_FP_SWITCH) @@ -1023,9 +1044,60 @@ RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context ); } while ( 0 ) #endif +/** + * @brief This structure contains the local and input registers of a register + * window. + */ typedef struct { + /** @brief This member contains the local 0..7 register values. */ + uint32_t local[ 8 ]; + + /** @brief This member contains the input 0..7 register values. */ + uint32_t input[ 8 ]; +} SPARC_Register_window; + +/** + * @brief This structure contains the register set of a context which caused an + * unexpected trap. + */ +typedef struct { + /** @brief This member contains the PSR register value. */ + uint32_t psr; + + /** @brief This member contains the PC value. */ + uint32_t pc; + + /** @brief This member contains the nPC value. */ + uint32_t npc; + + /** @brief This member contains the trap number. */ uint32_t trap; - CPU_Interrupt_frame *isf; + + /** @brief This member contains the WIM register value. */ + uint32_t wim; + + /** @brief This member contains the Y register value. */ + uint32_t y; + + /** @brief This member contains the global 0..7 register values. */ + uint32_t global[ 8 ]; + + /** @brief This member contains the output 0..7 register values. */ + uint32_t output[ 8 ] ; + + /** + * @brief This member contains the additional register windows according to + * the saved WIM. + */ + SPARC_Register_window windows[ SPARC_NUMBER_OF_REGISTER_WINDOWS - 1 ]; + +#if SPARC_HAS_FPU == 1 + /** This member contain the FSR register value. */ + uint32_t fsr; + + /** @brief This member contains the floating point 0..31 register values. */ + uint64_t fp[ 16 ]; +#endif } CPU_Exception_frame; void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ); @@ -1079,39 +1151,7 @@ typedef uint32_t CPU_Counter_ticks; uint32_t _CPU_Counter_frequency( void ); -typedef CPU_Counter_ticks ( *SPARC_Counter_read )( void ); - -/* - * The SPARC processors supported by RTEMS have no built-in CPU counter - * support. We have to use some hardware counter module for this purpose, for - * example the GPTIMER instance used by the clock driver. The BSP must provide - * an implementation of the CPU counter read function. This allows the use of - * dynamic hardware enumeration. - */ -typedef struct { - SPARC_Counter_read read_isr_disabled; - SPARC_Counter_read read; - volatile const CPU_Counter_ticks *counter_register; - volatile const uint32_t *pending_register; - uint32_t pending_mask; - CPU_Counter_ticks accumulated; - CPU_Counter_ticks interval; -} SPARC_Counter; - -extern const SPARC_Counter _SPARC_Counter; - -static inline CPU_Counter_ticks _CPU_Counter_read( void ) -{ - return ( *_SPARC_Counter.read )(); -} - -static inline CPU_Counter_ticks _CPU_Counter_difference( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - return second - first; -} +CPU_Counter_ticks _CPU_Counter_read( void ); /** Type that can store a 32-bit integer or a pointer. */ typedef uintptr_t CPU_Uint32ptr; diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h deleted file mode 100644 index 598ee76b20..0000000000 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpuatomic.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT (c) 2012-2013 Deng Hengyi. - * - * 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. - */ - -#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/sparc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h index a99da74fa9..9697209a97 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h @@ -1,16 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** * @file * - * @brief CPU Port Implementation API + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file defines implementation interfaces pertaining to the + * port of the executive to the SPARC processor. */ /* * Copyright (c) 1989, 2007 On-Line Applications Research Corporation (OAR) - * Copyright (c) 2013, 2016 embedded brains GmbH + * Copyright (C) 2013, 2016 embedded brains GmbH & Co. KG + * + * 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. * - * 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. + * 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 @@ -101,6 +123,8 @@ #define CPU_PER_CPU_CONTROL_SIZE 0 #endif +#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20 + #if ( SPARC_HAS_FPU == 1 ) /** * @brief Offset of the CPU_Per_CPU_control::fsr field relative to the @@ -117,6 +141,49 @@ #endif #endif +#define SPARC_REGISTER_WINDOW_OFFSET_LOCAL( i ) ( ( i ) * 4 ) +#define SPARC_REGISTER_WINDOW_OFFSET_INPUT( i ) ( ( i ) * 4 + 32 ) +#define SPARC_REGISTER_WINDOW_SIZE 64 + +#define SPARC_EXCEPTION_OFFSET_PSR 0 +#define SPARC_EXCEPTION_OFFSET_PC 4 +#define SPARC_EXCEPTION_OFFSET_NPC 8 +#define SPARC_EXCEPTION_OFFSET_TRAP 12 +#define SPARC_EXCEPTION_OFFSET_WIM 16 +#define SPARC_EXCEPTION_OFFSET_Y 20 +#define SPARC_EXCEPTION_OFFSET_GLOBAL( i ) ( ( i ) * 4 + 24 ) +#define SPARC_EXCEPTION_OFFSET_OUTPUT( i ) ( ( i ) * 4 + 56 ) +#define SPARC_EXCEPTION_OFFSET_WINDOWS( i ) ( ( i ) * 64 + 88 ) + +#if SPARC_HAS_FPU == 1 +#define SPARC_EXCEPTION_OFFSET_FSR 536 +#define SPARC_EXCEPTION_OFFSET_FP( i ) ( ( i ) * 8 + 544 ) +#define SPARC_EXCEPTION_FRAME_SIZE 672 +#else +#define SPARC_EXCEPTION_FRAME_SIZE 536 +#endif + +#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) +#define SPARC_FP_FRAME_OFFSET_FO_F1 (SPARC_MINIMUM_STACK_FRAME_SIZE + 0) +#define SPARC_FP_FRAME_OFFSET_F2_F3 (SPARC_FP_FRAME_OFFSET_FO_F1 + 8) +#define SPARC_FP_FRAME_OFFSET_F4_F5 (SPARC_FP_FRAME_OFFSET_F2_F3 + 8) +#define SPARC_FP_FRAME_OFFSET_F6_F7 (SPARC_FP_FRAME_OFFSET_F4_F5 + 8) +#define SPARC_FP_FRAME_OFFSET_F8_F9 (SPARC_FP_FRAME_OFFSET_F6_F7 + 8) +#define SPARC_FP_FRAME_OFFSET_F1O_F11 (SPARC_FP_FRAME_OFFSET_F8_F9 + 8) +#define SPARC_FP_FRAME_OFFSET_F12_F13 (SPARC_FP_FRAME_OFFSET_F1O_F11 + 8) +#define SPARC_FP_FRAME_OFFSET_F14_F15 (SPARC_FP_FRAME_OFFSET_F12_F13 + 8) +#define SPARC_FP_FRAME_OFFSET_F16_F17 (SPARC_FP_FRAME_OFFSET_F14_F15 + 8) +#define SPARC_FP_FRAME_OFFSET_F18_F19 (SPARC_FP_FRAME_OFFSET_F16_F17 + 8) +#define SPARC_FP_FRAME_OFFSET_F2O_F21 (SPARC_FP_FRAME_OFFSET_F18_F19 + 8) +#define SPARC_FP_FRAME_OFFSET_F22_F23 (SPARC_FP_FRAME_OFFSET_F2O_F21 + 8) +#define SPARC_FP_FRAME_OFFSET_F24_F25 (SPARC_FP_FRAME_OFFSET_F22_F23 + 8) +#define SPARC_FP_FRAME_OFFSET_F26_F27 (SPARC_FP_FRAME_OFFSET_F24_F25 + 8) +#define SPARC_FP_FRAME_OFFSET_F28_F29 (SPARC_FP_FRAME_OFFSET_F26_F27 + 8) +#define SPARC_FP_FRAME_OFFSET_F3O_F31 (SPARC_FP_FRAME_OFFSET_F28_F29 + 8) +#define SPARC_FP_FRAME_OFFSET_FSR (SPARC_FP_FRAME_OFFSET_F3O_F31 + 8) +#define SPARC_FP_FRAME_SIZE (SPARC_FP_FRAME_OFFSET_FSR + 8) +#endif + #ifndef ASM #ifdef __cplusplus @@ -156,20 +223,48 @@ register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__( "g6" ); #define _CPU_Get_thread_executing() ( _SPARC_Per_CPU_current->executing ) +RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error ); + void _CPU_Context_volatile_clobber( uintptr_t pattern ); void _CPU_Context_validate( uintptr_t pattern ); -RTEMS_INLINE_ROUTINE void _CPU_Instruction_illegal( void ) +static inline void _CPU_Instruction_illegal( void ) { __asm__ volatile ( "unimp 0" ); } -RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void ) +static inline void _CPU_Instruction_no_operation( void ) { __asm__ volatile ( "nop" ); } +static inline void _CPU_Use_thread_local_storage( + const Context_Control *context +) +{ + register uint32_t g7 __asm__( "g7" ); + + g7 = context->g7; + + /* Make sure that the register assignment is not optimized away */ + __asm__ volatile ( "" : : "r" ( g7 ) ); +} + +static inline void *_CPU_Get_TLS_thread_pointer( + const Context_Control *context +) +{ + return (void *) context->g7; +} + +#if defined(RTEMS_PROFILING) +/** + * @brief Reads the CPU counter while interrupts are disabled. + */ +CPU_Counter_ticks _SPARC_Counter_read_ISR_disabled( void ); +#endif + #ifdef __cplusplus } #endif diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h index 166e89d58a..9b1a09d5e6 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h @@ -1,8 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** * @file * - * @brief Information Required to Build RTEMS for a Particular Member - * of the SPARC Family + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file provides information required to build RTEMS for a + * particular member of the SPARC family. * * This file contains the information required to build * RTEMS for a particular member of the SPARC family. It does @@ -15,9 +19,26 @@ * COPYRIGHT (c) 1989-2011. * 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. + * 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_SPARC_H diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h deleted file mode 100644 index edc03bd074..0000000000 --- a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * 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. - */ - -#ifndef _RTEMS_SCORE_SPARCIMPL_H -#define _RTEMS_SCORE_SPARCIMPL_H - -#include <rtems/score/cpu.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -struct timecounter; - -/* - * Provides a mutable alias to _SPARC_Counter for use in - * _SPARC_Counter_initialize(). The _SPARC_Counter and _SPARC_Counter_mutable - * are defined via the SPARC_COUNTER_DEFINITION define. - */ -extern SPARC_Counter _SPARC_Counter_mutable; - -void _SPARC_Counter_at_tick_clock( void ); - -CPU_Counter_ticks _SPARC_Counter_read_default( void ); - -CPU_Counter_ticks _SPARC_Counter_read_up( void ); - -CPU_Counter_ticks _SPARC_Counter_read_down( void ); - -CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ); - -CPU_Counter_ticks _SPARC_Counter_read_clock( void ); - -CPU_Counter_ticks _SPARC_Counter_read_asr23( void ); - -uint32_t _SPARC_Get_timecount_up( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_down( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_clock( struct timecounter * ); - -uint32_t _SPARC_Get_timecount_asr23( struct timecounter * ); - -/* - * Defines the _SPARC_Counter and _SPARC_Counter_mutable global variables. - * Place this define in the global file scope of the CPU counter support file - * of the BSP. - */ -#define SPARC_COUNTER_DEFINITION \ - __asm__ ( \ - "\t.global\t_SPARC_Counter\n" \ - "\t.global\t_SPARC_Counter_mutable\n" \ - "\t.section\t.data._SPARC_Counter,\"aw\",@progbits\n" \ - "\t.align\t4\n" \ - "\t.type\t_SPARC_Counter, #object\n" \ - "\t.size\t_SPARC_Counter, 28\n" \ - "_SPARC_Counter:\n" \ - "_SPARC_Counter_mutable:\n" \ - "\t.long\t_SPARC_Counter_read_default\n" \ - "\t.long\t_SPARC_Counter_read_default\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.long\t0\n" \ - "\t.previous\n" \ - ) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_SPARCIMPL_H */ diff --git a/cpukit/score/cpu/sparc/sparc-access.S b/cpukit/score/cpu/sparc/sparc-access.S index 277fb7e652..e6628d9eb7 100644 --- a/cpukit/score/cpu/sparc/sparc-access.S +++ b/cpukit/score/cpu/sparc/sparc-access.S @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* * Optimized access routines for SPARC. * @@ -16,9 +18,26 @@ * COPYRIGHT (c) 2011 * Aeroflex Gaisler. * - * 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. + * 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 <rtems/asm.h> diff --git a/cpukit/score/cpu/sparc/sparc-bad-trap.S b/cpukit/score/cpu/sparc/sparc-bad-trap.S new file mode 100644 index 0000000000..f769b64125 --- /dev/null +++ b/cpukit/score/cpu/sparc/sparc-bad-trap.S @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This source file contains the implementation of _SPARC_Bad_trap(). + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * + * 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/percpu.h> + + /* + * The trap handler entry was set up by TRAP(). + */ + PUBLIC(_SPARC_Bad_trap) +SYM(_SPARC_Bad_trap): + + /* + * Do not use the existing stack since it may be invalid. Use the ISR + * stack for this processor. If the trap was caused from within + * interrupt context, then a return to the context which caused the + * trap would be unreliable. + */ + set SYM(_ISR_Stack_size), %l5 + +#if defined(RTEMS_SMP) && defined(__leon__) + rd %asr17, %l6 + srl %l6, LEON3_ASR17_PROCESSOR_INDEX_SHIFT, %l6 + add %l6, 1, %l4 + smul %l4, %l5, %l5 +#endif + set SYM(_ISR_Stack_area_begin), %l7 + add %l7, %l5, %l7 + andn %l7, CPU_STACK_ALIGNMENT - 1, %l7 + + /* + * Establish an area on the stack for a CPU_Exception_frame. + */ + sub %l7, SPARC_EXCEPTION_FRAME_SIZE, %l7 + + /* + * Start saving the context which caused the trap. + */ + mov %wim, %l4 + rd %y, %l5 + std %l0, [%l7 + SPARC_EXCEPTION_OFFSET_PSR] + SPARC_LEON3FT_B2BST_NOP + std %l2, [%l7 + SPARC_EXCEPTION_OFFSET_NPC] + SPARC_LEON3FT_B2BST_NOP + st %l4, [%l7 + SPARC_EXCEPTION_OFFSET_WIM] + st %l5, [%l7 + SPARC_EXCEPTION_OFFSET_Y] + std %g0, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(0)] + SPARC_LEON3FT_B2BST_NOP + std %g2, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(2)] + SPARC_LEON3FT_B2BST_NOP + std %g4, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(4)] + SPARC_LEON3FT_B2BST_NOP + std %g6, [%l7 + SPARC_EXCEPTION_OFFSET_GLOBAL(6)] + SPARC_LEON3FT_B2BST_NOP + std %i0, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(0)] + SPARC_LEON3FT_B2BST_NOP + std %i2, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(2)] + SPARC_LEON3FT_B2BST_NOP + std %i4, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(4)] + SPARC_LEON3FT_B2BST_NOP + std %i6, [%l7 + SPARC_EXCEPTION_OFFSET_OUTPUT(6)] + + /* + * Initialize %g6 since it may be corrupt. + */ + set SYM(_Per_CPU_Information), %g6 +#if defined(RTEMS_SMP) && defined(__leon__) + sll %l6, PER_CPU_CONTROL_SIZE_LOG2, %l4 + add %g6, %l4, %g6 +#endif + + /* + * Disable WIM traps. + */ + mov %g0, %wim + nop + nop + nop + + /* + * Save the remaining register windows. + */ + set SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g2 + add %l7, SPARC_EXCEPTION_OFFSET_WINDOWS(0), %g3 + +.Lsave_register_windows: + + restore + std %l0, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(0)] + SPARC_LEON3FT_B2BST_NOP + std %l2, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(2)] + SPARC_LEON3FT_B2BST_NOP + std %l4, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(4)] + SPARC_LEON3FT_B2BST_NOP + std %l6, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_LOCAL(6)] + SPARC_LEON3FT_B2BST_NOP + std %i0, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(0)] + SPARC_LEON3FT_B2BST_NOP + std %i2, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(2)] + SPARC_LEON3FT_B2BST_NOP + std %i4, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(4)] + SPARC_LEON3FT_B2BST_NOP + std %i6, [%g3 + SPARC_REGISTER_WINDOW_OFFSET_INPUT(6)] + add %g3, SPARC_REGISTER_WINDOW_SIZE, %g3 + subcc %g2, 1, %g2 + bne .Lsave_register_windows + nop + + /* + * Go back to register window at trap entry. + */ + restore + + /* + * Initialize the WIM based on the PSR[CWP] to have all register + * windows available for the fatal error procedure. + */ + and %l0, SPARC_PSR_CWP_MASK, %l4 + set 1, %l5 + sll %l5, %l4, %l5 + mov %l5, %wim + +#if SPARC_HAS_FPU == 1 + /* + * Enable the FPU in the new PSR (PSR[EF] == 1). + */ + sethi %hi(SPARC_PSR_EF_MASK), %l4 + or %l0, %l4, %l0 +#endif + + /* + * Enable traps and disable interrupts. + */ + or %l0, 0xf20, %l0 + wr %l0, %psr + nop + nop + nop + +#if SPARC_HAS_FPU == 1 + st %fsr, [%l7 + SPARC_EXCEPTION_OFFSET_FSR] + std %f0, [%l7 + SPARC_EXCEPTION_OFFSET_FP(0)] + SPARC_LEON3FT_B2BST_NOP + std %f2, [%l7 + SPARC_EXCEPTION_OFFSET_FP(1)] + SPARC_LEON3FT_B2BST_NOP + std %f4, [%l7 + SPARC_EXCEPTION_OFFSET_FP(2)] + SPARC_LEON3FT_B2BST_NOP + std %f6, [%l7 + SPARC_EXCEPTION_OFFSET_FP(3)] + SPARC_LEON3FT_B2BST_NOP + std %f8, [%l7 + SPARC_EXCEPTION_OFFSET_FP(4)] + SPARC_LEON3FT_B2BST_NOP + std %f10, [%l7 + SPARC_EXCEPTION_OFFSET_FP(5)] + SPARC_LEON3FT_B2BST_NOP + std %f12, [%l7 + SPARC_EXCEPTION_OFFSET_FP(6)] + SPARC_LEON3FT_B2BST_NOP + std %f14, [%l7 + SPARC_EXCEPTION_OFFSET_FP(7)] + SPARC_LEON3FT_B2BST_NOP + std %f16, [%l7 + SPARC_EXCEPTION_OFFSET_FP(8)] + SPARC_LEON3FT_B2BST_NOP + std %f18, [%l7 + SPARC_EXCEPTION_OFFSET_FP(9)] + SPARC_LEON3FT_B2BST_NOP + std %f20, [%l7 + SPARC_EXCEPTION_OFFSET_FP(10)] + SPARC_LEON3FT_B2BST_NOP + std %f22, [%l7 + SPARC_EXCEPTION_OFFSET_FP(11)] + SPARC_LEON3FT_B2BST_NOP + std %f24, [%l7 + SPARC_EXCEPTION_OFFSET_FP(12)] + SPARC_LEON3FT_B2BST_NOP + std %f26, [%l7 + SPARC_EXCEPTION_OFFSET_FP(13)] + SPARC_LEON3FT_B2BST_NOP + std %f28, [%l7 + SPARC_EXCEPTION_OFFSET_FP(14)] + SPARC_LEON3FT_B2BST_NOP + std %f30, [%l7 + SPARC_EXCEPTION_OFFSET_FP(15)] +#endif + + /* + * Call _Terminate( RTEMS_FATAL_SOURCE_EXCEPTION, %l0 ). + */ + sub %l7, SPARC_MINIMUM_STACK_FRAME_SIZE, %sp + set 9, %o0 + call SYM(_Terminate) + mov %l7, %o1 diff --git a/cpukit/score/cpu/sparc/sparc-context-validate.S b/cpukit/score/cpu/sparc/sparc-context-validate.S index 8bc116d700..ce1c738d7b 100644 --- a/cpukit/score/cpu/sparc/sparc-context-validate.S +++ b/cpukit/score/cpu/sparc/sparc-context-validate.S @@ -1,15 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* - * Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved. + * Copyright (C) 2015, 2017 embedded brains GmbH & Co. KG * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> + * 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. * - * 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. + * 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 diff --git a/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S index 716bcf2884..ebbaec59a6 100644 --- a/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S +++ b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S @@ -1,15 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /* - * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * Copyright (c) 2015 embedded brains GmbH & Co. KG * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> + * 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. * - * 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. + * 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 diff --git a/cpukit/score/cpu/sparc/sparc-counter-asm.S b/cpukit/score/cpu/sparc/sparc-counter-asm.S deleted file mode 100644 index 44c3fa8edb..0000000000 --- a/cpukit/score/cpu/sparc/sparc-counter-asm.S +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * 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 <rtems/asm.h> - - /* - * All functions except _SPARC_Counter_read_clock() in this module are - * sometimes called with traps disabled. - */ - - .section ".text" - .align 4 - - PUBLIC(_SPARC_Counter_read_default) -SYM(_SPARC_Counter_read_default): - sethi %hi(_SPARC_Counter + 12), %o1 - ld [%o1 + %lo(_SPARC_Counter + 12)], %o0 - add %o0, 1, %o0 - st %o0, [%o1 + %lo(_SPARC_Counter + 12)] - jmp %o7 + 8 - nop - - PUBLIC(_SPARC_Counter_read_up) - PUBLIC(_SPARC_Get_timecount_up) -SYM(_SPARC_Counter_read_up): -SYM(_SPARC_Get_timecount_up): - sethi %hi(_SPARC_Counter + 8), %o0 - ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 - jmp %o7 + 8 - ld [%o0], %o0 - - PUBLIC(_SPARC_Counter_read_down) - PUBLIC(_SPARC_Get_timecount_down) -SYM(_SPARC_Counter_read_down): -SYM(_SPARC_Get_timecount_down): - sethi %hi(_SPARC_Counter + 8), %o0 - ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 - ld [%o0], %o0 - jmp %o7 + 8 - xnor %g0, %o0, %o0 - - /* - * For the corresponding C code is something like this: - * - * CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ) - * { - * const SPARC_Counter *ctr; - * CPU_Counter_ticks ticks; - * CPU_Counter_ticks accumulated; - * - * ctr = &_SPARC_Counter; - * ticks = *ctr->counter_register; - * accumulated = ctr->accumulated; - * - * if ( ( *ctr->pending_register & ctr->pending_mask ) != 0 ) { - * ticks = *ctr->counter_register; - * accumulated += ctr->interval; - * } - * - * return accumulated - ticks; - * } - */ - PUBLIC(_SPARC_Counter_read_clock_isr_disabled) -SYM(_SPARC_Counter_read_clock_isr_disabled): - sethi %hi(_SPARC_Counter), %o5 - or %o5, %lo(_SPARC_Counter), %o5 - ld [%o5 + 8], %o3 - ld [%o5 + 12], %o4 - ld [%o5 + 16], %o2 - ld [%o3], %o0 - ld [%o4], %o1 - btst %o1, %o2 - bne .Lpending_isr_disabled - ld [%o5 + 20], %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 -.Lpending_isr_disabled: - ld [%o5 + 24], %o5 - ld [%o3], %o0 - add %o4, %o5, %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 - - /* - * For the corresponding C code see - * _SPARC_Counter_read_clock_isr_disabled() above. - */ - PUBLIC(_SPARC_Counter_read_clock) - PUBLIC(_SPARC_Get_timecount_clock) -SYM(_SPARC_Counter_read_clock): -SYM(_SPARC_Get_timecount_clock): - sethi %hi(_SPARC_Counter), %o5 - or %o5, %lo(_SPARC_Counter), %o5 - ta SPARC_SWTRAP_IRQDIS - ld [%o5 + 8], %o3 - ld [%o5 + 12], %o4 - ld [%o5 + 16], %o2 - ld [%o3], %o0 - ld [%o4], %o1 - btst %o1, %o2 - bne .Lpending - ld [%o5 + 20], %o4 - ta SPARC_SWTRAP_IRQEN -#ifdef __FIX_LEON3FT_TN0018 - /* A nop is added to work around the GRLIB-TN-0018 errata */ - nop -#endif - jmp %o7 + 8 - sub %o4, %o0, %o0 -.Lpending: - ld [%o5 + 24], %o5 - ld [%o3], %o0 - ta SPARC_SWTRAP_IRQEN - add %o4, %o5, %o4 - jmp %o7 + 8 - sub %o4, %o0, %o0 - - PUBLIC(_SPARC_Counter_read_asr23) - PUBLIC(_SPARC_Get_timecount_asr23) -SYM(_SPARC_Counter_read_asr23): -SYM(_SPARC_Get_timecount_asr23): - jmp %o7 + 8 - mov %asr23, %o0 diff --git a/cpukit/score/cpu/sparc/sparc-exception-frame-print.c b/cpukit/score/cpu/sparc/sparc-exception-frame-print.c new file mode 100644 index 0000000000..71f7f89c7c --- /dev/null +++ b/cpukit/score/cpu/sparc/sparc-exception-frame-print.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This source file contains the SPARC-specific implementation of + * _CPU_Exception_frame_print(). + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * + * 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/bspIo.h> +#include <inttypes.h> + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + size_t i; + size_t j; + const char *desc; + + switch ( SPARC_REAL_TRAP_NUMBER( frame->trap ) ) { + case 0x01: + desc = " (instruction access exception)"; + break; + case 0x02: + desc = " (illegal instruction)"; + break; + case 0x03: + desc = " (privileged instruction)"; + break; + case 0x04: + desc = " (fp disabled)"; + break; + case 0x05: + desc = " (window overflow)"; + break; + case 0x06: + desc = " (window underflow)"; + break; + case 0x07: + desc = " (memory address not aligned)"; + break; + case 0x08: + desc = " (fp exception)"; + break; + case 0x09: + desc = " (data access exception)"; + break; + case 0x0A: + desc = " (tag overflow)"; + break; + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + desc = " (external interrupt)"; + break; + case 0x24: + desc = " (cp disabled)"; + break; + case 0x28: + desc = " (cp exception)"; + break; + default: + desc = ""; + break; + } + + printk( + "\n" + "unexpected trap %" PRIu32 "%s\n" + "PSR = 0x%08" PRIx32 "\n" + "PC = 0x%08" PRIx32 "\n" + "nPC = 0x%08" PRIx32 "\n" + "WIM = 0x%08" PRIx32 "\n" + "Y = 0x%08" PRIx32 "\n", + frame->trap, + desc, + frame->psr, + frame->pc, + frame->npc, + frame->wim, + frame->y + ); + + for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->global ); ++i ) { + printk( "g%zu = 0x%08" PRIx32 "\n", i, frame->global[ i ] ); + } + + for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->output ); ++i ) { + printk( "o%zu[CWP - 0] = 0x%08" PRIx32 "\n", i, frame->output[ i ] ); + } + + for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->windows ); ++i ) { + const SPARC_Register_window *win; + + win = &frame->windows[ i ]; + + for ( j = 0; j < RTEMS_ARRAY_SIZE( win->local ); ++j ) { + printk( "l%zu[CWP - %zu] = 0x%08" PRIx32 "\n", j, i, win->local[ j ] ); + } + + for ( j = 0; j < RTEMS_ARRAY_SIZE( win->input ); ++j ) { + printk( "i%zu[CWP - %zu] = 0x%08" PRIx32 "\n", j, i, win->input[ j ] ); + } + } + +#if SPARC_HAS_FPU == 1 + printk( "FSR = 0x%08" PRIx32 "\n", frame->fsr ); + + for ( i = 0; i < RTEMS_ARRAY_SIZE( frame->fp ); ++i ) { + j = i * 2; + printk( "fp%zu:fp%zu = 0x%016" PRIx64 "\n", j, j + 1, frame->fp[ i ] ); + } +#endif +} diff --git a/cpukit/score/cpu/sparc/sparc-isr-handler.S b/cpukit/score/cpu/sparc/sparc-isr-handler.S new file mode 100644 index 0000000000..9ecb44e870 --- /dev/null +++ b/cpukit/score/cpu/sparc/sparc-isr-handler.S @@ -0,0 +1,637 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * This file contains the basic algorithms for all assembly code used + * in an specific CPU port of RTEMS. These algorithms must be implemented + * in assembly language. + * + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * Copyright (C) 2014, 2017 embedded brains GmbH & Co. KG + * + * 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. + * + * Ported to ERC32 implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <rtems/asm.h> +#include <rtems/score/percpu.h> +#include <libcpu/grlib-tn-0018.h> + +/* + * void _ISR_Handler() + * + * This routine provides the RTEMS interrupt management. + * + * We enter this handler from the 4 instructions in the trap table with + * the following registers assumed to be set as shown: + * + * l0 = PSR + * l1 = PC + * l2 = nPC + * l3 = trap type + * + * NOTE: By an executive defined convention, trap type is between 0 and 255 if + * it is an asynchonous trap and 256 and 511 if it is synchronous. + */ + + .align 4 + PUBLIC(_ISR_Handler) +SYM(_ISR_Handler): + /* + * Fix the return address for synchronous traps. + */ + + andcc %l3, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0 + ! Is this a synchronous trap? + be,a win_ovflow ! No, then skip the adjustment + nop ! DELAY + mov %l1, %l6 ! save trapped pc for debug info + mov %l2, %l1 ! do not return to the instruction + add %l2, 4, %l2 ! indicated + +win_ovflow: + /* + * Save the globals this block uses. + * + * These registers are not restored from the locals. Their contents + * are saved directly from the locals into the ISF below. + */ + + mov %g4, %l4 ! save the globals this block uses + mov %g5, %l5 + + /* + * When at a "window overflow" trap, (wim == (1 << cwp)). + * If we get here like that, then process a window overflow. + */ + + rd %wim, %g4 + srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP + ! are LS 5 bits ; how convenient :) + cmp %g5, 1 ! Is this an invalid window? + bne dont_do_the_window ! No, then skip all this stuff + ! we are using the delay slot + + /* + * The following is same as a 1 position right rotate of WIM + */ + + srl %g4, 1, %g5 ! g5 = WIM >> 1 + sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4 + ! g4 = WIM << (Number Windows - 1) + or %g4, %g5, %g4 ! g4 = (WIM >> 1) | + ! (WIM << (Number Windows - 1)) + + /* + * At this point: + * + * g4 = the new WIM + * g5 is free + */ + + /* + * Since we are tinkering with the register windows, we need to + * make sure that all the required information is in global registers. + */ + + save ! Save into the window + wr %g4, 0, %wim ! WIM = new WIM + nop ! delay slots + nop + nop + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + SPARC_LEON3FT_B2BST_NOP + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + SPARC_LEON3FT_B2BST_NOP + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + restore + nop + +dont_do_the_window: + /* + * Global registers %g4 and %g5 are saved directly from %l4 and + * %l5 directly into the ISF below. + */ + + /* + * Save the state of the interrupted task -- especially the global + * registers -- in the Interrupt Stack Frame. Note that the ISF + * includes a regular minimum stack frame which will be used if + * needed by register window overflow and underflow handlers. + * + * REGISTERS SAME AS AT _ISR_Handler + */ + + sub %fp, CPU_INTERRUPT_FRAME_SIZE, %sp + ! make space for ISF + + std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC + SPARC_LEON3FT_B2BST_NOP + st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC + st %g1, [%sp + ISF_G1_OFFSET] ! save g1 + std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3 + SPARC_LEON3FT_B2BST_NOP + std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above + SPARC_LEON3FT_B2BST_NOP + st %g7, [%sp + ISF_G7_OFFSET] ! save g7 + + std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1 + SPARC_LEON3FT_B2BST_NOP + std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3 + SPARC_LEON3FT_B2BST_NOP + std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5 + SPARC_LEON3FT_B2BST_NOP + std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7 + + rd %y, %g1 + st %g1, [%sp + ISF_Y_OFFSET] ! save y + st %l6, [%sp + ISF_TPC_OFFSET] ! save real trapped pc + + mov %sp, %o1 ! 2nd arg to ISR Handler + + /* + * Increment ISR nest level and Thread dispatch disable level. + * + * Register usage for this section: + * + * l6 = _Thread_Dispatch_disable_level value + * l7 = _ISR_Nest_level value + * + * NOTE: It is assumed that l6 - l7 will be preserved until the ISR + * nest and thread dispatch disable levels are unnested. + */ + + ld [%g6 + PER_CPU_ISR_NEST_LEVEL], %l7 + ld [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL], %l6 + + add %l7, 1, %l7 + st %l7, [%g6 + PER_CPU_ISR_NEST_LEVEL] + SPARC_LEON3FT_B2BST_NOP + + add %l6, 1, %l6 + st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + +#if SPARC_HAS_FPU == 1 + /* + * We cannot use an intermediate value for operations with the PSR[EF] + * bit since they use a 13-bit sign extension and PSR[EF] is bit 12. + */ + sethi %hi(SPARC_PSR_EF_MASK), %l5 +#endif + + /* + * If ISR nest level was zero (now 1), then switch stack. + */ + + mov %sp, %fp + subcc %l7, 1, %l7 ! outermost interrupt handler? + bnz dont_switch_stacks ! No, then do not switch stacks + +#if defined(RTEMS_PROFILING) + call SYM(_SPARC_Counter_read_ISR_disabled) + nop + mov %o0, %o5 +#else + nop +#endif + + ld [%g6 + PER_CPU_INTERRUPT_STACK_HIGH], %sp + +#if SPARC_HAS_FPU == 1 + /* + * Test if the interrupted thread uses the floating point unit + * (PSR[EF] == 1). In case it uses the floating point unit, then store + * the floating point status register. This has the side-effect that + * all pending floating point operations complete before the store + * completes. The PSR[EF] bit is restored after the call to the + * interrupt handler. Thus post-switch actions (e.g. signal handlers) + * and context switch extensions may still corrupt the floating point + * context. + */ + andcc %l0, %l5, %g0 + beq dont_switch_stacks + nop + st %fsr, [%g6 + SPARC_PER_CPU_FSR_OFFSET] +#endif + +dont_switch_stacks: + /* + * Make sure we have a place on the stack for the window overflow + * trap handler to write into. At this point it is safe to + * enable traps again. + */ + + sub %sp, SPARC_MINIMUM_STACK_FRAME_SIZE, %sp + + /* + * Check if we have an external interrupt (trap 0x11 - 0x1f). If so, + * set the PIL in the %psr to mask off interrupts with lower priority. + * The original %psr in %l0 is not modified since it will be restored + * when the interrupt handler returns. + */ + + mov %l0, %g5 + and %l3, 0x0ff, %g4 + subcc %g4, 0x11, %g0 + bl dont_fix_pil + subcc %g4, 0x1f, %g0 + bg dont_fix_pil + sll %g4, 8, %g4 + and %g4, SPARC_PSR_PIL_MASK, %g4 + andn %l0, SPARC_PSR_PIL_MASK, %g5 + ba pil_fixed + or %g4, %g5, %g5 +dont_fix_pil: + or %g5, SPARC_PSR_PIL_MASK, %g5 +pil_fixed: + +#if SPARC_HAS_FPU == 1 + /* + * Clear the PSR[EF] bit of the interrupted context to ensure that + * interrupt service routines cannot corrupt the floating point context. + */ + andn %g5, %l5, %g5 +#endif + + wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** + + /* + * Vector to user's handler. + * + * NOTE: TBR may no longer have vector number in it since + * we just enabled traps. It is definitely in l3. + */ + + sethi %hi(SYM(_ISR_Vector_table)), %g4 + or %g4, %lo(SYM(_ISR_Vector_table)), %g4 + and %l3, 0xFF, %g5 ! remove synchronous trap indicator + sll %g5, 2, %g5 ! g5 = offset into table + ld [%g4 + %g5], %g4 ! g4 = _ISR_Vector_table[ vector ] + + + ! o1 = 2nd arg = address of the ISF + ! WAS LOADED WHEN ISF WAS SAVED!!! + mov %l3, %o0 ! o0 = 1st arg = vector number + call %g4 +#if defined(RTEMS_PROFILING) + mov %o5, %l3 ! save interrupt entry instant +#else + nop ! delay slot +#endif + +#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) + mov %l0, %g1 ! PSR[EF] value of interrupted context + ta SPARC_SWTRAP_IRQDIS_FP ! **** DISABLE INTERRUPTS **** +#else + ta SPARC_SWTRAP_IRQDIS ! **** DISABLE INTERRUPTS **** +#endif + +#if defined(RTEMS_PROFILING) + cmp %l7, 0 + bne profiling_not_outer_most_exit + nop + call SYM(_SPARC_Counter_read_ISR_disabled) + mov %g1, %l4 ! Save previous interrupt status + mov %o0, %o2 ! o2 = 3rd arg = interrupt exit instant + mov %l3, %o1 ! o1 = 2nd arg = interrupt entry instant + call SYM(_Profiling_Outer_most_interrupt_entry_and_exit) + mov %g6, %o0 ! o0 = 1st arg = per-CPU control +profiling_not_outer_most_exit: +#endif + + /* + * Decrement ISR nest level and Thread dispatch disable level. + * + * Register usage for this section: + * + * o2 = g6->dispatch_necessary value + * o3 = g6->isr_dispatch_disable value + * l6 = g6->thread_dispatch_disable_level value + * l7 = g6->isr_nest_level value + */ + + ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %o2 + ld [%g6 + PER_CPU_ISR_DISPATCH_DISABLE], %o3 + st %l7, [%g6 + PER_CPU_ISR_NEST_LEVEL] + SPARC_LEON3FT_B2BST_NOP + sub %l6, 1, %l6 + st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + + /* + * Thread dispatching is necessary and allowed if and only if + * g6->dispatch_necessary == 1 and + * g6->isr_dispatch_disable == 0 and + * g6->thread_dispatch_disable_level == 0. + * + * Otherwise, continue with the simple return. + */ + xor %o2, 1, %o2 + or %o2, %l6, %o2 + orcc %o2, %o3, %o2 + bnz simple_return + + /* + * Switch back on the interrupted tasks stack and add enough room to + * invoke the dispatcher. Doing this in the delay slot causes no harm, + * since the stack pointer (%sp) is not used in the simple return path. + */ + sub %fp, SPARC_MINIMUM_STACK_FRAME_SIZE, %sp + +isr_dispatch: + + /* Set ISR dispatch disable and thread dispatch disable level to one */ + mov 1, %l6 + st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] + st %l6, [%g6 + PER_CPU_ISR_DISPATCH_DISABLE] + + /* Call _Thread_Do_dispatch(), this function will enable interrupts */ + + mov 0, %o1 ! ISR level for _Thread_Do_dispatch() + +#if defined(SPARC_USE_LAZY_FP_SWITCH) + /* Test if we interrupted a floating point thread (PSR[EF] == 1) */ + andcc %l0, %l5, %g0 + be .Lnon_fp_thread_dispatch + ld [%g6 + PER_CPU_OFFSET_EXECUTING], %l6 + + /* Set new floating point unit owner to executing thread */ + st %l6, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET] + + call SYM(_Thread_Do_dispatch) + mov %g6, %o0 + + /* + * If we are still the floating point unit owner, then reset the + * floating point unit owner to NULL, otherwise clear PSR[EF] in the + * interrupt frame and let the FP disabled system call do the floating + * point context save/restore. + */ + ld [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7 + cmp %l6, %l7 + bne,a .Ldisable_fp + andn %l0, %l5, %l0 + st %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET] + ba .Lthread_dispatch_done + nop +.Ldisable_fp: + st %l0, [%fp + ISF_PSR_OFFSET] + ba .Lthread_dispatch_done + nop +.Lnon_fp_thread_dispatch: +#elif defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) + /* Test if we interrupted a floating point thread (PSR[EF] == 1) */ + andcc %l0, %l5, %g0 + be .Lnon_fp_thread_dispatch + nop + + /* + * Yes, this is a floating point thread, then save the floating point + * context to a new stack frame. Then do the thread dispatch. + * Post-switch actions (e.g. signal handlers) and context switch + * extensions may safely use the floating point unit. + */ + sub %sp, SPARC_FP_FRAME_SIZE, %sp + std %f0, [%sp + SPARC_FP_FRAME_OFFSET_FO_F1] + SPARC_LEON3FT_B2BST_NOP + std %f2, [%sp + SPARC_FP_FRAME_OFFSET_F2_F3] + SPARC_LEON3FT_B2BST_NOP + std %f4, [%sp + SPARC_FP_FRAME_OFFSET_F4_F5] + SPARC_LEON3FT_B2BST_NOP + std %f6, [%sp + SPARC_FP_FRAME_OFFSET_F6_F7] + SPARC_LEON3FT_B2BST_NOP + std %f8, [%sp + SPARC_FP_FRAME_OFFSET_F8_F9] + SPARC_LEON3FT_B2BST_NOP + std %f10, [%sp + SPARC_FP_FRAME_OFFSET_F1O_F11] + SPARC_LEON3FT_B2BST_NOP + std %f12, [%sp + SPARC_FP_FRAME_OFFSET_F12_F13] + SPARC_LEON3FT_B2BST_NOP + std %f14, [%sp + SPARC_FP_FRAME_OFFSET_F14_F15] + SPARC_LEON3FT_B2BST_NOP + std %f16, [%sp + SPARC_FP_FRAME_OFFSET_F16_F17] + SPARC_LEON3FT_B2BST_NOP + std %f18, [%sp + SPARC_FP_FRAME_OFFSET_F18_F19] + SPARC_LEON3FT_B2BST_NOP + std %f20, [%sp + SPARC_FP_FRAME_OFFSET_F2O_F21] + SPARC_LEON3FT_B2BST_NOP + std %f22, [%sp + SPARC_FP_FRAME_OFFSET_F22_F23] + SPARC_LEON3FT_B2BST_NOP + std %f24, [%sp + SPARC_FP_FRAME_OFFSET_F24_F25] + SPARC_LEON3FT_B2BST_NOP + std %f26, [%sp + SPARC_FP_FRAME_OFFSET_F26_F27] + SPARC_LEON3FT_B2BST_NOP + std %f28, [%sp + SPARC_FP_FRAME_OFFSET_F28_F29] + SPARC_LEON3FT_B2BST_NOP + std %f30, [%sp + SPARC_FP_FRAME_OFFSET_F3O_F31] + SPARC_LEON3FT_B2BST_NOP + st %fsr, [%sp + SPARC_FP_FRAME_OFFSET_FSR] + call SYM(_Thread_Do_dispatch) + mov %g6, %o0 + + /* + * Restore the floating point context from stack frame and release the + * stack frame. + */ + ldd [%sp + SPARC_FP_FRAME_OFFSET_FO_F1], %f0 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F2_F3], %f2 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F4_F5], %f4 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F6_F7], %f6 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F8_F9], %f8 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F1O_F11], %f10 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F12_F13], %f12 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F14_F15], %f14 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F16_F17], %f16 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F18_F19], %f18 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F2O_F21], %f20 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F22_F23], %f22 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F24_F25], %f24 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F26_F27], %f26 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F28_F29], %f28 + ldd [%sp + SPARC_FP_FRAME_OFFSET_F3O_F31], %f30 + ld [%sp + SPARC_FP_FRAME_OFFSET_FSR], %fsr + ba .Lthread_dispatch_done + add %sp, SPARC_FP_FRAME_SIZE, %sp + +.Lnon_fp_thread_dispatch: +#endif + + call SYM(_Thread_Do_dispatch) + mov %g6, %o0 + +#if SPARC_HAS_FPU == 1 +.Lthread_dispatch_done: +#endif + + ta SPARC_SWTRAP_IRQDIS ! **** DISABLE INTERRUPTS **** + + /* + * While we had ISR dispatching disabled in this thread, + * did we miss anything? If so, then we need to do another + * _Thread_Do_dispatch() before leaving this ISR dispatch context. + */ + ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %l7 + + orcc %l7, %g0, %g0 ! Is a thread dispatch necessary? + bne isr_dispatch ! Yes, then invoke the dispatcher again. + mov 0, %o1 ! ISR level for _Thread_Do_dispatch() + + /* + * No, then set the ISR dispatch disable flag to zero and continue with + * the simple return. + */ + st %g0, [%g6 + PER_CPU_ISR_DISPATCH_DISABLE] + + /* + * The CWP in place at this point may be different from + * that which was in effect at the beginning of the ISR if we + * have been context switched between the beginning of this invocation + * of _ISR_Handler and this point. Thus the CWP and WIM should + * not be changed back to their values at ISR entry time. Any + * changes to the PSR must preserve the CWP. + */ + +simple_return: + ld [%fp + ISF_Y_OFFSET], %l5 ! restore y + wr %l5, 0, %y + + ldd [%fp + ISF_PSR_OFFSET], %l0 ! restore psr, PC + ld [%fp + ISF_NPC_OFFSET], %l2 ! restore nPC + rd %psr, %l3 + and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP + andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task + or %l3, %l0, %l0 ! install it later... + andn %l0, SPARC_PSR_ET_MASK, %l0 + + /* + * Restore tasks global and out registers + */ + + mov %fp, %g1 + + ! g1 is restored later + ldd [%fp + ISF_G2_OFFSET], %g2 ! restore g2, g3 + ldd [%fp + ISF_G4_OFFSET], %g4 ! restore g4, g5 + ld [%fp + ISF_G7_OFFSET], %g7 ! restore g7 + + ldd [%fp + ISF_I0_OFFSET], %i0 ! restore i0, i1 + ldd [%fp + ISF_I2_OFFSET], %i2 ! restore i2, i3 + ldd [%fp + ISF_I4_OFFSET], %i4 ! restore i4, i5 + ldd [%fp + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7 + + /* + * Registers: + * + * ALL global registers EXCEPT G1 and the input registers have + * already been restored and thuse off limits. + * + * The following is the contents of the local registers: + * + * l0 = original psr + * l1 = return address (i.e. PC) + * l2 = nPC + * l3 = CWP + */ + + /* + * if (CWP + 1) is an invalid window then we need to reload it. + * + * WARNING: Traps should now be disabled + */ + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop + nop + nop + rd %wim, %l4 + add %l0, 1, %l6 ! l6 = cwp + 1 + and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it + srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count + ! and CWP are conveniently LS 5 bits + cmp %l5, 1 ! Is tasks window invalid? + bne good_task_window + + /* + * The following code is the same as a 1 position left rotate of WIM. + */ + + sll %l4, 1, %l5 ! l5 = WIM << 1 + srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4 + ! l4 = WIM >> (Number Windows - 1) + or %l4, %l5, %l4 ! l4 = (WIM << 1) | + ! (WIM >> (Number Windows - 1)) + + /* + * Now restore the window just as if we underflowed to it. + */ + + wr %l4, 0, %wim ! WIM = new WIM + nop ! must delay after writing WIM + nop + nop + restore ! now into the tasks window + + ldd [%g1 + CPU_STACK_FRAME_L0_OFFSET], %l0 + ldd [%g1 + CPU_STACK_FRAME_L2_OFFSET], %l2 + ldd [%g1 + CPU_STACK_FRAME_L4_OFFSET], %l4 + ldd [%g1 + CPU_STACK_FRAME_L6_OFFSET], %l6 + ldd [%g1 + CPU_STACK_FRAME_I0_OFFSET], %i0 + ldd [%g1 + CPU_STACK_FRAME_I2_OFFSET], %i2 + ldd [%g1 + CPU_STACK_FRAME_I4_OFFSET], %i4 + ldd [%g1 + CPU_STACK_FRAME_I6_FP_OFFSET], %i6 + ! reload of sp clobbers ISF + save ! Back to ISR dispatch window + +good_task_window: + TN0018_WAIT_IFLUSH %l3,%l4 ! GRLIB-TN-0018 work around macro + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop; nop; nop + ! and restore condition codes. + ld [%g1 + ISF_G1_OFFSET], %g1 ! restore g1 + TN0018_FIX %l3,%l4 ! GRLIB-TN-0018 work around macro + jmp %l1 ! transfer control and + rett %l2 ! go back to tasks window + +/* end of file */ 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..3c8208ef24 --- /dev/null +++ b/cpukit/score/cpu/sparc/sparc-isr-install.c @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @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). + * + * 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/isr.h> +#include <rtems/rtems/cache.h> + +/* + * 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/cpukit/score/cpu/sparc/syscall.S b/cpukit/score/cpu/sparc/syscall.S index 737a501098..ee21c1b005 100644 --- a/cpukit/score/cpu/sparc/syscall.S +++ b/cpukit/score/cpu/sparc/syscall.S @@ -11,7 +11,7 @@ * COPYRIGHT: * * COPYRIGHT (c) 1995. European Space Agency. - * Copyright (c) 2016, 2017 embedded brains GmbH + * Copyright (C) 2016, 2017 embedded brains GmbH & Co. KG * * This terms of the RTEMS license apply to this file. * @@ -44,8 +44,10 @@ SYM(syscall): ta 0 ! syscall 1, halt with %g1,%g2,%g3 info PUBLIC(sparc_syscall_exit) + PUBLIC(_CPU_Fatal_halt) SYM(sparc_syscall_exit): +SYM(_CPU_Fatal_halt): mov SYS_exit, %g1 mov %o0, %g2 ! Additional exit code 1 diff --git a/cpukit/score/cpu/sparc/syscall.h b/cpukit/score/cpu/sparc/syscall.h index 2f20886840..6fc8fa3a6f 100644 --- a/cpukit/score/cpu/sparc/syscall.h +++ b/cpukit/score/cpu/sparc/syscall.h @@ -1 +1,9 @@ +/** + * @file + * + * @ingroup RTEMSScoreCPUSPARC + * + * @brief This header file provides system call interfaces. + */ + #define SYS_exit 1 |