arch: Add SPARC processor architecture
SPARC is an open and royalty free processor architecture. This commit provides SPARC architecture support to Zephyr. It is compatible with the SPARC V8 specification and the SPARC ABI and is independent of processor implementation. Functionality specific to SPRAC processor implementations should go in soc/sparc. One example is the LEON3 SOC which is part of this patch set. The architecture port is fully SPARC ABI compatible, including trap handlers and interrupt context. Number of implemented register windows can be configured. Some SPARC V8 processors borrow the CASA (compare-and-swap) atomic instructions from SPARC V9. An option has been defined in the architecture port to forward the corresponding code-generation option to the compiler. Stack size related config options have been defined in sparc/Kconfig to match the SPARC ABI. Co-authored-by: Nikolaus Huber <nikolaus.huber.melk@gmail.com> Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
This commit is contained in:
parent
188efb5bfb
commit
07160fa153
11
arch/Kconfig
11
arch/Kconfig
|
@ -37,6 +37,17 @@ config ARM
|
|||
help
|
||||
ARM architecture
|
||||
|
||||
config SPARC
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
select BIG_ENDIAN
|
||||
select ATOMIC_OPERATIONS_BUILTIN if SPARC_CASA
|
||||
select ATOMIC_OPERATIONS_C if !SPARC_CASA
|
||||
help
|
||||
SPARC architecture
|
||||
|
||||
config X86
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
|
|
4
arch/sparc/CMakeLists.txt
Normal file
4
arch/sparc/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT "elf32-sparc")
|
||||
add_subdirectory(core)
|
67
arch/sparc/Kconfig
Normal file
67
arch/sparc/Kconfig
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menu "SPARC Options"
|
||||
depends on SPARC
|
||||
|
||||
config ARCH
|
||||
default "sparc"
|
||||
|
||||
config SPARC_NWIN
|
||||
int "Number of register windows"
|
||||
default 8
|
||||
help
|
||||
Number of implemented register windows.
|
||||
|
||||
config GEN_ISR_TABLES
|
||||
default y
|
||||
|
||||
config GEN_IRQ_VECTOR_TABLE
|
||||
default n
|
||||
|
||||
config GEN_SW_ISR_TABLE
|
||||
default y
|
||||
|
||||
config NUM_IRQS
|
||||
int
|
||||
default 32
|
||||
|
||||
config SPARC_CASA
|
||||
bool "CASA instructions"
|
||||
help
|
||||
Use CASA atomic instructions. Defined by SPARC V9 and available
|
||||
in some LEON processors.
|
||||
|
||||
# The SPARC V8 ABI allocates a stack frame of minimum 96 byte for each SAVE
|
||||
# instruction so we bump the kernel default values.
|
||||
config MAIN_STACK_SIZE
|
||||
default 4096 if COVERAGE_GCOV
|
||||
default 2048
|
||||
|
||||
config IDLE_STACK_SIZE
|
||||
default 1024
|
||||
|
||||
config ISR_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config TEST_EXTRA_STACKSIZE
|
||||
default 4096 if COVERAGE_GCOV
|
||||
default 2048
|
||||
|
||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config CMSIS_THREAD_MAX_STACK_SIZE
|
||||
default 2048
|
||||
|
||||
config CMSIS_V2_THREAD_MAX_STACK_SIZE
|
||||
default 2048
|
||||
|
||||
config CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE
|
||||
default 2048
|
||||
|
||||
config IPM_CONSOLE_STACK_SIZE
|
||||
default 4096 if COVERAGE
|
||||
default 1024
|
||||
|
||||
endmenu
|
19
arch/sparc/core/CMakeLists.txt
Normal file
19
arch/sparc/core/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
fatal.c
|
||||
reset_trap.S
|
||||
prep_c.c
|
||||
switch.S
|
||||
interrupt_trap.S
|
||||
fault_trap.S
|
||||
irq_manage.c
|
||||
thread.c
|
||||
window_trap.S
|
||||
sw_trap_set_pil.S
|
||||
trap_table_mvt.S
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
|
32
arch/sparc/core/fatal.c
Normal file
32
arch/sparc/core/fatal.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason,
|
||||
const z_arch_esf_t *esf)
|
||||
{
|
||||
if (esf != NULL) {
|
||||
LOG_ERR(" pc: %08x", esf->pc);
|
||||
LOG_ERR("npc: %08x", esf->npc);
|
||||
LOG_ERR("psr: %08x", esf->psr);
|
||||
LOG_ERR("tbr: %08x", esf->tbr);
|
||||
LOG_ERR(" sp: %08x", esf->sp);
|
||||
LOG_ERR(" y: %08x", esf->y);
|
||||
}
|
||||
|
||||
z_fatal_error(reason, esf);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
FUNC_NORETURN void _Fault(const z_arch_esf_t *esf)
|
||||
{
|
||||
LOG_ERR("Trap tt=0x%02x", (esf->tbr >> 4) & 0xff);
|
||||
|
||||
z_sparc_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
||||
}
|
86
arch/sparc/core/fault_trap.S
Normal file
86
arch/sparc/core/fault_trap.S
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <offsets_short.h>
|
||||
#include <arch/sparc/sparc.h>
|
||||
|
||||
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
|
||||
*
|
||||
* 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_fault)
|
||||
/* We may have trapped into the invalid window. If so, make it valid. */
|
||||
rd %wim, %g2
|
||||
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:
|
||||
/* Allocate an ABI stack frame and exception stack frame */
|
||||
sub %fp, 96 + __z_arch_esf_t_SIZEOF, %sp
|
||||
/*
|
||||
* %fp: %sp of interrupted task
|
||||
* %sp: %sp of interrupted task - ABI_frame - esf
|
||||
*/
|
||||
|
||||
/* Fill in the content of the exception stack frame */
|
||||
st %l1, [%sp + 96 + __z_arch_esf_t_pc_OFFSET]
|
||||
st %l2, [%sp + 96 + __z_arch_esf_t_npc_OFFSET]
|
||||
st %l0, [%sp + 96 + __z_arch_esf_t_psr_OFFSET]
|
||||
st %l6, [%sp + 96 + __z_arch_esf_t_tbr_OFFSET]
|
||||
st %fp, [%sp + 96 + __z_arch_esf_t_sp_OFFSET]
|
||||
rd %y, %g1
|
||||
st %g1, [%sp + 96 + __z_arch_esf_t_y_OFFSET]
|
||||
|
||||
/* Enable traps, raise PIL to mask all maskable interrupts. */
|
||||
or %l0, PSR_PIL, %o0
|
||||
wr %o0, PSR_ET, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* Exception stack frame prepared earlier is the first argument. */
|
||||
call _Fault
|
||||
add %sp, 96, %o0
|
244
arch/sparc/core/interrupt_trap.S
Normal file
244
arch/sparc/core/interrupt_trap.S
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <offsets_short.h>
|
||||
#include <arch/sparc/sparc.h>
|
||||
#include "stack_offsets.h"
|
||||
|
||||
GTEXT(__sparc_trap_interrupt)
|
||||
GTEXT(__sparc_trap_irq_offload)
|
||||
|
||||
/*
|
||||
* Interrupt trap handler
|
||||
*
|
||||
* - IU state is saved and restored
|
||||
*
|
||||
* On entry:
|
||||
* %l0: psr (set by trap code)
|
||||
* %l1: pc
|
||||
* %l2: npc
|
||||
* %l3: SPARC interrupt request level (bp_IRL)
|
||||
* %fp: %sp of current register window at trap time
|
||||
*
|
||||
* This module also implements the IRQ offload support. The handling is the
|
||||
* same as for asynchronous maskable interrupts, with the following exceptions:
|
||||
* - Do not re-execute the causing (ta) instruction at trap exit.
|
||||
* - A dedicated interrupt request level (0x8d) is used.
|
||||
* - z_sparc_enter_irq() knows how to interpret this interrupt request level.
|
||||
*/
|
||||
SECTION_SUBSEC_FUNC(TEXT, __sparc_trap_interrupt, __sparc_trap_irq_offload)
|
||||
/* Preparation in the case of synchronous IRQ offload. */
|
||||
mov %l2, %l1
|
||||
add %l2, 4, %l2
|
||||
set 0x8d, %l3
|
||||
|
||||
__sparc_trap_interrupt:
|
||||
/* %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
|
||||
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:
|
||||
/*
|
||||
* %l4: %g2 at trap time
|
||||
* %l5: %g3 at trap time
|
||||
*
|
||||
* Save the state of the interrupted task including global registers on
|
||||
* the task stack.
|
||||
*
|
||||
* IMPORTANT: Globals are saved here as well on the task stack, since a
|
||||
* context switch might happen before the context of this interrupted
|
||||
* task is restored.
|
||||
*/
|
||||
|
||||
/* Allocate stack for isr context including ABI frame. */
|
||||
sub %fp, ISF_SIZE, %sp
|
||||
/*
|
||||
* %fp: %sp of interrupted task
|
||||
* %sp: %sp of interrupted task - ISF_SIZE.
|
||||
* (fits a full ABI frame + what we store here)
|
||||
*
|
||||
* Save the interrupted context.
|
||||
*/
|
||||
std %l0, [%sp + ISF_PSR_OFFSET] /* psr pc */
|
||||
st %l2, [%sp + ISF_NPC_OFFSET] /* npc */
|
||||
st %g1, [%sp + ISF_G1_OFFSET] /* g1 */
|
||||
std %l4, [%sp + ISF_G2_OFFSET] /* g2 g3 */
|
||||
st %g4, [%sp + ISF_G4_OFFSET] /* g4 */
|
||||
std %i0, [%sp + ISF_I0_OFFSET] /* i0 i1 */
|
||||
std %i2, [%sp + ISF_I2_OFFSET] /* i2 i3 */
|
||||
std %i4, [%sp + ISF_I4_OFFSET] /* i4 i5 */
|
||||
std %i6, [%sp + ISF_I6_OFFSET] /* fp i7 */
|
||||
rd %y, %g1
|
||||
st %g1, [%sp + ISF_Y_OFFSET] /* y */
|
||||
|
||||
/* %l5: reference to _kernel */
|
||||
set _kernel, %l5
|
||||
/* Switch to interrupt stack. */
|
||||
mov %sp, %fp
|
||||
ld [%l5 + _kernel_offset_to_irq_stack], %sp
|
||||
|
||||
/* Allocate a full C stack frame */
|
||||
sub %sp, STACK_FRAME_SIZE, %sp
|
||||
/*
|
||||
* %fp: %sp of interrupted task - ISF_SIZE.
|
||||
* %sp: irq stack - 96. An ABI frame
|
||||
*/
|
||||
|
||||
/* Enable traps, raise PIL to mask all maskable interrupts. */
|
||||
or %l0, PSR_PIL, %o0
|
||||
wr %o0, PSR_ET, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* SPARC interrupt request level is the first agrument */
|
||||
call z_sparc_enter_irq
|
||||
mov %l3, %o0
|
||||
|
||||
/*
|
||||
* Switch back to interrupted task stack
|
||||
* %fp: %sp of interrupted task - ISF_SIZE.
|
||||
* %sp: irq stack - 96. An ABI frame
|
||||
*/
|
||||
mov %fp, %sp
|
||||
/*
|
||||
* %fp: %sp of interrupted task - ISF_SIZE.
|
||||
* %sp: %sp of interrupted task - ISF_SIZE.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
sub %sp, (96+8), %sp
|
||||
call z_arch_get_next_switch_handle
|
||||
add %sp, 96, %o0
|
||||
/* we get old thread as "return value" on stack */
|
||||
ld [%sp + 96], %o1
|
||||
/*
|
||||
* o0: new thread
|
||||
* o1: old thread
|
||||
*/
|
||||
cmp %o0, %o1
|
||||
beq .Lno_reschedule
|
||||
nop
|
||||
call z_sparc_context_switch
|
||||
nop
|
||||
.Lno_reschedule:
|
||||
add %sp, (96+8), %sp
|
||||
#endif /* CONFIG_PREEMPT_ENABLED */
|
||||
|
||||
/* Restore the interrupted context. */
|
||||
ld [%sp + ISF_Y_OFFSET], %g1
|
||||
wr %g1, 0, %y
|
||||
|
||||
ldd [%sp + ISF_PSR_OFFSET], %l0 /* psr, pc */
|
||||
ld [%sp + ISF_NPC_OFFSET], %l2 /* npc */
|
||||
/* NOTE: %g1 will be restored later */
|
||||
ldd [%sp + ISF_G2_OFFSET], %g2
|
||||
ld [%sp + ISF_G4_OFFSET], %g4
|
||||
ldd [%sp + ISF_I0_OFFSET], %i0
|
||||
ldd [%sp + ISF_I2_OFFSET], %i2
|
||||
ldd [%sp + ISF_I4_OFFSET], %i4
|
||||
ldd [%sp + ISF_I6_OFFSET], %i6
|
||||
/* %g1 is used to access the stack frame later */
|
||||
mov %sp, %g1
|
||||
|
||||
/*
|
||||
* Install the PSR we got from the interrupt context. Current PSR.CWP
|
||||
* is preserved. Keep PSR.ET=0 until we do "rett".
|
||||
*/
|
||||
rd %psr, %l3
|
||||
and %l3, PSR_CWP, %l3
|
||||
andn %l0, (PSR_CWP | PSR_ET), %l0
|
||||
or %l3, %l0, %l0
|
||||
mov %l0, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Calculate %l6 := (cwp+1) % NWIN */
|
||||
rd %wim, %l3
|
||||
set (CONFIG_SPARC_NWIN), %l7
|
||||
add %l0, 1, %l6
|
||||
and %l6, PSR_CWP, %l6
|
||||
cmp %l6, %l7
|
||||
bge,a .Lwrapok
|
||||
mov 0, %l6
|
||||
|
||||
.Lwrapok:
|
||||
/* Determine if we must prepare the return window. */
|
||||
/* %l5 := %wim >> (cwp+1) */
|
||||
srl %l3, %l6, %l5
|
||||
/* %l5 is 1 if (cwp+1) is an invalid window */
|
||||
cmp %l5, 1
|
||||
bne .Lwudone
|
||||
sub %l7, 1, %l7 /* %l7 := NWIN - 1 */
|
||||
|
||||
/* Do the window underflow. */
|
||||
sll %l3, 1, %l4
|
||||
srl %l3, %l7, %l5
|
||||
wr %l4, %l5, %wim
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
restore
|
||||
ldd [%g1 + 0x00], %l0
|
||||
ldd [%g1 + 0x08], %l2
|
||||
ldd [%g1 + 0x10], %l4
|
||||
ldd [%g1 + 0x18], %l6
|
||||
ldd [%g1 + 0x20], %i0
|
||||
ldd [%g1 + 0x28], %i2
|
||||
ldd [%g1 + 0x30], %i4
|
||||
ldd [%g1 + 0x38], %i6
|
||||
save
|
||||
|
||||
.Lwudone:
|
||||
/*
|
||||
* Restore %psr since we may have trashed condition codes. PSR.ET is
|
||||
* still 0.
|
||||
*/
|
||||
wr %l0, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* restore g1 */
|
||||
ld [%g1 + ISF_G1_OFFSET], %g1
|
||||
|
||||
jmp %l1
|
||||
rett %l2
|
52
arch/sparc/core/irq_manage.c
Normal file
52
arch/sparc/core/irq_manage.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <kswap.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
FUNC_NORETURN void z_irq_spurious(const void *unused)
|
||||
{
|
||||
uint32_t tbr;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
__asm__ volatile (
|
||||
"rd %%tbr, %0" :
|
||||
"=r" (tbr)
|
||||
);
|
||||
LOG_ERR("Spurious interrupt detected! IRQ: %d", (tbr >> 4) & 0xf);
|
||||
z_sparc_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||
}
|
||||
|
||||
void z_sparc_enter_irq(uint32_t irl)
|
||||
{
|
||||
struct _isr_table_entry *ite;
|
||||
|
||||
_current_cpu->nested++;
|
||||
|
||||
#ifdef CONFIG_IRQ_OFFLOAD
|
||||
if (irl != 141) {
|
||||
irl = z_sparc_int_get_source(irl);
|
||||
ite = &_sw_isr_table[irl];
|
||||
ite->isr(ite->arg);
|
||||
} else {
|
||||
z_irq_do_offload();
|
||||
}
|
||||
#else
|
||||
/* Get the actual interrupt source from the interrupt controller */
|
||||
irl = z_sparc_int_get_source(irl);
|
||||
ite = &_sw_isr_table[irl];
|
||||
ite->isr(ite->arg);
|
||||
#endif
|
||||
|
||||
_current_cpu->nested--;
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
z_check_stack_sentinel();
|
||||
#endif
|
||||
}
|
41
arch/sparc/core/irq_offload.c
Normal file
41
arch/sparc/core/irq_offload.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <irq.h>
|
||||
#include <irq_offload.h>
|
||||
|
||||
volatile irq_offload_routine_t _offload_routine;
|
||||
static volatile const void *offload_param;
|
||||
|
||||
void z_irq_do_offload(void)
|
||||
{
|
||||
irq_offload_routine_t tmp;
|
||||
|
||||
if (!_offload_routine) {
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = _offload_routine;
|
||||
_offload_routine = NULL;
|
||||
|
||||
tmp((const void *)offload_param);
|
||||
}
|
||||
|
||||
void arch_irq_offload(irq_offload_routine_t routine, const void *parameter)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
key = irq_lock();
|
||||
_offload_routine = routine;
|
||||
offload_param = parameter;
|
||||
|
||||
/* Generate irq offload trap */
|
||||
__asm__ volatile ("ta 13");
|
||||
|
||||
irq_unlock(key);
|
||||
}
|
56
arch/sparc/core/offsets/offsets.c
Normal file
56
arch/sparc/core/offsets/offsets.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief SPARC kernel structure member offset definition file
|
||||
*
|
||||
* This module is responsible for the generation of the absolute symbols whose
|
||||
* value represents the member offsets for various SPARC kernel structures.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_arch_data.h>
|
||||
#include <gen_offset.h>
|
||||
#include <kernel_offsets.h>
|
||||
|
||||
GEN_OFFSET_SYM(_callee_saved_t, y);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, psr);
|
||||
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l0_and_l1);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l2);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l3);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l4);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l5);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l6);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, l7);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i0);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i1);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i2);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i3);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i4);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i5);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i6);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, i7);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, o6);
|
||||
GEN_OFFSET_SYM(_callee_saved_t, o7);
|
||||
|
||||
/* esf member offsets */
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, pc);
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, npc);
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, psr);
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, tbr);
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, sp);
|
||||
GEN_OFFSET_SYM(z_arch_esf_t, y);
|
||||
GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, STACK_ROUND_UP(sizeof(z_arch_esf_t)));
|
||||
|
||||
/*
|
||||
* size of the struct k_thread structure sans save area for floating
|
||||
* point regs
|
||||
*/
|
||||
GEN_ABSOLUTE_SYM(_K_THREAD_NO_FLOAT_SIZEOF, sizeof(struct k_thread));
|
||||
|
||||
GEN_ABS_SYM_END
|
30
arch/sparc/core/prep_c.c
Normal file
30
arch/sparc/core/prep_c.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Full C support initialization
|
||||
*/
|
||||
|
||||
#include <kernel_internal.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Prepare to and run C code
|
||||
*
|
||||
* This routine prepares for the execution of and runs C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void _PrepC(void)
|
||||
{
|
||||
#ifdef CONFIG_XIP
|
||||
z_data_copy();
|
||||
#endif
|
||||
z_cstart();
|
||||
CODE_UNREACHABLE;
|
||||
}
|
64
arch/sparc/core/reset_trap.S
Normal file
64
arch/sparc/core/reset_trap.S
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 %g0, 4, %wim
|
||||
/* %psr := pil=0, et=0, cwp=1 */
|
||||
set (PSR_S | PSR_PS | 1), %g7
|
||||
wr %g7, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* NOTE: wrpsr above may have changed the current register window. */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
set z_interrupt_stacks, %o0
|
||||
set CONFIG_ISR_STACK_SIZE, %o2
|
||||
add %o0, %o2, %l2
|
||||
and %l2, 0xfffffff0, %l3
|
||||
sub %l3, 96, %sp
|
||||
clr %fp
|
||||
clr %i7
|
||||
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
/* already have z_interrupt_stacks and CONFIG_ISR_STACK_SIZE in place */
|
||||
call memset
|
||||
mov 0xaa, %o1
|
||||
#endif
|
||||
|
||||
call z_bss_zero
|
||||
nop
|
||||
|
||||
/* Enable traps for the first time */
|
||||
/* %psr := pil=0, et=1, cwp=1 */
|
||||
wr %g7, PSR_ET, %psr
|
||||
nop
|
||||
nop
|
||||
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
|
65
arch/sparc/core/stack_offsets.h
Normal file
65
arch/sparc/core/stack_offsets.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_SPARC_CORE_STACK_H_
|
||||
#define ZEPHYR_ARCH_SPARC_CORE_STACK_H_
|
||||
|
||||
/*
|
||||
* Offsets for SPARC ABI stack frame.
|
||||
*
|
||||
* Reference: System V Application Binary Interface, SPARC Processor
|
||||
* Supplement, Third Edition, Page 3-35.
|
||||
*/
|
||||
#define STACK_FRAME_L0_OFFSET 0x00
|
||||
#define STACK_FRAME_L1_OFFSET 0x04
|
||||
#define STACK_FRAME_L2_OFFSET 0x08
|
||||
#define STACK_FRAME_L3_OFFSET 0x0c
|
||||
#define STACK_FRAME_L4_OFFSET 0x10
|
||||
#define STACK_FRAME_L5_OFFSET 0x14
|
||||
#define STACK_FRAME_L6_OFFSET 0x18
|
||||
#define STACK_FRAME_L7_OFFSET 0x1c
|
||||
#define STACK_FRAME_I0_OFFSET 0x20
|
||||
#define STACK_FRAME_I1_OFFSET 0x24
|
||||
#define STACK_FRAME_I2_OFFSET 0x28
|
||||
#define STACK_FRAME_I3_OFFSET 0x2c
|
||||
#define STACK_FRAME_I4_OFFSET 0x30
|
||||
#define STACK_FRAME_I5_OFFSET 0x34
|
||||
#define STACK_FRAME_I6_OFFSET 0x38
|
||||
#define STACK_FRAME_I7_OFFSET 0x3c
|
||||
#define STACK_FRAME_STRUCTURE_RETURN_ADDRESS_OFFSET 0x40
|
||||
#define STACK_FRAME_SAVED_ARG0_OFFSET 0x44
|
||||
#define STACK_FRAME_SAVED_ARG1_OFFSET 0x48
|
||||
#define STACK_FRAME_SAVED_ARG2_OFFSET 0x4c
|
||||
#define STACK_FRAME_SAVED_ARG3_OFFSET 0x50
|
||||
#define STACK_FRAME_SAVED_ARG4_OFFSET 0x54
|
||||
#define STACK_FRAME_SAVED_ARG5_OFFSET 0x58
|
||||
#define STACK_FRAME_PAD0_OFFSET 0x5c
|
||||
#define STACK_FRAME_SIZE 0x60
|
||||
|
||||
|
||||
/* Interrupt stack frame */
|
||||
#define ISF_PSR_OFFSET (STACK_FRAME_SIZE + 0x00)
|
||||
#define ISF_PC_OFFSET (STACK_FRAME_SIZE + 0x04)
|
||||
#define ISF_NPC_OFFSET (STACK_FRAME_SIZE + 0x08)
|
||||
#define ISF_G1_OFFSET (STACK_FRAME_SIZE + 0x0c)
|
||||
#define ISF_G2_OFFSET (STACK_FRAME_SIZE + 0x10)
|
||||
#define ISF_G3_OFFSET (STACK_FRAME_SIZE + 0x14)
|
||||
#define ISF_G4_OFFSET (STACK_FRAME_SIZE + 0x18)
|
||||
#define ISF_G5_OFFSET (STACK_FRAME_SIZE + 0x1c)
|
||||
#define ISF_G7_OFFSET (STACK_FRAME_SIZE + 0x24)
|
||||
#define ISF_I0_OFFSET (STACK_FRAME_SIZE + 0x28)
|
||||
#define ISF_I1_OFFSET (STACK_FRAME_SIZE + 0x2c)
|
||||
#define ISF_I2_OFFSET (STACK_FRAME_SIZE + 0x30)
|
||||
#define ISF_I3_OFFSET (STACK_FRAME_SIZE + 0x34)
|
||||
#define ISF_I4_OFFSET (STACK_FRAME_SIZE + 0x38)
|
||||
#define ISF_I5_OFFSET (STACK_FRAME_SIZE + 0x3c)
|
||||
#define ISF_I6_OFFSET (STACK_FRAME_SIZE + 0x40)
|
||||
#define ISF_I7_OFFSET (STACK_FRAME_SIZE + 0x44)
|
||||
#define ISF_Y_OFFSET (STACK_FRAME_SIZE + 0x48)
|
||||
|
||||
#define ISF_SIZE (STACK_FRAME_SIZE + 0x50)
|
||||
|
||||
#endif /* ZEPHYR_ARCH_SPARC_CORE_STACK_H_ */
|
43
arch/sparc/core/sw_trap_set_pil.S
Normal file
43
arch/sparc/core/sw_trap_set_pil.S
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
GTEXT(__sparc_trap_sw_set_pil)
|
||||
|
||||
/*
|
||||
* Set processor interrupt level
|
||||
*
|
||||
* Handler for SPARC trap 0x89: trap_instruction, defined as "Reserved for the
|
||||
* operating system" by SPARC-ABI.
|
||||
*
|
||||
* entry:
|
||||
* - %l0: psr
|
||||
* - %l1: pc
|
||||
* - %l2: npc
|
||||
* - %i0: New processor interrupt level
|
||||
*
|
||||
* return:
|
||||
* - %i0: Old processor interrupt level
|
||||
*/
|
||||
SECTION_FUNC(TEXT, __sparc_trap_sw_set_pil)
|
||||
/* %l5: new %psr */
|
||||
sll %i0, PSR_PIL_BIT, %i0
|
||||
andn %l0, PSR_PIL, %l5
|
||||
or %l5, %i0, %l5
|
||||
|
||||
wr %l5, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
and %l0, PSR_PIL, %l3
|
||||
srl %l3, PSR_PIL_BIT, %i0
|
||||
|
||||
jmp %l2
|
||||
rett %l2 + 4
|
142
arch/sparc/core/switch.S
Normal file
142
arch/sparc/core/switch.S
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <offsets_short.h>
|
||||
#include <arch/sparc/sparc.h>
|
||||
|
||||
GTEXT(z_sparc_arch_switch)
|
||||
GTEXT(z_sparc_context_switch)
|
||||
GTEXT(z_thread_entry_wrapper)
|
||||
|
||||
/* In this implementation, switch_handle is the thread itself. */
|
||||
SECTION_FUNC(TEXT, z_sparc_arch_switch)
|
||||
ba z_sparc_context_switch
|
||||
sub %o1, ___thread_t_switch_handle_OFFSET, %o1
|
||||
|
||||
/*
|
||||
* This is a leaf function, so only out registers
|
||||
* can be used without saving their context first.
|
||||
*
|
||||
* o0: new thread to restore
|
||||
* o1: old thread to save
|
||||
*/
|
||||
SECTION_FUNC(TEXT, z_sparc_context_switch)
|
||||
mov %y, %o4
|
||||
st %o4, [%o1 + _thread_offset_to_y]
|
||||
std %l0, [%o1 + _thread_offset_to_l0_and_l1]
|
||||
std %l2, [%o1 + _thread_offset_to_l2]
|
||||
std %l4, [%o1 + _thread_offset_to_l4]
|
||||
std %l6, [%o1 + _thread_offset_to_l6]
|
||||
std %i0, [%o1 + _thread_offset_to_i0]
|
||||
std %i2, [%o1 + _thread_offset_to_i2]
|
||||
std %i4, [%o1 + _thread_offset_to_i4]
|
||||
std %i6, [%o1 + _thread_offset_to_i6]
|
||||
|
||||
std %o6, [%o1 + _thread_offset_to_o6]
|
||||
|
||||
rd %psr, %o4
|
||||
st %o4, [%o1 + _thread_offset_to_psr]
|
||||
|
||||
and %o4, PSR_CWP, %g3 /* %g3 = CWP */
|
||||
andn %o4, PSR_ET, %g1 /* %g1 = psr with traps disabled */
|
||||
wr %g1, %psr /* disable traps */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
rd %wim, %g2 /* %g2 = wim */
|
||||
mov 1, %g4
|
||||
sll %g4, %g3, %g4 /* %g4 = wim mask for CW invalid */
|
||||
|
||||
.Lsave_frame_loop:
|
||||
sll %g4, 1, %g5 /* rotate wim left by 1 */
|
||||
srl %g4, (CONFIG_SPARC_NWIN-1), %g4
|
||||
or %g4, %g5, %g4 /* %g4 = wim if we do one restore */
|
||||
|
||||
/* if restore would not underflow, continue */
|
||||
andcc %g4, %g2, %g0 /* window to flush? */
|
||||
bnz .Ldone_flushing /* continue */
|
||||
nop
|
||||
restore /* go one window back */
|
||||
|
||||
/* essentially the same as window overflow */
|
||||
/* sp still points to task stack */
|
||||
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]
|
||||
ba .Lsave_frame_loop
|
||||
nop
|
||||
|
||||
.Ldone_flushing:
|
||||
/*
|
||||
* "wrpsr" is a delayed write instruction so wait three instructions
|
||||
* after the write before using non-global registers or instructions
|
||||
* affecting the CWP.
|
||||
*/
|
||||
wr %g1, %psr /* restore cwp */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
add %g3, 1, %g2 /* calculate desired wim */
|
||||
cmp %g2, (CONFIG_SPARC_NWIN-1) /* check if wim is in range */
|
||||
bg,a .Lwim_overflow
|
||||
mov 0, %g2
|
||||
|
||||
.Lwim_overflow:
|
||||
|
||||
mov 1, %g4
|
||||
sll %g4, %g2, %g4 /* %g4 = new wim */
|
||||
wr %g4, %wim
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldd [%o0 + _thread_offset_to_y], %o4
|
||||
mov %o4, %y
|
||||
|
||||
/* restore local registers */
|
||||
ldd [%o0 + _thread_offset_to_l0_and_l1], %l0
|
||||
ldd [%o0 + _thread_offset_to_l2], %l2
|
||||
ldd [%o0 + _thread_offset_to_l4], %l4
|
||||
ldd [%o0 + _thread_offset_to_l6], %l6
|
||||
|
||||
/* restore input registers */
|
||||
ldd [%o0 + _thread_offset_to_i0], %i0
|
||||
ldd [%o0 + _thread_offset_to_i2], %i2
|
||||
ldd [%o0 + _thread_offset_to_i4], %i4
|
||||
ldd [%o0 + _thread_offset_to_i6], %i6
|
||||
|
||||
/* restore output registers */
|
||||
ldd [%o0 + _thread_offset_to_o6], %o6
|
||||
|
||||
ld [%o0 + _thread_offset_to_psr], %g1 /* %g1 = new thread psr */
|
||||
|
||||
andn %g1, PSR_CWP, %g1 /* psr without cwp */
|
||||
or %g1, %g3, %g1 /* psr with new cwp */
|
||||
wr %g1, %psr /* restore status register and ET */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* jump into thread */
|
||||
jmp %o7 + 8
|
||||
nop
|
||||
|
||||
SECTION_FUNC(TEXT, z_thread_entry_wrapper)
|
||||
mov %g0, %o7
|
||||
ld [%sp + 0x40], %o0
|
||||
ld [%sp + 0x44], %o1
|
||||
ld [%sp + 0x48], %o2
|
||||
ld [%sp + 0x4C], %o3
|
||||
call z_thread_entry
|
||||
nop
|
58
arch/sparc/core/thread.c
Normal file
58
arch/sparc/core/thread.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <ksched.h>
|
||||
|
||||
void z_thread_entry_wrapper(k_thread_entry_t thread,
|
||||
void *arg1,
|
||||
void *arg2,
|
||||
void *arg3);
|
||||
|
||||
/*
|
||||
* Frame used by _thread_entry_wrapper
|
||||
*
|
||||
* Allocate a 16 register window save area at bottom of the stack. This is
|
||||
* required if we need to taken a trap (interrupt) in the thread entry wrapper.
|
||||
*/
|
||||
struct init_stack_frame {
|
||||
uint32_t window_save_area[16];
|
||||
k_thread_entry_t entry_point;
|
||||
void *arg1;
|
||||
void *arg2;
|
||||
void *arg3;
|
||||
uint32_t pad[8];
|
||||
};
|
||||
|
||||
void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
char *stack_ptr, k_thread_entry_t entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
{
|
||||
struct init_stack_frame *iframe;
|
||||
|
||||
/* Initial stack frame data, stored at base of the stack */
|
||||
iframe = Z_STACK_PTR_TO_FRAME(struct init_stack_frame, stack_ptr);
|
||||
|
||||
iframe->entry_point = entry;
|
||||
iframe->arg1 = p1;
|
||||
iframe->arg2 = p2;
|
||||
iframe->arg3 = p3;
|
||||
|
||||
/* Put values for debugging purposes */
|
||||
thread->callee_saved.i6 = 0; /* frame pointer */
|
||||
thread->callee_saved.o6 = (uint32_t) iframe; /* stack pointer */
|
||||
thread->callee_saved.o7 = (uint32_t) z_thread_entry_wrapper - 8;
|
||||
thread->callee_saved.psr = PSR_S | PSR_PS | PSR_ET;
|
||||
|
||||
thread->switch_handle = thread;
|
||||
}
|
||||
|
||||
void *z_arch_get_next_switch_handle(struct k_thread **old_thread)
|
||||
{
|
||||
*old_thread = _current;
|
||||
|
||||
return z_get_next_switch_handle(*old_thread);
|
||||
}
|
192
arch/sparc/core/trap_table_mvt.S
Normal file
192
arch/sparc/core/trap_table_mvt.S
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a full SPARC V8 trap table. The processor redirects
|
||||
* exection to the trap table on trap events. Each trap table entrys is four
|
||||
* instructions.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
#define BAD_TRAP \
|
||||
rd %psr, %l0; \
|
||||
sethi %hi(__sparc_trap_fault), %l4; \
|
||||
jmp %l4+%lo(__sparc_trap_fault); \
|
||||
rd %tbr, %l6;
|
||||
|
||||
#define INTERRUPT_TRAP(level) \
|
||||
rd %psr, %l0; \
|
||||
sethi %hi(INT_HANDLER), %l4; \
|
||||
jmp %l4+%lo(INT_HANDLER); \
|
||||
mov (0xf & level), %l3;
|
||||
|
||||
#define TRAP(handler) \
|
||||
rd %psr, %l0; \
|
||||
sethi %hi(handler), %l4; \
|
||||
jmp %l4+%lo(handler); \
|
||||
nop;
|
||||
|
||||
#define RESET_TRAP(handler) \
|
||||
mov %g0, %g4; \
|
||||
sethi %hi(handler), %g4; \
|
||||
jmp %g4+%lo(handler); \
|
||||
nop;
|
||||
|
||||
#define SOFT_TRAP \
|
||||
ta 0x00; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
#define WOF_TRAP TRAP(__sparc_trap_window_overflow)
|
||||
#define WUF_TRAP TRAP(__sparc_trap_window_underflow)
|
||||
#define FLW_TRAP BAD_TRAP
|
||||
#define INT_HANDLER __sparc_trap_interrupt
|
||||
|
||||
#ifdef CONFIG_IRQ_OFFLOAD
|
||||
#define IRQ_OFFLOAD_TRAP TRAP(__sparc_trap_irq_offload)
|
||||
#else
|
||||
#define IRQ_OFFLOAD_TRAP BAD_TRAP
|
||||
#endif
|
||||
|
||||
GTEXT(__sparc_trap_table)
|
||||
GTEXT(__start)
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, traptable, __sparc_trap_table)
|
||||
__start:
|
||||
/*
|
||||
* Values in the range 0 to 0x5F that are not assigned in SPARC V8
|
||||
* specification Table 7-1 are reserved for future versions of the
|
||||
* architecture.
|
||||
*/
|
||||
RESET_TRAP(__sparc_trap_reset); ! 00 reset
|
||||
BAD_TRAP; ! 01 instruction_access_exception
|
||||
BAD_TRAP; ! 02 illegal_instruction
|
||||
BAD_TRAP; ! 03 priveleged_instruction
|
||||
BAD_TRAP; ! 04 fp_disabled
|
||||
WOF_TRAP; ! 05 window_overflow
|
||||
WUF_TRAP; ! 06 window_underflow
|
||||
BAD_TRAP; ! 07 mem_address_not_aligned
|
||||
BAD_TRAP; ! 08 fp_exception
|
||||
BAD_TRAP; ! 09 data_access_exception
|
||||
BAD_TRAP; ! 0A tag_overflow
|
||||
BAD_TRAP; ! 0B watchpoint_detected
|
||||
BAD_TRAP; ! 0C reserved
|
||||
BAD_TRAP; ! 0D reserved
|
||||
BAD_TRAP; ! 0E reserved
|
||||
BAD_TRAP; ! 0F reserved
|
||||
BAD_TRAP; ! 10 reserved
|
||||
|
||||
/* Interrupt traps */
|
||||
INTERRUPT_TRAP(1); ! 11 interrupt_level_1
|
||||
INTERRUPT_TRAP(2); ! 12 interrupt_level_2
|
||||
INTERRUPT_TRAP(3); ! 13 interrupt_level_3
|
||||
INTERRUPT_TRAP(4); ! 14 interrupt_level_4
|
||||
INTERRUPT_TRAP(5); ! 15 interrupt_level_5
|
||||
INTERRUPT_TRAP(6); ! 16 interrupt_level_6
|
||||
INTERRUPT_TRAP(7); ! 17 interrupt_level_7
|
||||
INTERRUPT_TRAP(8); ! 18 interrupt_level_8
|
||||
INTERRUPT_TRAP(9); ! 19 interrupt_level_9
|
||||
INTERRUPT_TRAP(10); ! 1A interrupt_level_1
|
||||
INTERRUPT_TRAP(11); ! 1B interrupt_level_11
|
||||
INTERRUPT_TRAP(12); ! 1C interrupt_level_12
|
||||
INTERRUPT_TRAP(13); ! 1D interrupt_level_13
|
||||
INTERRUPT_TRAP(14); ! 1E interrupt_level_14
|
||||
INTERRUPT_TRAP(15); ! 1F interrupt_level_15
|
||||
BAD_TRAP; ! 20 r_register_access_error
|
||||
BAD_TRAP; ! 21 instruction_access_error
|
||||
BAD_TRAP; ! 22 reserved
|
||||
BAD_TRAP; ! 23 reserved
|
||||
BAD_TRAP; ! 24 cp_disabled
|
||||
BAD_TRAP; ! 25 unimplemented_FLUSH
|
||||
BAD_TRAP; ! 26 reserved
|
||||
BAD_TRAP; ! 27 reserved
|
||||
BAD_TRAP; ! 28 cp_exception
|
||||
BAD_TRAP; ! 29 data_access_error
|
||||
BAD_TRAP; ! 2A division_by_zero
|
||||
BAD_TRAP; ! 2B data_store_error
|
||||
BAD_TRAP; ! 2C data_access_MMU_miss
|
||||
BAD_TRAP; ! 2D reserved
|
||||
BAD_TRAP; ! 2E reserved
|
||||
BAD_TRAP; ! 2F reserved
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 reserved
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 reserved
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B reserved
|
||||
BAD_TRAP; ! 3C instruction_access_MMU_miss
|
||||
BAD_TRAP; ! 3D reserved
|
||||
BAD_TRAP; ! 3E reserved
|
||||
BAD_TRAP; ! 3F reserved
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefined
|
||||
|
||||
/*
|
||||
* tt values 0x60 to 0x7F are reserved for implementation-dependent
|
||||
* exceptions.
|
||||
*/
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefined
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F undefined
|
||||
|
||||
/* trap_instruction 0x80 - 0xFF */
|
||||
/* NOTE: "ta 5" can be generated by compiler. */
|
||||
SOFT_TRAP; ! 0 System calls
|
||||
SOFT_TRAP; ! 1 Breakpoints
|
||||
SOFT_TRAP; ! 2 Division by zero
|
||||
FLW_TRAP; ! 3 Flush windows
|
||||
SOFT_TRAP; ! 4 Clean windows
|
||||
SOFT_TRAP; ! 5 Range checking
|
||||
SOFT_TRAP; ! 6 Fix alignment
|
||||
SOFT_TRAP; ! 7 Integer overflow
|
||||
SOFT_TRAP ! 8 System calls
|
||||
TRAP(__sparc_trap_sw_set_pil); ! 9 Reserved for the os
|
||||
SOFT_TRAP; ! 10 Reserved for the os
|
||||
SOFT_TRAP; ! 11 Reserved for the os
|
||||
/* See SPARC-ABI for purpose of the following software traps */
|
||||
SOFT_TRAP; ! 12
|
||||
IRQ_OFFLOAD_TRAP; ! 13
|
||||
SOFT_TRAP; ! 14
|
||||
SOFT_TRAP; ! 15
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9B
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9F
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - AB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AF
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BF
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CF
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DF
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EF
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FB
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! FC - FF
|
75
arch/sparc/core/window_trap.S
Normal file
75
arch/sparc/core/window_trap.S
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains standard handlers for the SPARC V8 window overflow and
|
||||
* underflow traps.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
GTEXT(__sparc_trap_window_overflow)
|
||||
GTEXT(__sparc_trap_window_underflow)
|
||||
|
||||
SECTION_FUNC(TEXT, __sparc_trap_window_overflow)
|
||||
/* Enter the window to be stored. */
|
||||
save
|
||||
/* Save local register set. */
|
||||
std %l0, [%sp + 0x00]
|
||||
std %l2, [%sp + 0x08]
|
||||
std %l4, [%sp + 0x10]
|
||||
rd %wim, %l3
|
||||
std %l6, [%sp + 0x18]
|
||||
/* l2 := WIM << (NWIN-1) */
|
||||
sll %l3, (CONFIG_SPARC_NWIN-1), %l2
|
||||
/* Save input register set. */
|
||||
std %i0, [%sp + 0x20]
|
||||
/* l3 := WIM >> 1 */
|
||||
srl %l3, 1, %l3
|
||||
std %i2, [%sp + 0x28]
|
||||
/* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */
|
||||
wr %l3, %l2, %wim
|
||||
/* NOTE: 3 instruction before restore (delayed write instruction) */
|
||||
std %i4, [%sp + 0x30]
|
||||
nop
|
||||
std %i6, [%sp + 0x38]
|
||||
/* Go back to trap window. */
|
||||
restore
|
||||
/* Re-execute save. */
|
||||
jmp %l1
|
||||
rett %l2
|
||||
|
||||
SECTION_FUNC(TEXT, __sparc_trap_window_underflow)
|
||||
rd %wim, %l3
|
||||
/* l4 := WIM << 1 */
|
||||
sll %l3, 1, %l4
|
||||
/* l5 := WIM >> (NWIN-1) */
|
||||
srl %l3, (CONFIG_SPARC_NWIN-1), %l5
|
||||
/* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */
|
||||
wr %l4, %l5, %wim
|
||||
/* WIM is implicitly read so nops are needed. */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Enter the window to restore requires two restore instructions. */
|
||||
restore
|
||||
restore
|
||||
ldd [%sp + 0x00], %l0
|
||||
ldd [%sp + 0x08], %l2
|
||||
ldd [%sp + 0x10], %l4
|
||||
ldd [%sp + 0x18], %l6
|
||||
ldd [%sp + 0x20], %i0
|
||||
ldd [%sp + 0x28], %i2
|
||||
ldd [%sp + 0x30], %i4
|
||||
ldd [%sp + 0x38], %i6
|
||||
/* Go back to the trap window. */
|
||||
save
|
||||
save
|
||||
/* Re-execute restore. */
|
||||
jmp %l1
|
||||
rett %l2
|
38
arch/sparc/include/kernel_arch_data.h
Normal file
38
arch/sparc/include/kernel_arch_data.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Private kernel definitions
|
||||
*
|
||||
* This file contains private kernel structures definitions and various
|
||||
* other definitions for the SPARC processor architecture.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_DATA_H_
|
||||
#define ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_DATA_H_
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <sys/util.h>
|
||||
#include <sys/dlist.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_DATA_H_ */
|
54
arch/sparc/include/kernel_arch_func.h
Normal file
54
arch/sparc/include/kernel_arch_func.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Private kernel definitions
|
||||
*
|
||||
* This file contains private kernel function/macro definitions and various
|
||||
* other definitions for the SPARC processor architecture.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_FUNC_H_
|
||||
#define ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_FUNC_H_
|
||||
|
||||
#include <kernel_arch_data.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
static ALWAYS_INLINE void arch_kernel_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void z_sparc_arch_switch(void *switch_to, void **switched_from);
|
||||
|
||||
static inline void arch_switch(void *switch_to, void **switched_from)
|
||||
{
|
||||
z_sparc_arch_switch(switch_to, switched_from);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason,
|
||||
const z_arch_esf_t *esf);
|
||||
|
||||
static inline bool arch_is_in_isr(void)
|
||||
{
|
||||
return _current_cpu->nested != 0U;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_OFFLOAD
|
||||
void z_irq_do_offload(void);
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_ARCH_SPARC_INCLUDE_KERNEL_ARCH_FUNC_H_ */
|
69
arch/sparc/include/offsets_short_arch.h
Normal file
69
arch/sparc/include/offsets_short_arch.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_
|
||||
#define ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_
|
||||
|
||||
#include <offsets.h>
|
||||
|
||||
#define _thread_offset_to_y \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_y_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l0_and_l1 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l0_and_l1_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l2 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l2_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l3 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l3_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l4 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l4_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l5 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l5_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l6 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l6_OFFSET)
|
||||
|
||||
#define _thread_offset_to_l7 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_l7_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i0 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i0_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i1 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i1_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i2 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i2_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i3 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i3_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i4 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i4_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i5 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i5_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i6 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i6_OFFSET)
|
||||
|
||||
#define _thread_offset_to_i7 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_i7_OFFSET)
|
||||
|
||||
#define _thread_offset_to_o6 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_o6_OFFSET)
|
||||
|
||||
#define _thread_offset_to_o7 \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_o7_OFFSET)
|
||||
|
||||
#define _thread_offset_to_psr \
|
||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_psr_OFFSET)
|
||||
|
||||
#endif /* ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ */
|
|
@ -27,6 +27,8 @@
|
|||
#include <arch/xtensa/arch.h>
|
||||
#elif defined(CONFIG_ARCH_POSIX)
|
||||
#include <arch/posix/arch.h>
|
||||
#elif defined(CONFIG_SPARC)
|
||||
#include <arch/sparc/arch.h>
|
||||
#else
|
||||
#error "Unknown Architecture"
|
||||
#endif
|
||||
|
|
119
include/arch/sparc/arch.h
Normal file
119
include/arch/sparc/arch.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief SPARC specific kernel interface header
|
||||
* This header contains the SPARC specific kernel interface. It is
|
||||
* included by the generic kernel interface header (arch/cpu.h)
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_
|
||||
#define ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_
|
||||
|
||||
#include <arch/sparc/thread.h>
|
||||
#include <arch/sparc/sparc.h>
|
||||
#include <arch/common/sys_bitops.h>
|
||||
#include <arch/common/sys_io.h>
|
||||
#include <arch/common/ffs.h>
|
||||
|
||||
#include <irq.h>
|
||||
#include <sw_isr_table.h>
|
||||
#include <soc.h>
|
||||
#include <devicetree.h>
|
||||
|
||||
/* stacks, for SPARC architecture stack shall be 8byte-aligned */
|
||||
#define ARCH_STACK_PTR_ALIGN 8
|
||||
|
||||
/*
|
||||
* Software trap numbers.
|
||||
* Assembly usage: "ta SPARC_SW_TRAP_<TYPE>"
|
||||
*/
|
||||
#define SPARC_SW_TRAP_FLUSH_WINDOWS 0x03
|
||||
#define SPARC_SW_TRAP_SET_PIL 0x09
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <sys/util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STACK_ROUND_UP(x) ROUND_UP(x, ARCH_STACK_PTR_ALIGN)
|
||||
|
||||
/*
|
||||
* SOC specific function to translate from processor interrupt request level
|
||||
* (1..15) to logical interrupt source number. For example by probing the
|
||||
* interrupt controller.
|
||||
*/
|
||||
int z_sparc_int_get_source(int irl);
|
||||
void z_irq_spurious(const void *unused);
|
||||
|
||||
|
||||
#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
|
||||
{ \
|
||||
Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
|
||||
}
|
||||
|
||||
|
||||
static ALWAYS_INLINE unsigned int z_sparc_set_pil_inline(unsigned int newpil)
|
||||
{
|
||||
register uint32_t oldpil __asm__ ("o0") = newpil;
|
||||
|
||||
__asm__ volatile (
|
||||
"ta %1\nnop\n" :
|
||||
"=r" (oldpil) :
|
||||
"i" (SPARC_SW_TRAP_SET_PIL), "r" (oldpil)
|
||||
);
|
||||
return oldpil;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE unsigned int arch_irq_lock(void)
|
||||
{
|
||||
return z_sparc_set_pil_inline(15);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
|
||||
{
|
||||
z_sparc_set_pil_inline(key);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
|
||||
{
|
||||
return key == 0;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void arch_nop(void)
|
||||
{
|
||||
__asm__ volatile ("nop");
|
||||
}
|
||||
|
||||
extern uint32_t z_timer_cycle_get_32(void);
|
||||
|
||||
static inline uint32_t arch_k_cycle_get_32(void)
|
||||
{
|
||||
return z_timer_cycle_get_32();
|
||||
}
|
||||
|
||||
|
||||
struct __esf {
|
||||
uint32_t pc;
|
||||
uint32_t npc;
|
||||
uint32_t psr;
|
||||
uint32_t tbr;
|
||||
uint32_t sp;
|
||||
uint32_t y;
|
||||
};
|
||||
|
||||
typedef struct __esf z_arch_esf_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_ */
|
160
include/arch/sparc/linker.ld
Normal file
160
include/arch/sparc/linker.ld
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Linker command/script file for SPARC
|
||||
*/
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
#include <autoconf.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
#include <linker/linker-defs.h>
|
||||
#include <linker/linker-tool.h>
|
||||
|
||||
ENTRY(CONFIG_KERNEL_ENTRY)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
#include <linker/rel-sections.ld>
|
||||
|
||||
_image_rom_start = .;
|
||||
|
||||
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
|
||||
{
|
||||
/* Trap table alignment required by SPARC V8 specification. */
|
||||
. = ALIGN(0x1000);
|
||||
_image_text_start = .;
|
||||
|
||||
*(.text.traptable)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.stub)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} GROUP_LINK_IN(REGION_TEXT)
|
||||
|
||||
_image_text_end = .;
|
||||
|
||||
#include <linker/common-rom.ld>
|
||||
|
||||
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
|
||||
{
|
||||
. = ALIGN(8);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-rodata.ld>
|
||||
|
||||
} GROUP_LINK_IN(REGION_RODATA)
|
||||
|
||||
#include <linker/cplusplus-rom.ld>
|
||||
|
||||
_image_rom_end = .;
|
||||
__data_rom_start = .;
|
||||
|
||||
|
||||
SECTION_PROLOGUE(.plt,,)
|
||||
{
|
||||
*(.plt)
|
||||
}
|
||||
|
||||
SECTION_PROLOGUE(.iplt,,)
|
||||
{
|
||||
*(.iplt)
|
||||
}
|
||||
|
||||
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_image_ram_start = .;
|
||||
__data_ram_start = .;
|
||||
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-rwdata.ld>
|
||||
|
||||
} GROUP_DATA_LINK_IN(REGION_DATA_VMA, REGION_DATA_LMA)
|
||||
|
||||
#include <linker/common-ram.ld>
|
||||
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-ram-sections.ld>
|
||||
__data_ram_end = .;
|
||||
|
||||
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
|
||||
{
|
||||
/*
|
||||
* For performance, BSS section is assumed to be 4 byte aligned and
|
||||
* a multiple of 4 bytes
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
COMMON_SYMBOLS
|
||||
/*
|
||||
* As memory is cleared in words only, it is simpler to ensure the BSS
|
||||
* section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
|
||||
*/
|
||||
__bss_end = ALIGN(4);
|
||||
} GROUP_LINK_IN(REGION_BSS)
|
||||
|
||||
SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),)
|
||||
{
|
||||
/*
|
||||
* This section is used for non-initialized objects that
|
||||
* will not be cleared during the boot process.
|
||||
*/
|
||||
*(.noinit)
|
||||
*(.noinit.*)
|
||||
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-noinit.ld>
|
||||
|
||||
} GROUP_LINK_IN(REGION_BSS)
|
||||
|
||||
#include <linker/cplusplus-ram.ld>
|
||||
|
||||
_image_ram_end = .;
|
||||
_end = .; /* end of image */
|
||||
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-sections.ld>
|
||||
|
||||
#include <linker/debug-sections.ld>
|
||||
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
/DISCARD/ : { *(.gnu_debuglink) }
|
||||
/DISCARD/ : { *(.gnu.lto_*) }
|
||||
|
||||
SECTION_PROLOGUE(.gnu.attributes, 0,)
|
||||
{
|
||||
KEEP(*(.gnu.attributes))
|
||||
}
|
||||
|
||||
}
|
40
include/arch/sparc/sparc.h
Normal file
40
include/arch/sparc/sparc.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ARCH_SPARC_SPARC_H_
|
||||
#define ZEPHYR_INCLUDE_ARCH_SPARC_SPARC_H_
|
||||
|
||||
/*
|
||||
* @file
|
||||
* @brief Definitions for the SPARC V8 architecture.
|
||||
*/
|
||||
|
||||
/* Processor State Register */
|
||||
#define PSR_VER_BIT 24
|
||||
#define PSR_PIL_BIT 8
|
||||
|
||||
#define PSR_VER (0xf << PSR_VER_BIT)
|
||||
#define PSR_EF (1 << 12)
|
||||
#define PSR_S (1 << 7)
|
||||
#define PSR_PS (1 << 6)
|
||||
#define PSR_ET (1 << 5)
|
||||
#define PSR_PIL (0xf << PSR_PIL_BIT)
|
||||
#define PSR_CWP 0x1f
|
||||
|
||||
|
||||
/* Trap Base Register */
|
||||
#define TBR_TT_BIT 4
|
||||
|
||||
#define TBR_TBA 0xfffff000
|
||||
#define TBR_TT 0x00000ff0
|
||||
|
||||
/* Trap types in TBR.TT */
|
||||
#define TT_RESET 0x00
|
||||
#define TT_WINDOW_OVERFLOW 0x05
|
||||
#define TT_WINDOW_UNDERFLOW 0x06
|
||||
#define TT_DATA_ACCESS_EXCEPTION 0x09
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_SPARC_SPARC_H_ */
|
76
include/arch/sparc/thread.h
Normal file
76
include/arch/sparc/thread.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains definitions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ARCH_SPARC_THREAD_H_
|
||||
#define ZEPHYR_INCLUDE_ARCH_SPARC_THREAD_H_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/*
|
||||
* The following structure defines the list of registers that need to be
|
||||
* saved/restored when a cooperative context switch occurs.
|
||||
*/
|
||||
struct _callee_saved {
|
||||
/* y register used by mul/div */
|
||||
uint32_t y;
|
||||
|
||||
/* processor status register */
|
||||
uint32_t psr;
|
||||
|
||||
/*
|
||||
* local registers
|
||||
*
|
||||
* Using uint64_t l0_and_l1 will put everything in this structure on a
|
||||
* double word boundary which allows us to use double word loads and
|
||||
* stores safely in the context switch.
|
||||
*/
|
||||
uint64_t l0_and_l1;
|
||||
uint32_t l2;
|
||||
uint32_t l3;
|
||||
uint32_t l4;
|
||||
uint32_t l5;
|
||||
uint32_t l6;
|
||||
uint32_t l7;
|
||||
|
||||
/* input registers */
|
||||
uint32_t i0;
|
||||
uint32_t i1;
|
||||
uint32_t i2;
|
||||
uint32_t i3;
|
||||
uint32_t i4;
|
||||
uint32_t i5;
|
||||
uint32_t i6; /* frame pointer */
|
||||
uint32_t i7;
|
||||
|
||||
/* output registers */
|
||||
uint32_t o6; /* stack pointer */
|
||||
uint32_t o7;
|
||||
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
/* empty */
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_SPARC_THREAD_H_ */
|
Loading…
Reference in a new issue