zephyr/arch/sparc/core/reset_trap.S
Martin Åberg a1d1a5f547 SPARC: Keep interrupts disabled during kernel init
This commit avoids enabling interrupts during Zephyr init.

Details:
Interrupts will be enabled only when the first thread starts or if
arch_irq_unlock() is called before that.

The logic is now:
1. Enable traps, disable interrupts globally
2. Initialize bss
3. Call _PrepC

Use in-place memset() to avoid register window overflow and underflow
traps. That is perhaps not the common scenario, but could happen with
memset() implementation which contains SAVE instructions on a system
with few register windows.

The second, and more important, item this commit addresses is that it
increases the processor interrupt level (priority) to highest. That
is, it enters _PrepC with all maskable interrupts levels disabled.

This fixes some cases where interrupts could be taken after
z_clock_driver_init() while the system was still initializing. That
seem to have occurred when clearing large thread stacks.

The third thing is that we now start out with current window pointer
0 (PSR.CWP=0) instead of 1. It has no practical implication except
for preparing for possible future support for systems with only
two windows.

Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
2021-07-22 10:25:53 -04:00

61 lines
1.2 KiB
ArmAsm

/*
* Copyright (c) 2019-2020 Cobham Gaisler AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <linker/sections.h>
#include <arch/sparc/sparc.h>
/* The trap table reset entry jumps to here. */
GTEXT(__sparc_trap_reset)
SECTION_FUNC(TEXT, __sparc_trap_reset)
set __sparc_trap_table, %g1
wr %g1, %tbr
wr 2, %wim
wr PSR_PIL | PSR_S | PSR_PS | PSR_ET, %psr
/* NOTE: wrpsr above may have changed the current register window. */
/* We are in the 3 instruction wrpsr delay so use global registers. */
set z_interrupt_stacks, %g2
set CONFIG_ISR_STACK_SIZE, %g4
add %g2, %g4, %g1
and %g1, 0xfffffff0, %l3
/*
* According to SPARC ABI, Chapter 3: The system marks the deepest
* stack frame by setting the frame pointer to zero. No other frame's
* %fp has a zero value.
*/
sub %l3, 96, %sp
clr %fp
clr %i7
#ifdef CONFIG_INIT_STACKS
/* In-place memset() to avoid register window related traps. */
set 0xaaaaaaaa, %l0
mov %l0, %l1
1:
std %l0, [%g2]
add %g2, 8, %g2
cmp %g2, %l3
bne 1b
nop
#endif
call z_bss_zero
nop
call _PrepC
nop
/* We halt the system by generating a "trap in trap" condition. */
GTEXT(arch_system_halt)
SECTION_FUNC(TEXT, arch_system_halt)
mov %o0, %g0
mov %g1, %g0
set 1, %g1
ta 0x00