forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arch: riscv32: provide a general mechanism for saving SoC context
RISC-V permits myriad extensions to the ISA, any of which may imply additional context that must be saved and restored on ISR entry and exit. The current in-tree example is the Pulpino core, which has extra registers used by ISA extensions for running loops that shouldn't get clobbered by an ISR. This is currently supported by including pulpino-specific definitions in the generic architecture code. This works, but it's a bit inelegant and is something of a layering violation. A more generic mechanism is required to support other RISC-V SoCs with similar requirements without cluttering the arch code too much. Provide that by extending the semantics of the existing CONFIG_RISCV_SOC_CONTEXT_SAVE option to allow other SoCs to allocate space for saving and restoring their own state, promoting the currently pulpino-specific __soc_save_context / __soc_restore_context routines to a RISC-V arch API. The cost of making this generic is two more instructions in each ISR to pass the SoC specific context to these routines in a0 rather than just assuming the stack points to the right place. This is minimal, and should have been done anyway to keep with the ABI. As a first (and currently only in-tree) customer, convert the Pulpino SoC code to this new mechanism. Signed-off-by: Marti Bolivar <[email protected]>
- Loading branch information
Showing
7 changed files
with
161 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2016 Jean-Paul Etienne <[email protected]> | ||
* Copyright (c) 2018 Foundries.io Ltd | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
@@ -11,11 +12,13 @@ | |
|
||
/* imports */ | ||
GDATA(_sw_isr_table) | ||
GTEXT(__soc_save_context) | ||
GTEXT(__soc_restore_context) | ||
GTEXT(__soc_is_irq) | ||
GTEXT(__soc_handle_irq) | ||
GTEXT(_Fault) | ||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
GTEXT(__soc_save_context) | ||
GTEXT(__soc_restore_context) | ||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ | ||
|
||
GTEXT(_k_neg_eagain) | ||
GTEXT(_is_next_thread_current) | ||
|
@@ -36,23 +39,24 @@ GTEXT(__irq_wrapper) | |
/* use ABI name of registers for the sake of simplicity */ | ||
|
||
/* | ||
* ISR is handled at both ARCH and SOC levels. | ||
* At the ARCH level, ISR handles basic context saving/restore of registers | ||
* onto/from the thread stack and calls corresponding IRQ function registered | ||
* at driver level. | ||
|
||
* At SOC level, ISR handles saving/restoring of SOC-specific registers | ||
* onto/from the thread stack (handled via __soc_save_context and | ||
* __soc_restore_context functions). SOC level save/restore context | ||
* is accounted for only if CONFIG_RISCV_SOC_CONTEXT_SAVE variable is set | ||
* Generic architecture-level IRQ handling, along with callouts to | ||
* SoC-specific routines. | ||
* | ||
* Architecture level IRQ handling includes basic context save/restore | ||
* of standard registers and calling ISRs registered at Zephyr's driver | ||
* level. | ||
* | ||
* Since RISC-V does not completely prescribe IRQ handling behavior, | ||
* implementations vary (some implementations also deviate from | ||
* what standard behavior is defined). Hence, the arch level code expects | ||
* the following functions to be provided at the SOC level: | ||
* | ||
* - __soc_is_irq: decide if we're handling an interrupt or an exception | ||
* - __soc_handle_irq: handle SoC-specific details for a pending IRQ | ||
* (e.g. clear a pending bit in a SoC-specific register) | ||
* | ||
* Moreover, given that RISC-V architecture does not provide a clear ISA | ||
* specification about interrupt handling, each RISC-V SOC handles it in | ||
* its own way. Hence, the generic RISC-V ISR handler expects the following | ||
* functions to be provided at the SOC level: | ||
* __soc_is_irq: to check if the exception is the result of an interrupt or not. | ||
* __soc_handle_irq: handle pending IRQ at SOC level (ex: clear pending IRQ in | ||
* SOC-specific IRQ register) | ||
* If CONFIG_RISCV_SOC_CONTEXT=y, calls to SoC-level context save/restore | ||
* routines are also made here. For details, see the Kconfig help text. | ||
*/ | ||
|
||
/* | ||
|
@@ -99,6 +103,7 @@ SECTION_FUNC(exception.entry, __irq_wrapper) | |
|
||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
/* Handle context saving at SOC level. */ | ||
addi a0, sp, __NANO_ESF_soc_context_OFFSET | ||
jal ra, __soc_save_context | ||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ | ||
|
||
|
@@ -409,6 +414,7 @@ reschedule: | |
no_reschedule: | ||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
/* Restore context at SOC level */ | ||
addi a0, sp, __NANO_ESF_soc_context_OFFSET | ||
jal ra, __soc_restore_context | ||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2016 Jean-Paul Etienne <[email protected]> | ||
* Copyright (c) 2018 Foundries.io Ltd | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
@@ -22,6 +23,24 @@ extern "C" { | |
#include <zephyr/types.h> | ||
#include <toolchain.h> | ||
|
||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
#include <soc_context.h> | ||
#endif | ||
|
||
/* | ||
* The name of the structure which contains soc-specific state, if | ||
* any, as well as the soc_esf_t typedef below, are part of the RISC-V | ||
* arch API. | ||
* | ||
* The contents of the struct are provided by a SOC-specific | ||
* definition in soc_context.h. | ||
*/ | ||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
struct soc_esf { | ||
SOC_ESF_MEMBERS; | ||
}; | ||
#endif | ||
|
||
struct __esf { | ||
u32_t ra; /* return address */ | ||
u32_t gp; /* global pointer */ | ||
|
@@ -47,18 +66,15 @@ struct __esf { | |
u32_t mepc; /* machine exception program counter */ | ||
u32_t mstatus; /* machine status register */ | ||
|
||
#if defined(CONFIG_SOC_RISCV32_PULPINO) | ||
/* pulpino hardware loop registers */ | ||
u32_t lpstart0; | ||
u32_t lpend0; | ||
u32_t lpcount0; | ||
u32_t lpstart1; | ||
u32_t lpend1; | ||
u32_t lpcount1; | ||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
struct soc_esf soc_context; | ||
#endif | ||
}; | ||
|
||
typedef struct __esf NANO_ESF; | ||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
typedef struct soc_esf soc_esf_t; | ||
#endif | ||
extern const NANO_ESF _default_esf; | ||
|
||
extern FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright (c) 2018 Foundries.io Ltd | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* | ||
* Extra definitions required for CONFIG_RISCV_SOC_CONTEXT_SAVE. | ||
*/ | ||
|
||
#ifndef PULPINO_SOC_CONTEXT_H_ | ||
#define PULPINO_SOC_CONTEXT_H_ | ||
|
||
/* Extra state for pulpino hardware loop registers. */ | ||
#define SOC_ESF_MEMBERS \ | ||
u32_t lpstart0; \ | ||
u32_t lpend0; \ | ||
u32_t lpcount0; \ | ||
u32_t lpstart1; \ | ||
u32_t lpend1; \ | ||
u32_t lpcount1 | ||
|
||
/* Initial saved state. */ | ||
#define SOC_ESF_INIT \ | ||
0xdeadbaad, \ | ||
0xdeadbaad, \ | ||
0xdeadbaad, \ | ||
0xdeadbaad, \ | ||
0xdeadbaad, \ | ||
0xdeadbaad | ||
|
||
/* Ensure offset macros are available in <offsets.h> for the above. */ | ||
#define GEN_SOC_OFFSET_SYMS() \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpstart0); \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpend0); \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpcount0); \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpstart1); \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpend1); \ | ||
GEN_OFFSET_SYM(soc_esf_t, lpcount1) | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2016 Jean-Paul Etienne <[email protected]> | ||
* Copyright (c) 2018 Foundries.io Ltd | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
@@ -19,51 +20,54 @@ GTEXT(__soc_irq_unlock) | |
|
||
/* Use ABI name of registers for the sake of simplicity */ | ||
|
||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE | ||
/* | ||
* Pulpino core has hardware loops registers that need to be saved | ||
* prior to handling an interrupt/exception. | ||
* The Pulpino core has ISA extensions for faster loop performance | ||
* that use extra registers. | ||
* | ||
* NOTE: Stack space allocation is not needed here, as already allocated at | ||
* architecture level with __NANO_ESF_SIZEOF value (including space for the | ||
* pulpino-specific registers) | ||
* If the toolchain generates instructions that use them, they must be saved | ||
* prior to handling an interrupt/exception. This case is handled using | ||
* Zephyr's generic RISC-V mechanism for soc-specific context. | ||
* | ||
* For details, see the Kconfig help for CONFIG_RISCV_SOC_CONTEXT_SAVE. | ||
*/ | ||
SECTION_FUNC(exception.other, __soc_save_context) | ||
/* Save hardware loop registers to stack */ | ||
/* Save hardware loop registers to the soc_esf_t passed in a0. */ | ||
csrr t0, PULP_LPSTART0 | ||
csrr t1, PULP_LPEND0 | ||
csrr t2, PULP_LPCOUNT0 | ||
sw t0, __NANO_ESF_lpstart0_OFFSET(sp) | ||
sw t1, __NANO_ESF_lpend0_OFFSET(sp) | ||
sw t2, __NANO_ESF_lpcount0_OFFSET(sp) | ||
sw t0, __soc_esf_t_lpstart0_OFFSET(a0) | ||
sw t1, __soc_esf_t_lpend0_OFFSET(a0) | ||
sw t2, __soc_esf_t_lpcount0_OFFSET(a0) | ||
csrr t0, PULP_LPSTART1 | ||
csrr t1, PULP_LPEND1 | ||
csrr t2, PULP_LPCOUNT1 | ||
sw t0, __NANO_ESF_lpstart1_OFFSET(sp) | ||
sw t1, __NANO_ESF_lpend1_OFFSET(sp) | ||
sw t2, __NANO_ESF_lpcount1_OFFSET(sp) | ||
sw t0, __soc_esf_t_lpstart1_OFFSET(a0) | ||
sw t1, __soc_esf_t_lpend1_OFFSET(a0) | ||
sw t2, __soc_esf_t_lpcount1_OFFSET(a0) | ||
|
||
/* Return */ | ||
jalr x0, ra | ||
|
||
|
||
SECTION_FUNC(exception.other, __soc_restore_context) | ||
/* Restore hardloop registers from stack */ | ||
lw t0, __NANO_ESF_lpstart0_OFFSET(sp) | ||
lw t1, __NANO_ESF_lpend0_OFFSET(sp) | ||
lw t2, __NANO_ESF_lpcount0_OFFSET(sp) | ||
/* Restore hardware loop registers from soc_esf_t in a0. */ | ||
lw t0, __soc_esf_t_lpstart0_OFFSET(a0) | ||
lw t1, __soc_esf_t_lpend0_OFFSET(a0) | ||
lw t2, __soc_esf_t_lpcount0_OFFSET(a0) | ||
csrw PULP_LPSTART0, t0 | ||
csrw PULP_LPEND0, t1 | ||
csrw PULP_LPCOUNT0, t2 | ||
lw t0, __NANO_ESF_lpstart1_OFFSET(sp) | ||
lw t1, __NANO_ESF_lpend1_OFFSET(sp) | ||
lw t2, __NANO_ESF_lpcount1_OFFSET(sp) | ||
lw t0, __soc_esf_t_lpstart1_OFFSET(a0) | ||
lw t1, __soc_esf_t_lpend1_OFFSET(a0) | ||
lw t2, __soc_esf_t_lpcount1_OFFSET(a0) | ||
csrw PULP_LPSTART1, t0 | ||
csrw PULP_LPEND1, t1 | ||
csrw PULP_LPCOUNT1, t2 | ||
|
||
/* Return */ | ||
jalr x0, ra | ||
|
||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ | ||
|
||
/* | ||
* SOC-specific function to handle pending IRQ number generating the interrupt. | ||
|