/* * Copyright (c) 2019-2020 Cobham Gaisler AB * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include GTEXT(__sparc_trap_except_reason) GTEXT(__sparc_trap_fault) /* * Fault trap handler * * - IU state is saved and restored * * On entry: * %l0: psr (set by trap code) * %l1: pc * %l2: npc * %l6: tbr (set by trap code) * %fp: %sp of current register window at trap time * %g1: reason * * This trap handler will trash some of the global registers, which is OK since * we will not return to where we trapped. */ SECTION_FUNC(TEXT, __sparc_trap_except_reason) mov %g1, %l7 .Ldoit: /* %g2, %g3 are used at manual window overflow so save temporarily */ mov %g2, %l4 mov %g3, %l5 /* We may have trapped into the invalid window. If so, make it valid. */ rd %wim, %g2 mov %g2, %l3 srl %g2, %l0, %g3 cmp %g3, 1 bne .Lwodone nop /* Do the window overflow. */ sll %g2, (CONFIG_SPARC_NWIN-1), %g3 srl %g2, 1, %g2 or %g2, %g3, %g2 /* Enter window to save. */ save /* Install new wim calculated above. */ mov %g2, %wim nop nop nop /* Put registers on the dedicated save area of the ABI stack frame. */ std %l0, [%sp + 0x00] std %l2, [%sp + 0x08] std %l4, [%sp + 0x10] std %l6, [%sp + 0x18] std %i0, [%sp + 0x20] std %i2, [%sp + 0x28] std %i4, [%sp + 0x30] std %i6, [%sp + 0x38] /* Leave saved window. */ restore .Lwodone: mov %l4, %g2 mov %l5, %g3 /* Allocate an ABI stack frame and exception stack frame */ sub %fp, 96 + __struct_arch_esf_SIZEOF, %sp /* * %fp: %sp of interrupted task * %sp: %sp of interrupted task - ABI_frame - esf */ mov %l7, %o0 /* Fill in the content of the exception stack frame */ #if defined(CONFIG_EXTRA_EXCEPTION_INFO) std %i0, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x00] std %i2, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x08] std %i4, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x10] std %i6, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x18] std %g0, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x00] std %g2, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x08] std %g4, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x10] std %g6, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x18] #endif std %l0, [%sp + 96 + __struct_arch_esf_psr_OFFSET] /* psr pc */ std %l2, [%sp + 96 + __struct_arch_esf_npc_OFFSET] /* npc wim */ rd %y, %l7 std %l6, [%sp + 96 + __struct_arch_esf_tbr_OFFSET] /* tbr y */ /* Enable traps, raise PIL to mask all maskable interrupts. */ or %l0, PSR_PIL, %o2 wr %o2, PSR_ET, %psr nop nop nop #if defined(CONFIG_EXTRA_EXCEPTION_INFO) /* Flush all register windows to the stack. */ .rept CONFIG_SPARC_NWIN-1 save %sp, -64, %sp .endr .rept CONFIG_SPARC_NWIN-1 restore .endr #endif /* * reason is the first argument. * Exception stack frame prepared earlier is the second argument. */ call z_sparc_fatal_error add %sp, 96, %o1 /* * Entry for trap we don't handle explicitly * * Just drop into __sparc_trap_except_reason with reason set to * K_ERR_CPU_EXCEPTION. Note that "reason" is transported in %l7 of the * trapped-into window and global %g1 is preserved. */ SECTION_FUNC(TEXT, __sparc_trap_fault) b .Ldoit /* K_ERR_CPU_EXCEPTION */ mov %g0, %l7