RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
- Add config "ARCH_USE_S_MODE" which controls whether the kernel runs in M-mode or S-mode - Add more MSTATUS and most of the SSTATUS register definitions - Add more MIP flags for interrupt delegation - Add handling of interrupts from S-mode - Add handling of FPU from S-mode - Add new context handling functions that are not dependent on the trap handlers / ecall NOTE: S-mode requires a companion SW (SBI) which is not yet implemented, thus S-mode is not usable as is, yet.
This commit is contained in:
parent
c37474b5bd
commit
c15b6701ce
@ -102,6 +102,7 @@ config ARCH_CHIP_MPFS
|
||||
select ARCH_HAVE_RESET
|
||||
select ARCH_HAVE_SPI_CS_CONTROL
|
||||
select ARCH_HAVE_PWM_MULTICHAN
|
||||
select ARCH_HAVE_S_MODE
|
||||
select PMP_HAS_LIMITED_FEATURES
|
||||
---help---
|
||||
MicroChip Polarfire processor (RISC-V 64bit core with GCVX extensions).
|
||||
@ -189,6 +190,27 @@ config ARCH_MMU_TYPE_SV39
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAVE_S_MODE
|
||||
bool
|
||||
default n
|
||||
|
||||
# Option to run NuttX in supervisor mode. This is obviously not usable in
|
||||
# flat mode, is questionable in protected mode, but is mandatory in kernel
|
||||
# mode.
|
||||
#
|
||||
# Kernel mode requires this as M-mode uses flat addressing and the kernel
|
||||
# memory must be mapped in order to share memory between the kernel and
|
||||
# different user tasks which reside in virtual memory.
|
||||
|
||||
config ARCH_USE_S_MODE
|
||||
bool "Run the NuttX kernel in S-mode"
|
||||
default n
|
||||
depends on ARCH_HAVE_S_MODE && BUILD_KERNEL && ARCH_USE_MMU
|
||||
---help---
|
||||
Most of the RISC-V implementations run in M-mode (flat addressing)
|
||||
and/or U-mode (in case of separate kernel-/userspaces). This provides
|
||||
an option to run the kernel in S-mode, if the target supports it.
|
||||
|
||||
# MPU has certain architecture dependent configurations, which are presented
|
||||
# here. Default is that the full RISC-V PMP specification is supported.
|
||||
|
||||
|
@ -299,13 +299,27 @@
|
||||
|
||||
/* In mstatus register */
|
||||
|
||||
#define MSTATUS_UIE (0x1 << 0) /* User Interrupt Enable */
|
||||
#define MSTATUS_SIE (0x1 << 1) /* Supervisor Interrupt Enable */
|
||||
#define MSTATUS_MIE (0x1 << 3) /* Machine Interrupt Enable */
|
||||
#define MSTATUS_SPIE (0x1 << 5) /* Supervisor Previous Interrupt Enable */
|
||||
#define MSTATUS_MPIE (0x1 << 7) /* Machine Previous Interrupt Enable */
|
||||
#define MSTATUS_SPPU (0x0 << 8) /* Supervisor Previous Privilege (u-mode) */
|
||||
#define MSTATUS_SPPS (0x1 << 8) /* Supervisor Previous Privilege (s-mode) */
|
||||
#define MSTATUS_MPPU (0x0 << 11) /* Machine Previous Privilege (u-mode) */
|
||||
#define MSTATUS_MPPS (0x1 << 11) /* Machine Previous Privilege (s-mode) */
|
||||
#define MSTATUS_MPPM (0x3 << 11) /* Machine Previous Privilege (m-mode) */
|
||||
#define MSTATUS_MPP_MASK (0x3 << 11)
|
||||
#define MSTATUS_FS (0x3 << 13) /* Machine Floating-point Status */
|
||||
#define MSTATUS_FS_INIT (0x1 << 13)
|
||||
#define MSTATUS_FS_CLEAN (0x2 << 13)
|
||||
#define MSTATUS_FS_DIRTY (0x3 << 13)
|
||||
#define MSTATUS_MPRV (0x1 << 17) /* Modify Privilege */
|
||||
#define MSTATUS_SUM (0x1 << 18) /* S mode access to U mode memory */
|
||||
#define MSTATUS_MXR (0x1 << 19) /* Make executable / readable */
|
||||
#define MSTATUS_TVM (0x1 << 20) /* Trap access to satp from S mode */
|
||||
#define MSTATUS_TW (0x1 << 21) /* Trap WFI instruction from S mode */
|
||||
#define MSTATUS_TSR (0x1 << 22) /* Trap supervisor return (sret) */
|
||||
|
||||
/* Mask of preserved bits for mstatus */
|
||||
|
||||
@ -317,19 +331,50 @@
|
||||
|
||||
/* In mie (machine interrupt enable) register */
|
||||
|
||||
#define MIE_SSIE (0x1 << 1) /* Supervisor Software Interrupt Enable */
|
||||
#define MIE_MSIE (0x1 << 3) /* Machine Software Interrupt Enable */
|
||||
#define MIE_STIE (0x1 << 5) /* Supervisor Timer Interrupt Enable */
|
||||
#define MIE_MTIE (0x1 << 7) /* Machine Timer Interrupt Enable */
|
||||
#define MIE_SEIE (0x1 << 9) /* Supervisor External Interrupt Enable */
|
||||
#define MIE_MEIE (0x1 << 11) /* Machine External Interrupt Enable */
|
||||
|
||||
/* In mip (machine interrupt pending) register */
|
||||
|
||||
#define MIP_MTIP (0x1 << 7)
|
||||
#define MIP_SSIP (0x1 << 1)
|
||||
#define MIP_STIP (0x1 << 5)
|
||||
#define MIP_MTIP (0x1 << 7)
|
||||
#define MIP_SEIP (0x1 << 9)
|
||||
|
||||
/* In sstatus register (which is a view of mstatus) */
|
||||
|
||||
#define SSTATUS_SIE MSTATUS_SIE
|
||||
#define SSTATUS_SPIE MSTATUS_SPIE
|
||||
#define SSTATUS_SPPU MSTATUS_SPPU
|
||||
#define SSTATUS_SPPS MSTATUS_SPPS
|
||||
#define SSTATUS_FS MSTATUS_FS
|
||||
#define SSTATUS_FS_INIT MSTATUS_FS_INIT
|
||||
#define SSTATUS_FS_CLEAN MSTATUS_FS_CLEAN
|
||||
#define SSTATUS_FS_DIRTY MSTATUS_FS_DIRTY
|
||||
#define SSTATUS_SUM MSTATUS_SUM
|
||||
#define SSTATUS_MXR MSTATUS_MXR
|
||||
|
||||
/* In sie register (which is a view of mie) */
|
||||
|
||||
#define SIE_SSIE MIE_SSIE
|
||||
#define SIE_STIE MIE_STIE
|
||||
#define SIE_SEIE MIE_SEIE
|
||||
|
||||
/* In sip register (which is a view of mip) */
|
||||
|
||||
#define SIP_SSIP MIP_SSIP
|
||||
#define SIP_STIP MIP_STIP
|
||||
#define SIP_SEIP MIP_SEIP
|
||||
|
||||
/* In pmpcfg (PMP configuration) register */
|
||||
|
||||
#define PMPCFG_R (1 << 0) /* readable ? */
|
||||
#define PMPCFG_W (1 << 1) /* writeable ? */
|
||||
#define PMPCFG_X (1 << 2) /* excutable ? */
|
||||
#define PMPCFG_W (1 << 1) /* writable ? */
|
||||
#define PMPCFG_X (1 << 2) /* executable ? */
|
||||
#define PMPCFG_RWX_MASK (7 << 0) /* access rights mask */
|
||||
#define PMPCFG_A_OFF (0 << 3) /* null region (disabled) */
|
||||
#define PMPCFG_A_TOR (1 << 3) /* top of range */
|
||||
|
@ -35,8 +35,10 @@
|
||||
|
||||
#include <arch/types.h>
|
||||
|
||||
#include <arch/arch.h>
|
||||
#include <arch/csr.h>
|
||||
#include <arch/chip/irq.h>
|
||||
#include <arch/mode.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -47,7 +49,7 @@
|
||||
/* IRQ 0-15 : (exception:interrupt=0) */
|
||||
|
||||
#define RISCV_IRQ_IAMISALIGNED (0) /* Instruction Address Misaligned */
|
||||
#define RISCV_IRQ_IAFAULT (1) /* Instruction Address Fault */
|
||||
#define RISCV_IRQ_IAFAULT (1) /* Instruction Access Fault */
|
||||
#define RISCV_IRQ_IINSTRUCTION (2) /* Illegal Instruction */
|
||||
#define RISCV_IRQ_BPOINT (3) /* Break Point */
|
||||
#define RISCV_IRQ_LAMISALIGNED (4) /* Load Address Misaligned */
|
||||
@ -61,7 +63,7 @@
|
||||
#define RISCV_IRQ_INSTRUCTIONPF (12) /* Instruction page fault */
|
||||
#define RISCV_IRQ_LOADPF (13) /* Load page fault */
|
||||
#define RISCV_IRQ_RESERVED (14) /* Reserved */
|
||||
#define RISCV_IRQ_SROREPF (15) /* Store/AMO page fault */
|
||||
#define RISCV_IRQ_STOREPF (15) /* Store/AMO page fault */
|
||||
|
||||
#define RISCV_MAX_EXCEPTION (15)
|
||||
|
||||
@ -96,6 +98,16 @@
|
||||
# define CONFIG_SYS_NNEST 2
|
||||
#endif
|
||||
|
||||
/* Amount of interrupt stacks (amount of harts) */
|
||||
|
||||
#ifdef CONFIG_IRQ_NSTACKS
|
||||
# define IRQ_NSTACKS CONFIG_IRQ_NSTACKS
|
||||
#elif defined CONFIG_SMP
|
||||
# define IRQ_NSTACKS CONFIG_SMP_NCPUS
|
||||
#else
|
||||
# define IRQ_NSTACKS 1
|
||||
#endif
|
||||
|
||||
/* Processor PC */
|
||||
|
||||
#define REG_EPC_NDX 0
|
||||
@ -469,7 +481,7 @@ struct xcpt_syscall_s
|
||||
{
|
||||
uintptr_t sysreturn; /* The return PC */
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
uintptr_t int_ctx; /* Interrupt context (i.e. mstatus) */
|
||||
uintptr_t int_ctx; /* Interrupt context (i.e. m-/sstatus) */
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
@ -577,9 +589,9 @@ static inline irqstate_t up_irq_save(void)
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"csrrc %0, mstatus, %1\n"
|
||||
"csrrc %0, " __XSTR(CSR_STATUS) ", %1\n"
|
||||
: "=r" (flags)
|
||||
: "r"(MSTATUS_MIE)
|
||||
: "r"(STATUS_IE)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
@ -602,7 +614,7 @@ static inline void up_irq_restore(irqstate_t flags)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"csrw mstatus, %0\n"
|
||||
"csrw " __XSTR(CSR_STATUS) ", %0\n"
|
||||
: /* no output */
|
||||
: "r" (flags)
|
||||
: "memory"
|
||||
|
101
arch/risc-v/include/mode.h
Normal file
101
arch/risc-v/include/mode.h
Normal file
@ -0,0 +1,101 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/include/mode.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_RISCV_INCLUDE_MODE_H
|
||||
#define __ARCH_RISCV_INCLUDE_MODE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
|
||||
/* CSR definitions */
|
||||
|
||||
# define CSR_STATUS sstatus /* Global status register */
|
||||
# define CSR_EPC sepc /* Exception program counter */
|
||||
# define CSR_IE sie /* Interrupt enable register */
|
||||
# define CSR_CAUSE scause /* Interrupt cause register */
|
||||
|
||||
/* In status register */
|
||||
|
||||
# define STATUS_IE SSTATUS_SIE /* Global interrupt enable */
|
||||
# define STATUS_PIE SSTATUS_SPIE /* Previous interrupt enable */
|
||||
# define STATUS_PPP SSTATUS_SPPS /* Previous privilege */
|
||||
# define STATUS_SUM SSTATUS_SUM /* Access to user memory */
|
||||
|
||||
/* Interrupt bits */
|
||||
|
||||
# define IE_EIE SIE_SEIE /* External interrupt enable */
|
||||
# define IE_SIE SIE_SSIE /* Software interrupt enable */
|
||||
# define IE_TIE SIE_STIE /* Timer interrupt enable */
|
||||
|
||||
/* External, timer and software interrupt */
|
||||
|
||||
# define RISCV_IRQ_EXT RISCV_IRQ_SEXT /* PLIC IRQ */
|
||||
# define RISCV_IRQ_TIMER RISCV_IRQ_STIMER /* Timer IRQ */
|
||||
# define RISCV_IRQ_SOFT RISCV_IRQ_SSOFT /* SW IRQ */
|
||||
|
||||
/* Define return from exception */
|
||||
|
||||
# define ERET sret
|
||||
|
||||
#else
|
||||
|
||||
/* CSR definitions */
|
||||
|
||||
# define CSR_STATUS mstatus /* Global status register */
|
||||
# define CSR_EPC mepc /* Exception program counter */
|
||||
# define CSR_IE mie /* Interrupt enable register */
|
||||
# define CSR_CAUSE mcause /* Interrupt cause register */
|
||||
|
||||
/* In status register */
|
||||
|
||||
# define STATUS_IE MSTATUS_MIE /* Global interrupt enable */
|
||||
# define STATUS_PIE MSTATUS_MPIE /* Previous interrupt enable */
|
||||
# define STATUS_PPP MSTATUS_MPPM /* Previous privilege */
|
||||
# define STATUS_SUM 0 /* Not needed in M-mode */
|
||||
|
||||
/* Interrupt bits */
|
||||
|
||||
# define IE_EIE MIE_MEIE /* External interrupt enable */
|
||||
# define IE_SIE MIE_MSIE /* Software interrupt enable */
|
||||
# define IE_TIE MIE_MTIE /* Timer interrupt enable */
|
||||
|
||||
/* External, timer and software interrupt */
|
||||
|
||||
# define RISCV_IRQ_EXT RISCV_IRQ_MEXT /* PLIC IRQ */
|
||||
# define RISCV_IRQ_TIMER RISCV_IRQ_MTIMER /* Timer IRQ */
|
||||
# define RISCV_IRQ_SOFT RISCV_IRQ_MSOFT /* SW IRQ */
|
||||
|
||||
/* Define return from exception */
|
||||
|
||||
# define ERET mret
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_RISCV_INCLUDE_MODE_H */
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <arch/arch.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
@ -122,50 +124,17 @@
|
||||
#define SYS_signal_handler_return (7)
|
||||
#endif /* !CONFIG_BUILD_FLAT */
|
||||
|
||||
/* sys_call macros **********************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Context switching system calls *******************************************/
|
||||
|
||||
/* SYS call 0:
|
||||
*
|
||||
* int riscv_saveusercontext(uintptr_t *saveregs);
|
||||
*
|
||||
* Return:
|
||||
* 0: Normal Return
|
||||
* 1: Context Switch Return
|
||||
*/
|
||||
|
||||
#define riscv_saveusercontext(saveregs) \
|
||||
(int)sys_call1(SYS_save_context, (uintptr_t)(saveregs))
|
||||
|
||||
/* SYS call 1:
|
||||
*
|
||||
* void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
|
||||
*/
|
||||
|
||||
#define riscv_fullcontextrestore(restoreregs) \
|
||||
sys_call1(SYS_restore_context, (uintptr_t)(restoreregs))
|
||||
|
||||
/* SYS call 2:
|
||||
*
|
||||
* void riscv_switchcontext(uintptr_t **saveregs, uintptr_t *restoreregs);
|
||||
*/
|
||||
|
||||
#define riscv_switchcontext(saveregs, restoreregs) \
|
||||
sys_call2(SYS_switch_context, (uintptr_t)(saveregs), (uintptr_t)(restoreregs))
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* SYS call 3:
|
||||
*
|
||||
* void riscv_syscall_return(void);
|
||||
*/
|
||||
|
||||
#define riscv_syscall_return() sys_call0(SYS_syscall_return)
|
||||
|
||||
#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__)
|
||||
# define ASM_SYS_CALL \
|
||||
" addi sp, sp, -16\n" /* Make room */ \
|
||||
REGSTORE " ra, 0(sp)\n" /* Save ra */ \
|
||||
" jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ \
|
||||
REGLOAD " ra, 0(sp)\n" /* Restore ra */ \
|
||||
" addi sp, sp, 16\n" /* Restore sp */
|
||||
#else
|
||||
# define ASM_SYS_CALL \
|
||||
"ecall"
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@ -207,7 +176,7 @@ static inline uintptr_t sys_call0(unsigned int nbr)
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0)
|
||||
: "memory"
|
||||
);
|
||||
@ -232,7 +201,7 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1)
|
||||
: "memory"
|
||||
);
|
||||
@ -259,7 +228,7 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1), "r"(r2)
|
||||
: "memory"
|
||||
);
|
||||
@ -287,7 +256,7 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3)
|
||||
: "memory"
|
||||
);
|
||||
@ -317,7 +286,7 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
|
||||
: "memory"
|
||||
);
|
||||
@ -348,7 +317,7 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
|
||||
: "memory"
|
||||
);
|
||||
@ -381,7 +350,7 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
ASM_SYS_CALL
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
|
||||
: "memory"
|
||||
);
|
||||
|
@ -24,6 +24,12 @@ ifeq ($(CONFIG_OPENSBI),y)
|
||||
include opensbi/Make.defs
|
||||
endif
|
||||
|
||||
# Kernel runs in supervisor mode or machine mode ?
|
||||
|
||||
ifeq ($(CONFIG_ARCH_USE_S_MODE),y)
|
||||
include common/supervisor/Make.defs
|
||||
endif
|
||||
|
||||
ARCH_SRCDIR = $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src
|
||||
|
||||
INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip}
|
||||
|
@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -34,7 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_mdelay.c riscv_idle.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c
|
||||
CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -48,7 +48,16 @@
|
||||
|
||||
uintptr_t riscv_mhartid(void)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
/* Kernel is in S-mode */
|
||||
|
||||
#error "Missing functionality..."
|
||||
|
||||
#else
|
||||
/* Kernel is in M-mode */
|
||||
|
||||
return READ_CSR(mhartid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -26,6 +26,9 @@
|
||||
|
||||
#include <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/mode.h>
|
||||
|
||||
#include "riscv_exception_macros.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -50,16 +53,13 @@
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IRQ_NSTACKS
|
||||
# define IRQ_NSTACKS CONFIG_IRQ_NSTACKS
|
||||
#elif defined CONFIG_SMP
|
||||
# define IRQ_NSTACKS CONFIG_SMP_NCPUS
|
||||
#else
|
||||
# define IRQ_NSTACKS 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: exception_common
|
||||
*
|
||||
* Description:
|
||||
* Handles interrupts. If kernel is in S-mode, handles delegated interrupts
|
||||
* in S-mode interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.section .text
|
||||
@ -69,48 +69,16 @@
|
||||
exception_common:
|
||||
|
||||
addi sp, sp, -XCPTCONTEXT_SIZE
|
||||
save_ctx sp
|
||||
|
||||
REGSTORE x1, REG_X1(sp) /* ra */
|
||||
#ifdef RISCV_SAVE_GP
|
||||
REGSTORE x3, REG_X3(sp) /* gp */
|
||||
#endif
|
||||
REGSTORE x4, REG_X4(sp) /* tp */
|
||||
REGSTORE x5, REG_X5(sp) /* t0 */
|
||||
REGSTORE x6, REG_X6(sp) /* t1 */
|
||||
REGSTORE x7, REG_X7(sp) /* t2 */
|
||||
REGSTORE x8, REG_X8(sp) /* s0 */
|
||||
REGSTORE x9, REG_X9(sp) /* s1 */
|
||||
REGSTORE x10, REG_X10(sp) /* a0 */
|
||||
REGSTORE x11, REG_X11(sp) /* a1 */
|
||||
REGSTORE x12, REG_X12(sp) /* a2 */
|
||||
REGSTORE x13, REG_X13(sp) /* a3 */
|
||||
REGSTORE x14, REG_X14(sp) /* a4 */
|
||||
REGSTORE x15, REG_X15(sp) /* a5 */
|
||||
REGSTORE x16, REG_X16(sp) /* a6 */
|
||||
REGSTORE x17, REG_X17(sp) /* a7 */
|
||||
REGSTORE x18, REG_X18(sp) /* s2 */
|
||||
REGSTORE x19, REG_X19(sp) /* s3 */
|
||||
REGSTORE x20, REG_X20(sp) /* s4 */
|
||||
REGSTORE x21, REG_X21(sp) /* s5 */
|
||||
REGSTORE x22, REG_X22(sp) /* s6 */
|
||||
REGSTORE x23, REG_X23(sp) /* s7 */
|
||||
REGSTORE x24, REG_X24(sp) /* s8 */
|
||||
REGSTORE x25, REG_X25(sp) /* s9 */
|
||||
REGSTORE x26, REG_X26(sp) /* s10 */
|
||||
REGSTORE x27, REG_X27(sp) /* s11 */
|
||||
REGSTORE x28, REG_X28(sp) /* t3 */
|
||||
REGSTORE x29, REG_X29(sp) /* t4 */
|
||||
REGSTORE x30, REG_X30(sp) /* t5 */
|
||||
REGSTORE x31, REG_X31(sp) /* t6 */
|
||||
|
||||
csrr s0, mstatus
|
||||
REGSTORE s0, REG_INT_CTX(sp) /* mstatus */
|
||||
csrr s0, CSR_STATUS
|
||||
REGSTORE s0, REG_INT_CTX(sp) /* status */
|
||||
|
||||
addi s0, sp, XCPTCONTEXT_SIZE
|
||||
REGSTORE s0, REG_X2(sp) /* original SP */
|
||||
REGSTORE s0, REG_X2(sp) /* original SP */
|
||||
|
||||
csrr s0, mepc
|
||||
REGSTORE s0, REG_EPC(sp) /* exception PC */
|
||||
csrr s0, CSR_EPC
|
||||
REGSTORE s0, REG_EPC(sp) /* exception PC */
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
mv a0, sp
|
||||
@ -119,24 +87,29 @@ exception_common:
|
||||
|
||||
/* Setup arg0(exception cause), arg1(context) */
|
||||
|
||||
csrr a0, mcause /* exception cause */
|
||||
csrr a0, CSR_CAUSE /* exception cause */
|
||||
mv a1, sp /* context = sp */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
/* Load mhartid (cpuid) */
|
||||
|
||||
csrr s0, mhartid
|
||||
/* Offset to hartid */
|
||||
|
||||
mv s0, a0 /* save cause */
|
||||
jal x1, riscv_mhartid /* get hartid */
|
||||
|
||||
/* Switch to interrupt stack */
|
||||
|
||||
#if IRQ_NSTACKS > 1
|
||||
li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
mul t0, s0, t0
|
||||
la s0, g_intstacktop
|
||||
sub sp, s0, t0
|
||||
mul t0, a0, t0
|
||||
la a0, g_intstacktop
|
||||
sub sp, a0, t0
|
||||
#else
|
||||
la sp, g_intstacktop
|
||||
#endif
|
||||
|
||||
mv a0, s0 /* restore cause */
|
||||
|
||||
/* Call interrupt handler in C */
|
||||
|
||||
jal x1, riscv_dispatch_irq
|
||||
@ -159,62 +132,27 @@ exception_common:
|
||||
jal x1, riscv_restorefpu /* restore FPU context */
|
||||
#endif
|
||||
|
||||
/* If context switch is needed, return a new sp */
|
||||
/* If context switch is needed, return a new sp */
|
||||
|
||||
mv sp, a0
|
||||
REGLOAD s0, REG_EPC(sp) /* restore mepc */
|
||||
csrw mepc, s0
|
||||
|
||||
REGLOAD s0, REG_INT_CTX(sp) /* restore mstatus */
|
||||
csrw mstatus, s0
|
||||
REGLOAD s0, REG_EPC(sp) /* restore sepc */
|
||||
csrw CSR_EPC, s0
|
||||
|
||||
#ifdef RISCV_SAVE_GP
|
||||
REGLOAD x3, REG_X3(sp) /* gp */
|
||||
#endif
|
||||
REGLOAD x4, REG_X4(sp) /* tp */
|
||||
REGLOAD x5, REG_X5(sp) /* t0 */
|
||||
REGLOAD x6, REG_X6(sp) /* t1 */
|
||||
REGLOAD x7, REG_X7(sp) /* t2 */
|
||||
REGLOAD x8, REG_X8(sp) /* s0 */
|
||||
REGLOAD x9, REG_X9(sp) /* s1 */
|
||||
REGLOAD x10, REG_X10(sp) /* a0 */
|
||||
REGLOAD x11, REG_X11(sp) /* a1 */
|
||||
REGLOAD x12, REG_X12(sp) /* a2 */
|
||||
REGLOAD x13, REG_X13(sp) /* a3 */
|
||||
REGLOAD x14, REG_X14(sp) /* a4 */
|
||||
REGLOAD x15, REG_X15(sp) /* a5 */
|
||||
REGLOAD x16, REG_X16(sp) /* a6 */
|
||||
REGLOAD x17, REG_X17(sp) /* a7 */
|
||||
REGLOAD x18, REG_X18(sp) /* s2 */
|
||||
REGLOAD x19, REG_X19(sp) /* s3 */
|
||||
REGLOAD x20, REG_X20(sp) /* s4 */
|
||||
REGLOAD x21, REG_X21(sp) /* s5 */
|
||||
REGLOAD x22, REG_X22(sp) /* s6 */
|
||||
REGLOAD x23, REG_X23(sp) /* s7 */
|
||||
REGLOAD x24, REG_X24(sp) /* s8 */
|
||||
REGLOAD x25, REG_X25(sp) /* s9 */
|
||||
REGLOAD x26, REG_X26(sp) /* s10 */
|
||||
REGLOAD x27, REG_X27(sp) /* s11 */
|
||||
REGLOAD x28, REG_X28(sp) /* t3 */
|
||||
REGLOAD x29, REG_X29(sp) /* t4 */
|
||||
REGLOAD x30, REG_X30(sp) /* t5 */
|
||||
REGLOAD x31, REG_X31(sp) /* t6 */
|
||||
REGLOAD s0, REG_INT_CTX(sp) /* restore sstatus */
|
||||
csrw CSR_STATUS, s0
|
||||
|
||||
REGLOAD x1, REG_X1(sp) /* ra */
|
||||
load_ctx sp
|
||||
|
||||
REGLOAD sp, REG_X2(sp) /* restore original sp */
|
||||
REGLOAD sp, REG_SP(sp) /* restore original sp */
|
||||
|
||||
/* Return from Machine Interrupt */
|
||||
/* Return from exception */
|
||||
|
||||
mret
|
||||
ERET
|
||||
|
||||
/************************************************************************************
|
||||
/*****************************************************************************
|
||||
* Name: g_intstackalloc and g_intstacktop
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: g_intstackalloc and g_intstacktop
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
.bss
|
||||
|
130
arch/risc-v/src/common/riscv_exception_macros.S
Normal file
130
arch/risc-v/src/common/riscv_exception_macros.S
Normal file
@ -0,0 +1,130 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/common/supervisor/riscv_exception_macros.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.file "riscv_exception_macros.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: save_ctx
|
||||
*
|
||||
* Parameter:
|
||||
* in - Pointer to where the save is performed (e.g. sp)
|
||||
*
|
||||
* Description:
|
||||
* Save the common context registers (i.e. work / temp / etc).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.macro save_ctx in
|
||||
|
||||
REGSTORE x1, REG_X1(\in) /* ra */
|
||||
#ifdef RISCV_SAVE_GP
|
||||
REGSTORE x3, REG_X3(\in) /* gp */
|
||||
#endif
|
||||
REGSTORE x4, REG_X4(\in) /* tp */
|
||||
REGSTORE x5, REG_X5(\in) /* t0 */
|
||||
REGSTORE x6, REG_X6(\in) /* t1 */
|
||||
REGSTORE x7, REG_X7(\in) /* t2 */
|
||||
REGSTORE x8, REG_X8(\in) /* s0 */
|
||||
REGSTORE x9, REG_X9(\in) /* s1 */
|
||||
REGSTORE x10, REG_X10(\in) /* a0 */
|
||||
REGSTORE x11, REG_X11(\in) /* a1 */
|
||||
REGSTORE x12, REG_X12(\in) /* a2 */
|
||||
REGSTORE x13, REG_X13(\in) /* a3 */
|
||||
REGSTORE x14, REG_X14(\in) /* a4 */
|
||||
REGSTORE x15, REG_X15(\in) /* a5 */
|
||||
REGSTORE x16, REG_X16(\in) /* a6 */
|
||||
REGSTORE x17, REG_X17(\in) /* a7 */
|
||||
REGSTORE x18, REG_X18(\in) /* s2 */
|
||||
REGSTORE x19, REG_X19(\in) /* s3 */
|
||||
REGSTORE x20, REG_X20(\in) /* s4 */
|
||||
REGSTORE x21, REG_X21(\in) /* s5 */
|
||||
REGSTORE x22, REG_X22(\in) /* s6 */
|
||||
REGSTORE x23, REG_X23(\in) /* s7 */
|
||||
REGSTORE x24, REG_X24(\in) /* s8 */
|
||||
REGSTORE x25, REG_X25(\in) /* s9 */
|
||||
REGSTORE x26, REG_X26(\in) /* s10 */
|
||||
REGSTORE x27, REG_X27(\in) /* s11 */
|
||||
REGSTORE x28, REG_X28(\in) /* t3 */
|
||||
REGSTORE x29, REG_X29(\in) /* t4 */
|
||||
REGSTORE x30, REG_X30(\in) /* t5 */
|
||||
REGSTORE x31, REG_X31(\in) /* t6 */
|
||||
|
||||
.endm
|
||||
|
||||
/****************************************************************************
|
||||
* Name: load_ctx
|
||||
*
|
||||
* Parameter:
|
||||
* out - Pointer to where the load is performed (e.g. sp)
|
||||
*
|
||||
* Description:
|
||||
* Load the common context registers (i.e. work / temp / etc).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.macro load_ctx out
|
||||
|
||||
REGLOAD x1, REG_X1(\out) /* ra */
|
||||
#ifdef RISCV_SAVE_GP
|
||||
REGLOAD x3, REG_X3(\out) /* gp */
|
||||
#endif
|
||||
REGLOAD x4, REG_X4(\out) /* tp */
|
||||
REGLOAD x5, REG_X5(\out) /* t0 */
|
||||
REGLOAD x6, REG_X6(\out) /* t1 */
|
||||
REGLOAD x7, REG_X7(\out) /* t2 */
|
||||
REGLOAD x8, REG_X8(\out) /* s0 */
|
||||
REGLOAD x9, REG_X9(\out) /* s1 */
|
||||
REGLOAD x10, REG_X10(\out) /* a0 */
|
||||
REGLOAD x11, REG_X11(\out) /* a1 */
|
||||
REGLOAD x12, REG_X12(\out) /* a2 */
|
||||
REGLOAD x13, REG_X13(\out) /* a3 */
|
||||
REGLOAD x14, REG_X14(\out) /* a4 */
|
||||
REGLOAD x15, REG_X15(\out) /* a5 */
|
||||
REGLOAD x16, REG_X16(\out) /* a6 */
|
||||
REGLOAD x17, REG_X17(\out) /* a7 */
|
||||
REGLOAD x18, REG_X18(\out) /* s2 */
|
||||
REGLOAD x19, REG_X19(\out) /* s3 */
|
||||
REGLOAD x20, REG_X20(\out) /* s4 */
|
||||
REGLOAD x21, REG_X21(\out) /* s5 */
|
||||
REGLOAD x22, REG_X22(\out) /* s6 */
|
||||
REGLOAD x23, REG_X23(\out) /* s7 */
|
||||
REGLOAD x24, REG_X24(\out) /* s8 */
|
||||
REGLOAD x25, REG_X25(\out) /* s9 */
|
||||
REGLOAD x26, REG_X26(\out) /* s10 */
|
||||
REGLOAD x27, REG_X27(\out) /* s11 */
|
||||
REGLOAD x28, REG_X28(\out) /* t3 */
|
||||
REGLOAD x29, REG_X29(\out) /* t4 */
|
||||
REGLOAD x30, REG_X30(\out) /* t5 */
|
||||
REGLOAD x31, REG_X31(\out) /* t6 */
|
||||
|
||||
.endm
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/mode.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
|
||||
@ -74,7 +75,7 @@
|
||||
|
||||
riscv_fpuconfig:
|
||||
li a0, FS_INITIAL
|
||||
csrs mstatus, a0
|
||||
csrs CSR_STATUS, a0
|
||||
csrwi fcsr, 0
|
||||
ret
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include <arch/mode.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -48,23 +50,23 @@
|
||||
|
||||
uintptr_t riscv_get_newintctx(void)
|
||||
{
|
||||
/* Set machine previous privilege mode to machine mode. Reegardless of
|
||||
/* Set machine previous privilege mode to privileged mode. Regardless of
|
||||
* how NuttX is configured and of what kind of thread is being started.
|
||||
* That is because all threads, even user-mode threads will start in
|
||||
* kernel trampoline at nxtask_start() or pthread_start().
|
||||
* The thread's privileges will be dropped before transitioning to
|
||||
* user code. Also set machine previous interrupt enable.
|
||||
* user code. Also set machine / supervisor previous interrupt enable.
|
||||
*
|
||||
* Mask the bits which should be preserved (from ISA spec)
|
||||
*/
|
||||
|
||||
uintptr_t mstatus = READ_CSR(mstatus);
|
||||
uintptr_t status = READ_CSR(CSR_STATUS);
|
||||
|
||||
mstatus &= MSTATUS_WPRI;
|
||||
status &= MSTATUS_WPRI;
|
||||
|
||||
return (mstatus | MSTATUS_MPPM | MSTATUS_MPIE
|
||||
return (status | STATUS_PPP | STATUS_SUM | STATUS_PIE
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
| MSTATUS_FS_INIT
|
||||
| MSTATUS_FS_INIT
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
# include <nuttx/arch.h>
|
||||
# include <sys/types.h>
|
||||
# include <stdint.h>
|
||||
# include <syscall.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -315,6 +316,53 @@ int riscv_pause_handler(int irq, void *c, void *arg);
|
||||
|
||||
uintptr_t riscv_mhartid(void);
|
||||
|
||||
/* If kernel runs in Supervisor mode, a system call trampoline is needed */
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
void riscv_syscall_dispatch(void) noreturn_function;
|
||||
void *riscv_perform_syscall(uintptr_t *regs);
|
||||
#endif
|
||||
|
||||
/* Context switching via system calls ***************************************/
|
||||
|
||||
/* SYS call 0:
|
||||
*
|
||||
* int riscv_saveusercontext(uintptr_t *saveregs);
|
||||
*
|
||||
* Return:
|
||||
* 0: Normal Return
|
||||
* 1: Context Switch Return
|
||||
*/
|
||||
|
||||
#define riscv_saveusercontext(saveregs) \
|
||||
sys_call1(SYS_save_context, (uintptr_t)saveregs)
|
||||
|
||||
/* SYS call 1:
|
||||
*
|
||||
* void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
|
||||
*/
|
||||
|
||||
#define riscv_fullcontextrestore(restoreregs) \
|
||||
sys_call1(SYS_restore_context, (uintptr_t)restoreregs)
|
||||
|
||||
/* SYS call 2:
|
||||
*
|
||||
* void riscv_switchcontext(uintptr_t *saveregs, uintptr_t *restoreregs);
|
||||
*/
|
||||
|
||||
#define riscv_switchcontext(saveregs, restoreregs) \
|
||||
sys_call2(SYS_switch_context, (uintptr_t)saveregs, (uintptr_t)restoreregs)
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* SYS call 3:
|
||||
*
|
||||
* void riscv_syscall_return(void);
|
||||
*/
|
||||
|
||||
#define riscv_syscall_return() sys_call0(SYS_syscall_return)
|
||||
|
||||
#endif /* CONFIG_BUILD_KERNEL */
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -146,12 +146,13 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
int_ctx = CURRENT_REGS[REG_INT_CTX];
|
||||
int_ctx &= ~MSTATUS_MPIE;
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
|
||||
int_ctx = CURRENT_REGS[REG_INT_CTX];
|
||||
int_ctx &= ~STATUS_PIE;
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
int_ctx |= MSTATUS_MPPM;
|
||||
int_ctx |= STATUS_PPP;
|
||||
#endif
|
||||
|
||||
CURRENT_REGS[REG_INT_CTX] = int_ctx;
|
||||
@ -201,7 +202,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
|
||||
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
int_ctx = tcb->xcp.regs[REG_INT_CTX];
|
||||
int_ctx &= ~MSTATUS_MPIE;
|
||||
int_ctx &= ~STATUS_PIE;
|
||||
|
||||
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
|
||||
|
||||
@ -312,9 +313,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
|
||||
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
int_ctx = tcb->xcp.regs[REG_INT_CTX];
|
||||
int_ctx &= ~MSTATUS_MPIE;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
int_ctx |= MSTATUS_MPPM;
|
||||
int_ctx &= ~STATUS_PIE;
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
int_ctx |= STATUS_PPP;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
|
||||
}
|
||||
@ -353,9 +354,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
CURRENT_REGS[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
|
||||
int_ctx = CURRENT_REGS[REG_INT_CTX];
|
||||
int_ctx &= ~MSTATUS_MPIE;
|
||||
int_ctx &= ~STATUS_PIE;
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
int_ctx |= MSTATUS_MPPM;
|
||||
int_ctx |= STATUS_PPP;
|
||||
#endif
|
||||
|
||||
CURRENT_REGS[REG_INT_CTX] = int_ctx;
|
||||
@ -429,7 +430,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver;
|
||||
|
||||
int_ctx = tcb->xcp.regs[REG_INT_CTX];
|
||||
int_ctx &= ~MSTATUS_MPIE;
|
||||
int_ctx &= ~STATUS_PIE;
|
||||
|
||||
tcb->xcp.regs[REG_INT_CTX] = int_ctx;
|
||||
}
|
||||
|
@ -122,13 +122,17 @@ static void dispatch_syscall(void)
|
||||
"slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */
|
||||
#endif
|
||||
"add t0, t0, a0\n" /* t0=The address in the table */
|
||||
REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
|
||||
REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
|
||||
"jalr ra, t0\n" /* Call the stub (modifies ra) */
|
||||
REGLOAD " ra, 0(sp)\n" /* Restore ra */
|
||||
"addi sp, sp, " STACK_FRAME_SIZE "\n" /* Destroy the stack frame */
|
||||
"mv a2, a0\n" /* a2=Save return value in a0 */
|
||||
"li a0, 3\n" /* a0=SYS_syscall_return (3) */
|
||||
"ecall" /* Return from the syscall */
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
" j riscv_syscall_dispatch" /* Return from the syscall */
|
||||
#else
|
||||
" ecall" /* Return from the syscall */
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
@ -332,7 +336,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
regs[REG_A0] = regs[REG_A2]; /* argc */
|
||||
regs[REG_A1] = regs[REG_A3]; /* argv */
|
||||
#endif
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -364,7 +368,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
|
||||
regs[REG_A0] = regs[REG_A2]; /* pthread entry */
|
||||
regs[REG_A1] = regs[REG_A3]; /* arg */
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -403,7 +407,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
regs[REG_EPC] =
|
||||
(uintptr_t)ARCH_DATA_RESERVE->ar_sigtramp & ~1;
|
||||
#endif
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
regs[REG_INT_CTX] &= ~STATUS_PPP; /* User mode */
|
||||
|
||||
/* Change the parameter ordering to match the expectation of struct
|
||||
* userpace_s signal_handler.
|
||||
@ -453,7 +457,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
|
||||
DEBUGASSERT(rtcb->xcp.sigreturn != 0);
|
||||
regs[REG_EPC] = rtcb->xcp.sigreturn & ~1;
|
||||
regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
|
||||
regs[REG_INT_CTX] |= STATUS_PPP; /* Privileged mode */
|
||||
|
||||
rtcb->xcp.sigreturn = 0;
|
||||
|
||||
@ -501,7 +505,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
|
||||
rtcb->xcp.syscall[index].sysreturn = regs[REG_EPC];
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
rtcb->xcp.syscall[index].int_ctx = regs[REG_INT_CTX];
|
||||
rtcb->xcp.syscall[index].int_ctx = regs[REG_INT_CTX];
|
||||
#endif
|
||||
|
||||
rtcb->xcp.nsyscalls = index + 1;
|
||||
@ -509,7 +513,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
regs[REG_EPC] = (uintptr_t)dispatch_syscall & ~1;
|
||||
|
||||
#ifndef CONFIG_BUILD_FLAT
|
||||
regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
|
||||
regs[REG_INT_CTX] |= STATUS_PPP; /* Privileged mode */
|
||||
#endif
|
||||
|
||||
/* Offset A0 to account for the reserved values */
|
||||
|
@ -23,11 +23,16 @@
|
||||
****************************************************************************/
|
||||
|
||||
.section .text
|
||||
.balign 4
|
||||
.balign 8
|
||||
.global __trap_vec
|
||||
|
||||
/****************************************************************************
|
||||
* Name: exception_common
|
||||
* Name: __trap_vec
|
||||
*
|
||||
* Description:
|
||||
* All M-mode exceptions and interrupts will be handled from here. If
|
||||
* kernel is in S-mode delegated exceptions and interrupts are handled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
__trap_vec:
|
||||
|
28
arch/risc-v/src/common/supervisor/Make.defs
Normal file
28
arch/risc-v/src/common/supervisor/Make.defs
Normal file
@ -0,0 +1,28 @@
|
||||
############################################################################
|
||||
# arch/risc-v/src/common/supervisor/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# If the NuttX kernel runs in S-mode
|
||||
|
||||
CMN_ASRCS += riscv_syscall_dispatch.S
|
||||
CMN_CSRCS += riscv_sbi.c riscv_perform_syscall.c
|
||||
CMN_CSRCS += riscv_percpu.c
|
||||
|
||||
INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)common$(DELIM)supervisor}
|
||||
VPATH += common$(DELIM)supervisor
|
65
arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
Normal file
65
arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
Normal file
@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
#include "group/group.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void *riscv_perform_syscall(uintptr_t *regs)
|
||||
{
|
||||
/* Set up the interrupt register set needed by swint() */
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
/* Run the system call handler (swint) */
|
||||
|
||||
riscv_swint(0, regs, NULL);
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
* MMU flushed) and set up the address environment for the new
|
||||
* thread at the head of the ready-to-run list.
|
||||
*/
|
||||
|
||||
group_addrenv(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set new context */
|
||||
|
||||
regs = (uintptr_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = NULL;
|
||||
|
||||
return regs;
|
||||
}
|
148
arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
Normal file
148
arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
Normal file
@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.file "riscv_syscall_dispatch.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/mode.h>
|
||||
|
||||
#include "riscv_exception_macros.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.globl riscv_syscall_dispatch
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_syscall_dispatch
|
||||
*
|
||||
* Description:
|
||||
* Dispatch syscall from kernel
|
||||
*
|
||||
* C Function Prototype:
|
||||
* void riscv_syscall_dispatch(void);
|
||||
*
|
||||
* Input Parameters:
|
||||
* Assumes the context to return is already set up
|
||||
*
|
||||
* Returned Value:
|
||||
* Return value of system call is returned into contex
|
||||
*
|
||||
* Assumptions:
|
||||
* Task is running in privileged mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.type riscv_syscall_dispatch, function
|
||||
|
||||
riscv_syscall_dispatch:
|
||||
|
||||
addi sp, sp, -XCPTCONTEXT_SIZE /* make room */
|
||||
save_ctx sp /* save current context */
|
||||
|
||||
/* Mask interrupts and store the status register to context */
|
||||
|
||||
li s1, STATUS_IE /* move IE -> PIE */
|
||||
csrrc s0, CSR_STATUS, s1
|
||||
and s1, s0, s1 /* if (STATUS & IE) */
|
||||
beqz s1, 1f
|
||||
li s1, ~STATUS_IE /* clear IE */
|
||||
and s0, s0, s1
|
||||
li s1, STATUS_PIE /* set PIE */
|
||||
or s0, s0, s1
|
||||
|
||||
1:
|
||||
/* Set previous privilege, we are in privileged mode now */
|
||||
|
||||
li s1, STATUS_PPP /* set previous privilege */
|
||||
or s0, s0, s1
|
||||
REGSTORE s0, REG_INT_CTX(sp) /* store status to context */
|
||||
|
||||
REGSTORE x1, REG_EPC(sp) /* save ra to epc */
|
||||
|
||||
addi s0, sp, XCPTCONTEXT_SIZE
|
||||
REGSTORE s0, REG_SP(sp) /* original SP */
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
mv a0, sp
|
||||
jal x1, riscv_savefpu /* FP registers */
|
||||
#endif
|
||||
|
||||
mv a0, sp /* a0 = context */
|
||||
|
||||
/* Switch to interrupt stack */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
#if IRQ_NSTACKS > 1
|
||||
jal x1, riscv_mhartid /* get hartid */
|
||||
li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
mul t0, a0, t0
|
||||
la a0, g_intstacktop
|
||||
sub sp, a0, t0
|
||||
#else
|
||||
la sp, g_intstacktop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Run the handler */
|
||||
|
||||
jal x1, riscv_perform_syscall
|
||||
|
||||
/* Restore (potentially new) context */
|
||||
|
||||
mv sp, a0 /* use sp, as a0 gets wiped */
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
jal x1, riscv_restorefpu /* FP registers */
|
||||
#endif
|
||||
|
||||
REGLOAD s0, REG_EPC(sp) /* restore epc */
|
||||
csrw CSR_EPC, s0
|
||||
|
||||
/* Restore status register, but don't enable interrupts yet */
|
||||
|
||||
REGLOAD s0, REG_INT_CTX(sp) /* restore status */
|
||||
li s1, STATUS_IE /* move IE -> PIE */
|
||||
and s1, s0, s1 /* if (STATUS & IE) */
|
||||
beqz s1, 1f
|
||||
li s1, ~STATUS_IE /* clear IE */
|
||||
and s0, s0, s1
|
||||
li s1, STATUS_PIE /* set PIE */
|
||||
or s0, s0, s1
|
||||
|
||||
1:
|
||||
csrw CSR_STATUS, s0
|
||||
|
||||
load_ctx sp
|
||||
|
||||
REGLOAD sp, REG_SP(sp) /* restore original sp */
|
||||
|
||||
/* return from exception, which updates the status register */
|
||||
|
||||
ERET
|
@ -37,6 +37,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -35,6 +35,7 @@ CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_mdelay.c riscv_idle.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_tcbinfo.c riscv_cpuidlestack.c riscv_getnewintctx.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SMP), y)
|
||||
CMN_CSRCS += riscv_cpuindex.c riscv_cpupause.c riscv_cpustart.c
|
||||
|
@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_udelay.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -58,7 +58,7 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
|
||||
if (vector < RISCV_IRQ_ECALLU ||
|
||||
vector == RISCV_IRQ_INSTRUCTIONPF ||
|
||||
vector == RISCV_IRQ_LOADPF ||
|
||||
vector == RISCV_IRQ_SROREPF ||
|
||||
vector == RISCV_IRQ_STOREPF ||
|
||||
vector == RISCV_IRQ_RESERVED)
|
||||
{
|
||||
riscv_fault(irq, regs);
|
||||
|
@ -35,6 +35,7 @@ CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_cpuidlestack.c
|
||||
CMN_CSRCS += riscv_fault.c riscv_getnewintctx.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SMP), y)
|
||||
CMN_CSRCS += riscv_cpuindex.c riscv_cpupause.c riscv_cpustart.c
|
||||
|
@ -34,6 +34,7 @@ CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c
|
||||
CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
||||
CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_getnewintctx.c
|
||||
CMN_CSRCS += riscv_cpuindex.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_BACKTRACE),y)
|
||||
CMN_CSRCS += riscv_backtrace.c
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user