arc: enable gen_isr_tables mechanism

Change-Id: I5897e110f554377796bfe38dd5c0f8652c29e5be
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-02-13 09:36:32 -08:00
commit 35fcb2736c
10 changed files with 56 additions and 212 deletions

View file

@ -144,6 +144,12 @@ config XIP
default n if NSIM
default y
config GEN_ISR_TABLES
default y
config GEN_IRQ_START_VECTOR
default 16
config HARVARD
prompt "Harvard Architecture"
bool
@ -208,46 +214,6 @@ config FLASH_BASE_ADDRESS
normally set by the board's defconfig file and the user should generally
avoid modifying it via the menu configuration.
config SW_ISR_TABLE
bool
prompt "Enable software interrupt handler table"
default y
help
Enable an interrupt handler table implemented in software. This
table, unlike ISRs connected directly in the vector table, allow
a parameter to be passed to the interrupt handlers. Also, invoking
the exeception/interrupt exit stub is automatically done.
config IRQ_VECTOR_TABLE_CUSTOM
bool
prompt "Projects provide a custom static IRQ part of vector table"
depends on !SW_ISR_TABLE
default n
help
Projects, not the BSP, provide the IRQ part of the vector table.
This is the table of interrupt handlers with the best potential
performance, but is the less flexible.
The ISRs are installed directly in the vector table, thus are
directly called by the CPU when an interrupt is taken. This adds
the least overhead when handling an interrupt.
Downsides:
- ISRs cannot have a parameter
- ISRs cannot be connected at runtime
- ISRs must notify the kernel manually by invoking _ExcExit() when
then are about to return.
config IRQ_VECTOR_TABLE_BSP
bool
# omit prompt to signify a "hidden" option
depends on SW_ISR_TABLE || !IRQ_VECTOR_TABLE_CUSTOM
default y
help
Not user-selectable, helps build system logic.
config CACHE_LINE_SIZE_DETECT
bool
prompt "Detect d-cache line size at runtime"

View file

@ -16,5 +16,3 @@ obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
# Some ARC cores like the EM4 lack the atomic LLOCK/SCOND and
# can't use these.
obj-$(CONFIG_ATOMIC_OPERATIONS_CUSTOM) += atomic.o
obj-$(CONFIG_IRQ_VECTOR_TABLE_BSP) += irq_vector_table.o
obj-$(CONFIG_SW_ISR_TABLE) += sw_isr_table.o

View file

@ -72,7 +72,7 @@ SECTION_FUNC(TEXT, _firq_enter)
* If CONFIG_RGF_NUM_BANKS>1, firq uses a 2nd register bank so GPRs do
* not need to be saved.
* If CONFIG_RGF_NUM_BANKS==1, firq must use the stack to save registers.
* This has already been done by _isr_enter.
* This has already been done by _isr_wrapper.
*/
#ifdef CONFIG_ARC_STACK_CHECKING

View file

@ -1,43 +0,0 @@
/*
* Copyright (c) 2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief IRQ part of vector table for Quark SE Sensor Subsystem
*
* This file contains the IRQ part of the vector table. It is meant to be used
* for one of two cases:
*
* a) When software-managed ISRs (SW_ISR_TABLE) is enabled, and in that case it
* binds _IsrWrapper() to all the IRQ entries in the vector table.
*
* b) When the BSP is written so that device ISRs are installed directly in the
* vector table, they are enumerated here.
*
*/
#include <toolchain.h>
#include <sections.h>
extern void _isr_enter(void);
typedef void (*vth)(void); /* Vector Table Handler */
#if defined(CONFIG_SW_ISR_TABLE)
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS - 16] = {
[0 ...(CONFIG_NUM_IRQS - 17)] = _isr_enter
};
#elif !defined(CONFIG_IRQ_VECTOR_TABLE_CUSTOM)
extern void _SpuriousIRQ(void);
/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS - 16] = {
[0 ...(CONFIG_NUM_IRQS - 17)] = _SpuriousIRQ
};
#endif /* CONFIG_SW_ISR_TABLE */

View file

@ -20,7 +20,7 @@
#include <kernel_structs.h>
#include <arch/cpu.h>
GTEXT(_isr_enter)
GTEXT(_isr_wrapper)
GTEXT(_isr_demux)
#if CONFIG_RGF_NUM_BANKS == 1
@ -41,9 +41,9 @@ _rirq_enter/_firq_enter: they are jump points.
The flow is the following:
ISR -> _isr_enter -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
ISR -> _isr_wrapper -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
Context switch explanation:
@ -216,7 +216,7 @@ From RIRQ:
interrupt.
*/
SECTION_FUNC(TEXT, _isr_enter)
SECTION_FUNC(TEXT, _isr_wrapper)
#if CONFIG_RGF_NUM_BANKS == 1
st r0,[saved_r0]
#endif

View file

@ -1,52 +0,0 @@
/* sw_isr_table.S - ISR table for static ISR declarations for ARC */
/*
* Copyright (c) 2015 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <sections.h>
#include <arch/cpu.h>
/*
* enable preprocessor features, such
* as %expr - evaluate the expression and use it as a string
*/
.altmacro
/*
* Define an ISR table entry
* Define symbol as weak and give the section .gnu.linkonce
* prefix. This allows linker overload the symbol and the
* whole section by the one defined by a device driver
*/
.macro _isr_table_entry_declare index
WDATA(_isr_irq\index)
.section .gnu.linkonce.isr_irq\index
_isr_irq\index: .word 0xABAD1DEA, _irq_spurious
.endm
/*
* Declare the ISR table
*/
.macro _isr_table_declare from, to
counter = \from
.rept (\to - \from)
_isr_table_entry_declare %counter
counter = counter + 1
.endr
.endm
GTEXT(_irq_spurious)
GDATA(_sw_isr_table)
.section .isr_irq16
.align
_sw_isr_table:
/*In ARC architecture, IRQ 0-15 are reserved for the system and are not
assignable by the user, for that reason the isr table linker section
start at IRQ 16*/
_isr_table_declare 16 CONFIG_NUM_IRQS

