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
26 changed files with 1839 additions and 0 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue