arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
*/
|
|
|
|
|
2024-05-21 16:06:07 +08:00
|
|
|
#include <zephyr/debug/symtab.h>
|
2022-05-06 10:49:15 +02:00
|
|
|
#include <zephyr/kernel.h>
|
|
|
|
#include <zephyr/kernel_structs.h>
|
2022-05-12 23:57:46 -04:00
|
|
|
#include <kernel_internal.h>
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
#include <inttypes.h>
|
2023-08-29 19:18:32 +00:00
|
|
|
#include <zephyr/arch/common/exc_handle.h>
|
2022-05-06 10:49:15 +02:00
|
|
|
#include <zephyr/logging/log.h>
|
2020-11-26 19:32:34 +01:00
|
|
|
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
2020-07-21 16:00:39 +02:00
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
Z_EXC_DECLARE(z_riscv_user_string_nlen);
|
|
|
|
|
|
|
|
static const struct z_exc_handle exceptions[] = {
|
|
|
|
Z_EXC_HANDLE(z_riscv_user_string_nlen),
|
|
|
|
};
|
|
|
|
#endif /* CONFIG_USERSPACE */
|
|
|
|
|
2021-01-07 21:16:00 +01:00
|
|
|
#if __riscv_xlen == 32
|
|
|
|
#define PR_REG "%08" PRIxPTR
|
|
|
|
#define NO_REG " "
|
|
|
|
#elif __riscv_xlen == 64
|
|
|
|
#define PR_REG "%016" PRIxPTR
|
|
|
|
#define NO_REG " "
|
|
|
|
#endif
|
|
|
|
|
2024-05-16 17:45:47 +08:00
|
|
|
/* Stack trace function */
|
|
|
|
void z_riscv_unwind_stack(const z_arch_esf_t *esf);
|
|
|
|
|
|
|
|
uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf)
|
2024-05-13 15:55:24 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kernel stack pointer prior this exception i.e. before
|
|
|
|
* storing the exception stack frame.
|
|
|
|
*/
|
|
|
|
uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t);
|
|
|
|
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
if ((esf->mstatus & MSTATUS_MPP) == PRV_U) {
|
|
|
|
/*
|
|
|
|
* Exception happened in user space:
|
|
|
|
* consider the saved user stack instead.
|
|
|
|
*/
|
|
|
|
sp = esf->sp;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return sp;
|
|
|
|
}
|
|
|
|
|
2019-07-17 13:17:05 -04:00
|
|
|
FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
|
|
|
const z_arch_esf_t *esf)
|
2024-03-06 16:25:06 +08:00
|
|
|
{
|
|
|
|
z_riscv_fatal_error_csf(reason, esf, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf,
|
|
|
|
const _callee_saved_t *csf)
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
{
|
2023-12-12 09:57:11 -05:00
|
|
|
#ifdef CONFIG_EXCEPTION_DEBUG
|
2019-07-15 15:22:29 -07:00
|
|
|
if (esf != NULL) {
|
2021-01-07 21:16:00 +01:00
|
|
|
LOG_ERR(" a0: " PR_REG " t0: " PR_REG, esf->a0, esf->t0);
|
|
|
|
LOG_ERR(" a1: " PR_REG " t1: " PR_REG, esf->a1, esf->t1);
|
|
|
|
LOG_ERR(" a2: " PR_REG " t2: " PR_REG, esf->a2, esf->t2);
|
2022-06-07 14:18:11 +02:00
|
|
|
#if defined(CONFIG_RISCV_ISA_RV32E)
|
|
|
|
LOG_ERR(" a3: " PR_REG, esf->a3);
|
|
|
|
LOG_ERR(" a4: " PR_REG, esf->a4);
|
|
|
|
LOG_ERR(" a5: " PR_REG, esf->a5);
|
|
|
|
#else
|
2021-01-07 21:16:00 +01:00
|
|
|
LOG_ERR(" a3: " PR_REG " t3: " PR_REG, esf->a3, esf->t3);
|
|
|
|
LOG_ERR(" a4: " PR_REG " t4: " PR_REG, esf->a4, esf->t4);
|
|
|
|
LOG_ERR(" a5: " PR_REG " t5: " PR_REG, esf->a5, esf->t5);
|
|
|
|
LOG_ERR(" a6: " PR_REG " t6: " PR_REG, esf->a6, esf->t6);
|
|
|
|
LOG_ERR(" a7: " PR_REG, esf->a7);
|
2022-06-07 14:18:11 +02:00
|
|
|
#endif /* CONFIG_RISCV_ISA_RV32E */
|
2024-05-16 17:45:47 +08:00
|
|
|
LOG_ERR(" sp: " PR_REG, z_riscv_get_sp_before_exc(esf));
|
2021-06-14 23:47:04 +08:00
|
|
|
LOG_ERR(" ra: " PR_REG, esf->ra);
|
2024-05-21 16:06:07 +08:00
|
|
|
#ifndef CONFIG_SYMTAB
|
2021-01-07 21:16:00 +01:00
|
|
|
LOG_ERR(" mepc: " PR_REG, esf->mepc);
|
2024-05-21 16:06:07 +08:00
|
|
|
#else
|
|
|
|
uint32_t offset = 0;
|
|
|
|
const char *name = symtab_find_symbol_name(esf->mepc, &offset);
|
|
|
|
|
|
|
|
LOG_ERR(" mepc: " PR_REG " [%s+0x%x]", esf->mepc, name, offset);
|
|
|
|
#endif
|
2021-01-07 21:16:00 +01:00
|
|
|
LOG_ERR("mstatus: " PR_REG, esf->mstatus);
|
|
|
|
LOG_ERR("");
|
2019-07-15 15:22:29 -07:00
|
|
|
}
|
2024-03-06 16:25:06 +08:00
|
|
|
|
|
|
|
if (csf != NULL) {
|
|
|
|
#if defined(CONFIG_RISCV_ISA_RV32E)
|
|
|
|
LOG_ERR(" s0: " PR_REG, csf->s0);
|
|
|
|
LOG_ERR(" s1: " PR_REG, csf->s1);
|
|
|
|
#else
|
|
|
|
LOG_ERR(" s0: " PR_REG " s6: " PR_REG, csf->s0, csf->s6);
|
|
|
|
LOG_ERR(" s1: " PR_REG " s7: " PR_REG, csf->s1, csf->s7);
|
|
|
|
LOG_ERR(" s2: " PR_REG " s8: " PR_REG, csf->s2, csf->s8);
|
|
|
|
LOG_ERR(" s3: " PR_REG " s9: " PR_REG, csf->s3, csf->s9);
|
|
|
|
LOG_ERR(" s4: " PR_REG " s10: " PR_REG, csf->s4, csf->s10);
|
|
|
|
LOG_ERR(" s5: " PR_REG " s11: " PR_REG, csf->s5, csf->s11);
|
|
|
|
#endif /* CONFIG_RISCV_ISA_RV32E */
|
|
|
|
LOG_ERR("");
|
|
|
|
}
|
2024-05-13 13:16:25 +08:00
|
|
|
|
2024-05-26 01:55:10 +08:00
|
|
|
if (IS_ENABLED(CONFIG_RISCV_EXCEPTION_STACK_TRACE) && (esf != NULL)) {
|
2024-05-16 17:45:47 +08:00
|
|
|
z_riscv_unwind_stack(esf);
|
|
|
|
}
|
2024-05-13 13:16:25 +08:00
|
|
|
|
2023-12-12 09:57:11 -05:00
|
|
|
#endif /* CONFIG_EXCEPTION_DEBUG */
|
2019-07-11 14:18:28 -07:00
|
|
|
z_fatal_error(reason, esf);
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
CODE_UNREACHABLE;
|
|
|
|
}
|
|
|
|
|
2022-08-25 11:45:38 +02:00
|
|
|
static char *cause_str(unsigned long cause)
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
{
|
|
|
|
switch (cause) {
|
|
|
|
case 0:
|
|
|
|
return "Instruction address misaligned";
|
|
|
|
case 1:
|
|
|
|
return "Instruction Access fault";
|
|
|
|
case 2:
|
|
|
|
return "Illegal instruction";
|
|
|
|
case 3:
|
|
|
|
return "Breakpoint";
|
|
|
|
case 4:
|
|
|
|
return "Load address misaligned";
|
|
|
|
case 5:
|
|
|
|
return "Load access fault";
|
2021-03-14 02:08:49 +08:00
|
|
|
case 6:
|
|
|
|
return "Store/AMO address misaligned";
|
|
|
|
case 7:
|
|
|
|
return "Store/AMO access fault";
|
|
|
|
case 8:
|
|
|
|
return "Environment call from U-mode";
|
|
|
|
case 9:
|
|
|
|
return "Environment call from S-mode";
|
|
|
|
case 11:
|
|
|
|
return "Environment call from M-mode";
|
|
|
|
case 12:
|
|
|
|
return "Instruction page fault";
|
|
|
|
case 13:
|
|
|
|
return "Load page fault";
|
|
|
|
case 15:
|
|
|
|
return "Store/AMO page fault";
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-12 23:57:46 -04:00
|
|
|
static bool bad_stack_pointer(z_arch_esf_t *esf)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_PMP_STACK_GUARD
|
|
|
|
/*
|
|
|
|
* Check if the kernel stack pointer prior this exception (before
|
|
|
|
* storing the exception stack frame) was in the stack guard area.
|
|
|
|
*/
|
|
|
|
uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t);
|
|
|
|
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
if (_current->arch.priv_stack_start != 0 &&
|
|
|
|
sp >= _current->arch.priv_stack_start &&
|
|
|
|
sp < _current->arch.priv_stack_start + Z_RISCV_STACK_GUARD_SIZE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (z_stack_is_user_capable(_current->stack_obj) &&
|
|
|
|
sp >= _current->stack_info.start - K_THREAD_STACK_RESERVED &&
|
|
|
|
sp < _current->stack_info.start - K_THREAD_STACK_RESERVED
|
|
|
|
+ Z_RISCV_STACK_GUARD_SIZE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_USERSPACE */
|
|
|
|
|
|
|
|
if (sp >= _current->stack_info.start - K_KERNEL_STACK_RESERVED &&
|
|
|
|
sp < _current->stack_info.start - K_KERNEL_STACK_RESERVED
|
|
|
|
+ Z_RISCV_STACK_GUARD_SIZE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_PMP_STACK_GUARD */
|
|
|
|
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
if ((esf->mstatus & MSTATUS_MPP) == 0 &&
|
|
|
|
(esf->sp < _current->stack_info.start ||
|
|
|
|
esf->sp > _current->stack_info.start +
|
|
|
|
_current->stack_info.size -
|
|
|
|
_current->stack_info.delta)) {
|
|
|
|
/* user stack pointer moved outside of its allowed stack */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-21 16:00:39 +02:00
|
|
|
void _Fault(z_arch_esf_t *esf)
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
{
|
2020-07-21 16:00:39 +02:00
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
/*
|
|
|
|
* Perform an assessment whether an PMP fault shall be
|
|
|
|
* treated as recoverable.
|
|
|
|
*/
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
|
2022-08-25 11:45:38 +02:00
|
|
|
unsigned long start = (unsigned long)exceptions[i].start;
|
|
|
|
unsigned long end = (unsigned long)exceptions[i].end;
|
2020-07-21 16:00:39 +02:00
|
|
|
|
|
|
|
if (esf->mepc >= start && esf->mepc < end) {
|
2022-08-25 11:45:38 +02:00
|
|
|
esf->mepc = (unsigned long)exceptions[i].fixup;
|
2020-07-21 16:00:39 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_USERSPACE */
|
2022-05-12 23:57:46 -04:00
|
|
|
|
2022-08-25 11:45:38 +02:00
|
|
|
unsigned long mcause;
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
|
|
|
__asm__ volatile("csrr %0, mcause" : "=r" (mcause));
|
2021-04-07 08:06:08 -05:00
|
|
|
|
2022-09-14 22:23:15 +02:00
|
|
|
#ifndef CONFIG_SOC_OPENISA_RV32M1
|
2022-08-25 11:45:38 +02:00
|
|
|
unsigned long mtval;
|
2021-03-14 02:08:49 +08:00
|
|
|
__asm__ volatile("csrr %0, mtval" : "=r" (mtval));
|
2021-04-07 08:06:08 -05:00
|
|
|
#endif
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
2024-01-10 16:11:51 +01:00
|
|
|
mcause &= CONFIG_RISCV_MCAUSE_EXCEPTION_MASK;
|
2021-01-07 21:16:00 +01:00
|
|
|
LOG_ERR("");
|
|
|
|
LOG_ERR(" mcause: %ld, %s", mcause, cause_str(mcause));
|
2022-09-14 22:23:15 +02:00
|
|
|
#ifndef CONFIG_SOC_OPENISA_RV32M1
|
2021-03-14 02:08:49 +08:00
|
|
|
LOG_ERR(" mtval: %lx", mtval);
|
2021-04-07 08:06:08 -05:00
|
|
|
#endif
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
|
2022-05-12 23:57:46 -04:00
|
|
|
unsigned int reason = K_ERR_CPU_EXCEPTION;
|
|
|
|
|
|
|
|
if (bad_stack_pointer(esf)) {
|
|
|
|
reason = K_ERR_STACK_CHK_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
z_riscv_fatal_error(reason, esf);
|
arch: added support for the riscv32 architecture
RISC-V is an open-source instruction set architecture.
Added support for the 32bit version of RISC-V to Zephyr.
1) exceptions/interrupts/faults are handled at the architecture
level via the __irq_wrapper handler. Context saving/restoring
of registers can be handled at both architecture and SOC levels.
If SOC-specific registers need to be saved, SOC level needs to
provide __soc_save_context and __soc_restore_context functions
that shall be accounted by the architecture level, when
corresponding config variable RISCV_SOC_CONTEXT_SAVE is set.
2) As RISC-V architecture does not provide a clear ISA specification
about interrupt handling, each RISC-V SOC handles it in its own
way. Hence, at the architecture level, the __irq_wrapper handler
expects the following functions to be provided by 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)
3) Thread/task scheduling, as well as IRQ offloading are handled via
the RISC-V system call ("ecall"), which is also handled via the
__irq_wrapper handler. The _Swap asm function just calls "ecall"
to generate an exception.
4) As there is no conventional way of handling CPU power save in
RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle
functions just unlock interrupts and return to the caller, without
issuing any CPU power saving instruction. Nonetheless, to allow
SOC-level to implement proper CPU power save, nano_cpu_idle and
nano_cpu_atomic_idle functions are defined as __weak
at the architecture level.
Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389
Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 00:24:30 +01:00
|
|
|
}
|
2020-07-21 16:00:39 +02:00
|
|
|
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
|
|
FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr)
|
|
|
|
{
|
|
|
|
user_fault(K_ERR_KERNEL_OOPS);
|
|
|
|
CODE_UNREACHABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void z_impl_user_fault(unsigned int reason)
|
|
|
|
{
|
|
|
|
z_arch_esf_t *oops_esf = _current->syscall_frame;
|
|
|
|
|
|
|
|
if (((_current->base.user_options & K_USER) != 0) &&
|
|
|
|
reason != K_ERR_STACK_CHK_FAIL) {
|
|
|
|
reason = K_ERR_KERNEL_OOPS;
|
|
|
|
}
|
|
|
|
z_riscv_fatal_error(reason, oops_esf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void z_vrfy_user_fault(unsigned int reason)
|
|
|
|
{
|
|
|
|
z_impl_user_fault(reason);
|
|
|
|
}
|
|
|
|
|
2024-01-24 17:35:04 +08:00
|
|
|
#include <zephyr/syscalls/user_fault_mrsh.c>
|
2020-07-21 16:00:39 +02:00
|
|
|
|
|
|
|
#endif /* CONFIG_USERSPACE */
|