View file

@ -134,7 +134,7 @@ parameter.
executing. A common interrupt handler demuxer is installed for all entries of
the real interrupt vector table, which then fetches the device's ISR and
parameter from the separate table. This approach is commonly used in the ARC
and ARM architectures via the :option:`CONFIG_SW_ISR_TABLE` implementation.
and ARM architectures via the :option:`CONFIG_GEN_ISR_TABLES` implementation.
You can find examples of the stubs by looking at :code:`_interrupt_enter()` in
x86, :code:`_IntExit()` in ARM, :code:`_isr_wrapper()` in ARM, or the full
implementation description for ARC in :file:`arch/arc/core/isr_wrapper.S`.

View file

@ -43,53 +43,4 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#ifndef _ASMLANGUAGE
#include <irq.h>
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
extern void _irq_priority_set(unsigned int irq, unsigned int prio,
uint32_t flags);
/**
* Configure a static interrupt.
*
* All arguments must be computable by the compiler at build time.
*
* Internally this function does a few things:
*
* 1. The enum statement has no effect but forces the compiler to only
* accept constant values for the irq_p parameter, very important as the
* numerical IRQ line is used to create a named section.
*
* 2. An instance of struct _isr_table_entry is created containing the ISR and
* its parameter. If you look at how _sw_isr_table is created, each entry in
* the array is in its own section named by the IRQ line number. What we are
* doing here is to override one of the default entries (which points to the
* spurious IRQ handler) with what was supplied here.
*
* 3. The priority level for the interrupt is configured by a call to
* _irq_priority_set()
*
* @param irq_p IRQ line number
* @param priority_p Interrupt priority, in range 0-13
* @param isr_p Interrupt service routine
* @param isr_param_p ISR parameter
* @param flags_p IRQ options (ignored for now)
*
* @return The vector assigned to this interrupt
*/
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
({ \
enum { IRQ = irq_p }; \
static struct _isr_table_entry _CONCAT(_isr_irq, irq_p) \
__attribute__ ((used)) \
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
{isr_param_p, isr_p}; \
_irq_priority_set(irq_p, priority_p, flags_p); \
irq_p; \
})
#endif
#endif /* _ARC_ARCH__H_ */

View file

@ -18,6 +18,7 @@
#include <toolchain/common.h>
#include <irq.h>
#include <misc/util.h>
#include <sw_isr_table.h>
#ifdef __cplusplus
extern "C" {
@ -33,6 +34,40 @@ extern void _arch_irq_enable(unsigned int irq);
extern void _arch_irq_disable(unsigned int irq);
extern void _irq_exit(void);
extern void _irq_priority_set(unsigned int irq, unsigned int prio,
uint32_t flags);
extern void _isr_wrapper(void);
extern void _irq_spurious(void *unused);
/**
* Configure a static interrupt.
*
* All arguments must be computable by the compiler at build time.
*
* _ISR_DECLARE will populate the .intList section with the interrupt's
* parameters, which will then be used by gen_irq_tables.py to create
* the vector table and the software ISR table. This is all done at
* build-time.
*
* We additionally set the priority in the interrupt controller at
* runtime.
*
* @param irq_p IRQ line number
* @param priority_p Interrupt priority
* @param isr_p Interrupt service routine
* @param isr_param_p ISR parameter
* @param flags_p IRQ options
*
* @return The vector assigned to this interrupt
*/
#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
({ \
_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
_irq_priority_set(irq_p, priority_p, flags_p); \
irq_p; \
})
/**
*

View file

@ -57,6 +57,8 @@ MEMORY {
#ifdef DCCM_START
DCCM (rw) : ORIGIN = DCCM_START, LENGTH = DCCM_SIZE*1k
#endif
/* Used by and documented in include/linker/intlist.ld */
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}
SECTIONS {
@ -72,25 +74,9 @@ SECTIONS {
KEEP(*(".exc_vector_table.*"))
KEEP(*(IRQ_VECTOR_TABLE))
KEEP(*(.isr_irq*))
/*
* The following sections maps the location of the different
* rows for the _sw_isr_table. Each row maps to an IRQ entry
* (handler, argument).
*
* In ARC architecture, IRQ 0-15 are reserved for the system
* and are not * assignable by the user, for that reason the
* linker sections start on IRQ 16
*/
/* sections for IRQ16-19 */
KEEP(*(SORT(.gnu.linkonce.isr_irq[1][6-9])))
/* sections for IRQ20-99 */
KEEP(*(SORT(.gnu.linkonce.isr_irq[2-9][0-9])))
/* sections for IRQ100-999 */
KEEP(*(SORT(.gnu.linkonce.isr_irq[1-9][0-9][0-9])))
#ifdef CONFIG_GEN_SW_ISR_TABLE
KEEP(*(SW_ISR_TABLE))
#endif
*(.text)
*(".text.*")
*(.gnu.linkonce.t.*)
@ -189,4 +175,7 @@ SECTIONS {
#include <custom-sections.ld>
#endif
#ifdef CONFIG_GEN_ISR_TABLES
#include <linker/intlist.ld>
#endif
}