diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 6bc640e706f..97c66bd56da 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -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. diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h index 25b63169439..ea17adb3e2c 100644 --- a/arch/risc-v/include/csr.h +++ b/arch/risc-v/include/csr.h @@ -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 */ diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index dd972223e0e..78799adae6a 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -35,8 +35,10 @@ #include +#include #include #include +#include /**************************************************************************** * 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" diff --git a/arch/risc-v/include/mode.h b/arch/risc-v/include/mode.h new file mode 100644 index 00000000000..144fd73d03b --- /dev/null +++ b/arch/risc-v/include/mode.h @@ -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 +#include + +/**************************************************************************** + * 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 */ diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h index a357d1d84d1..0a212a6606d 100644 --- a/arch/risc-v/include/syscall.h +++ b/arch/risc-v/include/syscall.h @@ -31,6 +31,8 @@ #include +#include + #ifndef __ASSEMBLY__ # include #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" ); diff --git a/arch/risc-v/src/Makefile b/arch/risc-v/src/Makefile index f598c6fd2e3..ad45227d2d3 100644 --- a/arch/risc-v/src/Makefile +++ b/arch/risc-v/src/Makefile @@ -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} diff --git a/arch/risc-v/src/bl602/Make.defs b/arch/risc-v/src/bl602/Make.defs index b33f44c6efd..5f4c8548b75 100644 --- a/arch/risc-v/src/bl602/Make.defs +++ b/arch/risc-v/src/bl602/Make.defs @@ -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 diff --git a/arch/risc-v/src/c906/Make.defs b/arch/risc-v/src/c906/Make.defs index 889bdcb8133..6406e8c822c 100644 --- a/arch/risc-v/src/c906/Make.defs +++ b/arch/risc-v/src/c906/Make.defs @@ -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 diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c index 45e252f0ced..fe490655f59 100644 --- a/arch/risc-v/src/common/riscv_cpuindex.c +++ b/arch/risc-v/src/common/riscv_cpuindex.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 } /**************************************************************************** diff --git a/arch/risc-v/src/common/riscv_exception_common.S b/arch/risc-v/src/common/riscv_exception_common.S index 3daa5ce0892..f0603f951e7 100644 --- a/arch/risc-v/src/common/riscv_exception_common.S +++ b/arch/risc-v/src/common/riscv_exception_common.S @@ -26,6 +26,9 @@ #include #include +#include + +#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 diff --git a/arch/risc-v/src/common/riscv_exception_macros.S b/arch/risc-v/src/common/riscv_exception_macros.S new file mode 100644 index 00000000000..d2f3291503e --- /dev/null +++ b/arch/risc-v/src/common/riscv_exception_macros.S @@ -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 + +#include +#include + +/**************************************************************************** + * 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 diff --git a/arch/risc-v/src/common/riscv_fpu.S b/arch/risc-v/src/common/riscv_fpu.S index 2d3de5b18c0..3c29465e9b5 100644 --- a/arch/risc-v/src/common/riscv_fpu.S +++ b/arch/risc-v/src/common/riscv_fpu.S @@ -26,6 +26,7 @@ #include #include +#include #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 diff --git a/arch/risc-v/src/common/riscv_getnewintctx.c b/arch/risc-v/src/common/riscv_getnewintctx.c index 6b7619a18b0..f1fa4cf3ded 100644 --- a/arch/risc-v/src/common/riscv_getnewintctx.c +++ b/arch/risc-v/src/common/riscv_getnewintctx.c @@ -32,6 +32,8 @@ #include #include +#include + #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 ); } diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index 34317d7fccd..976a7f696a4 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -32,6 +32,7 @@ # include # include # include +# include #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 } diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c b/arch/risc-v/src/common/riscv_schedulesigaction.c index e8c5eab946a..a68b077c276 100644 --- a/arch/risc-v/src/common/riscv_schedulesigaction.c +++ b/arch/risc-v/src/common/riscv_schedulesigaction.c @@ -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; } diff --git a/arch/risc-v/src/common/riscv_swint.c b/arch/risc-v/src/common/riscv_swint.c index d2955a46934..c01866dcc65 100644 --- a/arch/risc-v/src/common/riscv_swint.c +++ b/arch/risc-v/src/common/riscv_swint.c @@ -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 */ diff --git a/arch/risc-v/src/common/riscv_vectors.S b/arch/risc-v/src/common/riscv_vectors.S index d7f0163d441..8f68edaf1b9 100644 --- a/arch/risc-v/src/common/riscv_vectors.S +++ b/arch/risc-v/src/common/riscv_vectors.S @@ -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: diff --git a/arch/risc-v/src/common/supervisor/Make.defs b/arch/risc-v/src/common/supervisor/Make.defs new file mode 100644 index 00000000000..3146d4efa0d --- /dev/null +++ b/arch/risc-v/src/common/supervisor/Make.defs @@ -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 diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c new file mode 100644 index 00000000000..af32ec2cef8 --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c @@ -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 + +#include + +#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; +} diff --git a/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S new file mode 100644 index 00000000000..5e2fd2f8dc7 --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S @@ -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 +#include + +#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 diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs index 0161d9067ae..74e83b5923e 100644 --- a/arch/risc-v/src/esp32c3/Make.defs +++ b/arch/risc-v/src/esp32c3/Make.defs @@ -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 diff --git a/arch/risc-v/src/fe310/Make.defs b/arch/risc-v/src/fe310/Make.defs index 8ebd460ac94..751d3ed0ee0 100644 --- a/arch/risc-v/src/fe310/Make.defs +++ b/arch/risc-v/src/fe310/Make.defs @@ -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 diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs index c1f3e890453..df638976bf5 100644 --- a/arch/risc-v/src/k210/Make.defs +++ b/arch/risc-v/src/k210/Make.defs @@ -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 diff --git a/arch/risc-v/src/litex/Make.defs b/arch/risc-v/src/litex/Make.defs index 667fe01735a..c9727e8e905 100644 --- a/arch/risc-v/src/litex/Make.defs +++ b/arch/risc-v/src/litex/Make.defs @@ -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 diff --git a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c index 77849ff20a2..01e471c0b78 100755 --- a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c +++ b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.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); diff --git a/arch/risc-v/src/qemu-rv/Make.defs b/arch/risc-v/src/qemu-rv/Make.defs index 7813400f695..3d2e6dbaa7f 100644 --- a/arch/risc-v/src/qemu-rv/Make.defs +++ b/arch/risc-v/src/qemu-rv/Make.defs @@ -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 diff --git a/arch/risc-v/src/rv32m1/Make.defs b/arch/risc-v/src/rv32m1/Make.defs index 4adb7c401cb..745bae629fb 100644 --- a/arch/risc-v/src/rv32m1/Make.defs +++ b/arch/risc-v/src/rv32m1/Make.defs @@ -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 diff --git a/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c index 3d3f0299386..bd11c4e3b6b 100644 --- a/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c +++ b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c @@ -31,6 +31,8 @@ #include +#include "riscv_internal.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/boards/risc-v/c906/smartl-c906/src/c906_ostest.c b/boards/risc-v/c906/smartl-c906/src/c906_ostest.c index f3a5c8a6e49..dd6bc11fe88 100644 --- a/boards/risc-v/c906/smartl-c906/src/c906_ostest.c +++ b/boards/risc-v/c906/smartl-c906/src/c906_ostest.c @@ -31,6 +31,8 @@ #include +#include "riscv_internal.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/boards/risc-v/mpfs/common/src/mpfs_ostest.c b/boards/risc-v/mpfs/common/src/mpfs_ostest.c index 587b4415131..6b4e3dbfecb 100755 --- a/boards/risc-v/mpfs/common/src/mpfs_ostest.c +++ b/boards/risc-v/mpfs/common/src/mpfs_ostest.c @@ -31,6 +31,8 @@ #include +#include "riscv_internal.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c index d06f3e1cd9a..4fefb06a085 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_ostest.c @@ -31,6 +31,8 @@ #include +#include "riscv_internal.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/