diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index b199d393e9691..e2fed3613311e 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -101,6 +101,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). @@ -188,6 +189,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 a5cb948b0c82b..3866f6637d217 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,15 +331,47 @@ /* 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) -#define CSR_STR(csr) #csr +/* 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 + +#define CSR_STR(csr) #csr +#define CSR_XSTR(str) CSR_STR(str) #define READ_CSR(reg) \ ({ \ @@ -359,8 +405,8 @@ /* 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 4ae804c5b9df6..38e8a942f8185 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -39,6 +39,7 @@ #include #include #include +#include #endif /**************************************************************************** @@ -50,7 +51,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 */ @@ -64,7 +65,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) @@ -99,6 +100,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 @@ -472,7 +483,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 @@ -580,9 +591,9 @@ static inline irqstate_t up_irq_save(void) __asm__ __volatile__ ( - "csrrc %0, mstatus, %1\n" + "csrrc %0, " CSR_XSTR(CSR_STATUS) ", %1\n" : "=r" (flags) - : "r"(MSTATUS_MIE) + : "r"(STATUS_IE) : "memory" ); @@ -605,7 +616,7 @@ static inline void up_irq_restore(irqstate_t flags) { __asm__ __volatile__ ( - "csrw mstatus, %0\n" + "csrw " CSR_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 0000000000000..1dc7eb4762639 --- /dev/null +++ b/arch/risc-v/include/mode.h @@ -0,0 +1,93 @@ +/**************************************************************************** + * 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 +#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 */ + +/* 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 */ + +#else + +/* CSR definitions */ + +# define CSR_STATUS mstatus /* Global status register */ +# define CSR_EPC mepc /* Exception program counter */ +# define CSR_IE mie /* Interrupt enable 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 */ + +#endif + +#endif /* __ARCH_RISCV_INCLUDE_MODE_H */ diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h index a357d1d84d169..27fdd83502299 100644 --- a/arch/risc-v/include/syscall.h +++ b/arch/risc-v/include/syscall.h @@ -57,6 +57,7 @@ /* RV64GC system calls ******************************************************/ +#ifndef CONFIG_ARCH_USE_S_MODE /* SYS call 1 and 2 are defined for internal use by the RISC-V port (see * arch/risc-v/include/syscall.h). In addition, SYS call 3 is the * return from a SYS call in kernel mode. The first four syscall values must, @@ -78,6 +79,7 @@ */ #define SYS_switch_context (2) +#endif /* CONFIG_ARCH_USE_S_MODE */ #ifdef CONFIG_LIB_SYSCALL /* SYS call 3: @@ -122,51 +124,6 @@ #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) - -#endif -#endif /* __ASSEMBLY__ */ - /**************************************************************************** * Public Types ****************************************************************************/ @@ -207,7 +164,15 @@ static inline uintptr_t sys_call0(unsigned int nbr) asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0) : "memory" ); @@ -232,7 +197,15 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0), "r"(r1) : "memory" ); @@ -259,7 +232,15 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0), "r"(r1), "r"(r2) : "memory" ); @@ -287,7 +268,15 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0), "r"(r1), "r"(r2), "r"(r3) : "memory" ); @@ -317,7 +306,15 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4) : "memory" ); @@ -348,7 +345,15 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) : "memory" ); @@ -381,7 +386,15 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, asm volatile ( +#if defined (CONFIG_ARCH_USE_S_MODE) && defined (__KERNEL__) + " addi sp, sp, -16\n" /* Make room */ + " sd ra, 0(sp)\n" /* Save ra */ + " jal ra, riscv_syscall_dispatch\n" /* Dispatch (modifies ra) */ + " ld ra, 0(sp)\n" /* Restore ra */ + " addi sp, sp, 16\n" /* Restore sp */ +#else "ecall" +#endif :: "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 f598c6fd2e30f..06c2d0bf86c7f 100644 --- a/arch/risc-v/src/Makefile +++ b/arch/risc-v/src/Makefile @@ -24,10 +24,19 @@ ifeq ($(CONFIG_OPENSBI),y) include opensbi/Make.defs endif +# Kernel runs in supervisor mode or machine mode ? + +ifeq ($(CONFIG_ARCH_USE_S_MODE),y) +ARCH_CMN_MODE_DIR = supervisor +else +ARCH_CMN_MODE_DIR = machine +endif + ARCH_SRCDIR = $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip} INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)common} +INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)common$(DELIM)$(ARCH_CMN_MODE_DIR)} INCLUDES += ${shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)sched} ifeq ($(CONFIG_OPENSBI),y) INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdparty$(DELIM)include) @@ -101,6 +110,7 @@ endif VPATH += chip VPATH += common +VPATH += common$(DELIM)$(ARCH_CMN_MODE_DIR) ifeq ($(CONFIG_OPENSBI),y) VPATH += opensbi endif diff --git a/arch/risc-v/src/common/riscv_exception_common.S b/arch/risc-v/src/common/machine/riscv_exception_common.S similarity index 96% rename from arch/risc-v/src/common/riscv_exception_common.S rename to arch/risc-v/src/common/machine/riscv_exception_common.S index 4d5665ac2dc4a..8a43a16b01e8e 100644 --- a/arch/risc-v/src/common/riscv_exception_common.S +++ b/arch/risc-v/src/common/machine/riscv_exception_common.S @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/riscv_exception_common.S + * arch/risc-v/src/common/machine/riscv_exception_common.S * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -37,14 +37,6 @@ # define REGSTORE sd #endif -#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 ****************************************************************************/ diff --git a/arch/risc-v/src/common/riscv_vectors.S b/arch/risc-v/src/common/machine/riscv_vectors.S similarity index 88% rename from arch/risc-v/src/common/riscv_vectors.S rename to arch/risc-v/src/common/machine/riscv_vectors.S index d7f0163d4412f..ac2959a3fb1df 100644 --- a/arch/risc-v/src/common/riscv_vectors.S +++ b/arch/risc-v/src/common/machine/riscv_vectors.S @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/riscv_vectors.S + * arch/risc-v/src/common/machine/riscv_vectors.S * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -23,11 +23,15 @@ ****************************************************************************/ .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. + * ****************************************************************************/ __trap_vec: diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c index fbf4e9face411..201fa0639a1c6 100644 --- a/arch/risc-v/src/common/riscv_cpuindex.c +++ b/arch/risc-v/src/common/riscv_cpuindex.c @@ -47,7 +47,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_fpu.S b/arch/risc-v/src/common/riscv_fpu.S index ba35db263f21f..69ffecb863f6a 100644 --- a/arch/risc-v/src/common/riscv_fpu.S +++ b/arch/risc-v/src/common/riscv_fpu.S @@ -25,6 +25,7 @@ #include #include +#include #ifdef CONFIG_ARCH_FPU @@ -92,7 +93,7 @@ up_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 04180f7abb713..713c8413883cf 100644 --- a/arch/risc-v/src/common/riscv_getnewintctx.c +++ b/arch/risc-v/src/common/riscv_getnewintctx.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "riscv_internal.h" @@ -49,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 be7967e8ecb21..b413d754e9eec 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 /**************************************************************************** @@ -201,6 +202,7 @@ void riscv_copystate(uintptr_t *dest, uintptr_t *src); void riscv_sigdeliver(void); int riscv_swint(int irq, void *context, void *arg); +void *riscv_handle_syscall(uintptr_t *regs); uintptr_t riscv_get_newintctx(void); #ifdef CONFIG_ARCH_FPU @@ -283,6 +285,60 @@ int riscv_pause_handler(int irq, void *c, void *arg); uintptr_t riscv_mhartid(void); +#ifdef CONFIG_ARCH_USE_S_MODE +/* If kernel runs in Supervisor mode, declare proper function prototypes, + * this is because it is not possible to ecall from S mode to S mode + */ + +int riscv_saveusercontext(uintptr_t *saveregs); +void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function; +void riscv_switchcontext(uintptr_t **saveregs, uintptr_t *restoreregs); +void riscv_syscall_return(void); +void riscv_syscall_dispatch(void) noreturn_function; + +#else + +/* 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 */ +#endif /* CONFIG_ARCH_USE_S_MODE */ + #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 e8c5eab946a45..a68b077c2764d 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 7d14148e1ca1d..0017fafe6bffd 100644 --- a/arch/risc-v/src/common/riscv_swint.c +++ b/arch/risc-v/src/common/riscv_swint.c @@ -114,7 +114,7 @@ static void dispatch_syscall(void) { asm volatile ( - " addi sp, sp, -8\n" /* Create a stack frame to hold ra */ + " addi sp, sp, -16\n" /* Create a stack frame to hold ra */ " sd ra, 0(sp)\n" /* Save ra in the stack frame */ " la t0, g_stublookup\n" /* t0=The base of the stub lookup table */ " slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */ @@ -122,10 +122,14 @@ static void dispatch_syscall(void) " ld t0, 0(t0)\n" /* t0=The address of the stub for this syscall */ " jalr ra, t0\n" /* Call the stub (modifies ra) */ " ld ra, 0(sp)\n" /* Restore ra */ - " addi sp, sp, 8\n" /* Destroy the stack frame */ + " addi sp, sp, 16\n" /* Destroy the stack frame */ " mv a2, a0\n" /* a2=Save return value in a0 */ " li a0, 3\n" /* a0=SYS_syscall_return (3) */ +#ifdef CONFIG_ARCH_USE_S_MODE + " j riscv_syscall_return" /* Return from the syscall */ +#else " ecall" /* Return from the syscall */ +#endif ); } #else @@ -144,7 +148,11 @@ static void dispatch_syscall(void) " addi sp, sp, 4\n" /* Destroy the stack frame */ " mv a2, a0\n" /* a2=Save return value in a0 */ " li a0, 3\n" /* a0=SYS_syscall_return (3) */ +#ifdef CONFIG_ARCH_USE_S_MODE + " j riscv_syscall_return" /* Return from the syscall */ +#else " ecall" /* Return from the syscall */ +#endif ); } #endif @@ -179,6 +187,31 @@ int riscv_swint(int irq, void *context, void *arg) riscv_registerdump(regs); #endif + /* Handle the syscall */ + + regs = riscv_handle_syscall(regs); + + /* Report what happened. That might difficult in the case of a context + * switch + */ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO + if (regs != CURRENT_REGS) + { + svcinfo("SWInt Return: Context switch!\n"); + riscv_registerdump((const uintptr_t *)CURRENT_REGS); + } + else + { + svcinfo("SWInt Return: %d\n", regs[REG_A0]); + } +#endif + + return OK; +} + +void *riscv_handle_syscall(uintptr_t *regs) +{ /* Handle the SWInt according to the command in $a0 */ switch (regs[REG_A0]) @@ -196,6 +229,7 @@ int riscv_swint(int irq, void *context, void *arg) * save register space references in the saved A1 and return. */ +#ifndef CONFIG_ARCH_USE_S_MODE case SYS_save_context: { DEBUGASSERT(regs[REG_A1] != 0); @@ -253,6 +287,7 @@ int riscv_swint(int irq, void *context, void *arg) CURRENT_REGS = (uintptr_t *)regs[REG_A2]; } break; +#endif /* CONFIG_ARCH_USE_S_MODE */ /* A0=SYS_syscall_return: This is a SYSCALL return command: * @@ -352,7 +387,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 @@ -384,7 +419,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 @@ -423,7 +458,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. @@ -473,7 +508,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; @@ -521,7 +556,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; @@ -529,7 +564,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 */ @@ -559,21 +594,5 @@ int riscv_swint(int irq, void *context, void *arg) break; } - /* Report what happened. That might difficult in the case of a context - * switch - */ - -#ifdef CONFIG_DEBUG_SYSCALL_INFO - if (regs != CURRENT_REGS) - { - svcinfo("SWInt Return: Context switch!\n"); - riscv_registerdump((const uintptr_t *)CURRENT_REGS); - } - else - { - svcinfo("SWInt Return: %d\n", regs[REG_A0]); - } -#endif - - return OK; + return regs; } diff --git a/arch/risc-v/src/common/supervisor/riscv_context.S b/arch/risc-v/src/common/supervisor/riscv_context.S new file mode 100644 index 0000000000000..f27e56fe918ae --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_context.S @@ -0,0 +1,234 @@ +/**************************************************************************** + * arch/risc-v/src/common/supervisor/riscv_context.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_context.S" + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "riscv_exception_macros.S" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl riscv_saveusercontext + .globl riscv_fullcontextrestore + .globl riscv_switchcontext + .globl riscv_syscall_return + +/**************************************************************************** + * Name: riscv_saveusercontext + * + * Description: + * Save user context, partially destroys the caller's context + * + * C Function Prototype: + * int riscv_saveusercontext(uintptr_t *saveregs); + * + * Input Parameters: + * saveregs - Context to save + * + * Returned Value: + * 0 on context switch + * 1 on no context switch + * + * Assumptions: + * Global interrupts disabled by the caller. + * + ****************************************************************************/ + +.type riscv_saveusercontext, function + +riscv_saveusercontext: + + save_ctx a0 /* save context */ + + csrr s0, CSR_STATUS + REGSTORE s0, REG_INT_CTX(a0) /* save status */ + + REGSTORE x1, REG_EPC(a0) /* save ra to epc */ + REGSTORE sp, REG_SP(a0) /* original SP */ + +#ifdef CONFIG_ARCH_FPU + jal x1, riscv_savefpu /* FP registers */ + REGLOAD x1, REG_X1(a0) /* restore ra */ +#endif + + li s0, 1 /* return 1 (in context) */ + REGSTORE s0, REG_A0(a0) + REGLOAD s0, REG_S0(a0) /* restore s0 */ + + li a0, 0 /* return 0 (back to caller) */ + ret + +/**************************************************************************** + * Name: riscv_fullcontextrestore + * + * Description: + * Restore context + * + * C Function Prototype: + * void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function; + * + * Input Parameters: + * restoreregs - Context to restore + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts disabled by the caller. + * + ****************************************************************************/ + +.type riscv_fullcontextrestore, function + +riscv_fullcontextrestore: + +#ifdef CONFIG_ARCH_FPU + jal x1, riscv_restorefpu /* FP registers */ +#endif + + mv sp, a0 /* use sp, as a0 gets wiped */ + + 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 */ + + sret + +/**************************************************************************** + * Name: riscv_switchcontext + * + * Description: + * Restore user context + * + * C Function Prototype: + * void riscv_switchcontext(uintptr_t *saveregs, uintptr_t *restoreregs); + * + * Input Parameters: + * saveregs - Context to save + * restoreregs - Context to restore + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts disabled by the caller. + * + ****************************************************************************/ + +.type riscv_switchcontext, function + +riscv_switchcontext: + + /* Save old context to arg[0] */ + + save_ctx a0 /* save context */ + + REGSTORE x1, REG_EPC(a0) /* save ra to epc */ + REGSTORE sp, REG_SP(a0) /* original SP */ + + /* Set previous privilege, we are in privileged mode now */ + + csrr s0, CSR_STATUS /* read status register */ + li s1, STATUS_PPP /* set previous privilege */ + or s0, s0, s1 + li s1, ~STATUS_PIE /* clear previous interrupt enable */ + and s0, s0, s1 + REGSTORE s0, REG_INT_CTX(a0) /* store status to context */ + +#ifdef CONFIG_ARCH_FPU + jal x1, riscv_savefpu /* FP registers */ +#endif + + /* Load new context from arg[1] */ + + mv a0, a1 /* load from a1 */ + j riscv_fullcontextrestore /* restore context */ + +/**************************************************************************** + * Name: riscv_syscall_return + * + * Description: + * Return from system call to user task with user mode privileges + * + * C Function Prototype: + * void riscv_syscall_return(void); + * + * Input Parameters: + * Assumes the return value of the system call is in a0 + * + * Returned Value: + * Return value of system call is returned into contex + * + * Assumptions: + * User task is running system call in privileged mode, ready to resume + * the user task in unprivileged mode + * + ****************************************************************************/ + +.type riscv_syscall_return, function + +riscv_syscall_return: + + addi sp, sp, -XCPTCONTEXT_SIZE /* make room */ + save_ctx sp /* save current context */ + + /* Mask interrupts here, they will be re-enabled later */ + + li s0, STATUS_IE + csrc CSR_STATUS, s0 + + addi s0, sp, XCPTCONTEXT_SIZE + REGSTORE s0, REG_SP(sp) /* original SP */ + + mv a0, sp /* a0 = context */ + jal x1, riscv_handle_syscall /* run the exit function */ + + j riscv_fullcontextrestore /* resume the user task */ diff --git a/arch/risc-v/src/common/supervisor/riscv_exception_common.S b/arch/risc-v/src/common/supervisor/riscv_exception_common.S new file mode 100644 index 0000000000000..73b633aaf423c --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_exception_common.S @@ -0,0 +1,137 @@ +/**************************************************************************** + * arch/risc-v/src/common/supervisor/riscv_exception_common.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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "riscv_exception_macros.S" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + +/**************************************************************************** + * Name: exception_common + * + * Description: + * Handles delegated interrupts in S-mode interrupt handler. + * + ****************************************************************************/ + + .section .text + .global exception_common + .align 8 + +exception_common: + + addi sp, sp, -XCPTCONTEXT_SIZE + save_ctx sp + + csrr s0, sstatus + REGSTORE s0, REG_INT_CTX(sp) /* sstatus */ + + addi s0, sp, XCPTCONTEXT_SIZE + REGSTORE s0, REG_X2(sp) /* original SP */ + + /* Setup arg0(exception cause), arg1(context) */ + + csrr a0, scause /* exception cause */ + csrr s0, sepc + REGSTORE s0, REG_EPC(sp) /* exception PC */ + + mv a1, sp /* context = sp */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + + /* Offset to hartid */ + + mv s0, a0 /* save scause */ + jal x1, riscv_mhartid /* get hartid */ + + /* Switch to interrupt stack */ + +#if IRQ_NSTACKS > 1 + li t0, (CONFIG_ARCH_INTERRUPTSTACK & ~15) + mul t0, a0, t0 + la a0, g_intstacktop + sub sp, a0, t0 +#else + la sp, g_intstacktop +#endif + + mv a0, s0 /* restore scause */ + + /* Call interrupt handler in C */ + + jal x1, riscv_dispatch_irq + +#else + /* Reserve some space for CURRENT_REGS if interrupt stack disabled */ + + addi sp, sp, -XCPTCONTEXT_SIZE + + /* Call interrupt handler in C */ + + jal x1, riscv_dispatch_irq + + /* Restore sp */ + + addi sp, sp, XCPTCONTEXT_SIZE +#endif + + /* If context switch is needed, return a new sp */ + + mv sp, a0 + + REGLOAD s0, REG_EPC(sp) /* restore sepc */ + csrw sepc, s0 + + REGLOAD s0, REG_INT_CTX(sp) /* restore sstatus */ + csrw sstatus, s0 + + load_ctx sp + + REGLOAD sp, REG_SP(sp) /* restore original sp */ + + /* Return from Supervisor Interrupt */ + + sret + +/***************************************************************************** + * Name: g_intstackalloc and g_intstacktop + ****************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + .bss + .balign 16 + .global g_intstackalloc + .global g_intstacktop + .type g_intstackalloc, object + .type g_intstacktop, object +g_intstackalloc: + .skip (((CONFIG_ARCH_INTERRUPTSTACK * IRQ_NSTACKS) + 8) & ~15) +g_intstacktop: + .size g_intstacktop, 0 + .size g_intstackalloc, ((CONFIG_ARCH_INTERRUPTSTACK * IRQ_NSTACKS) & ~15) +#endif diff --git a/arch/risc-v/src/common/supervisor/riscv_exception_macros.S b/arch/risc-v/src/common/supervisor/riscv_exception_macros.S new file mode 100644 index 0000000000000..ec4dc78fa3f3c --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_exception_macros.S @@ -0,0 +1,136 @@ +/**************************************************************************** + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_ARCH_RV32 +# define REGLOAD lw +# define REGSTORE sw +#else +# define REGLOAD ld +# define REGSTORE sd +#endif + +/**************************************************************************** + * 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/supervisor/riscv_syscall_dispatch.S b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S new file mode 100644 index 0000000000000..348d431575808 --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_syscall_dispatch.S @@ -0,0 +1,93 @@ +/**************************************************************************** + * 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, return to user mode + * + * 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: + * User task is running in privileged mode with interrupts masked, + * ready to resume the user task in unprivileged mode with interrupts + * restored + * + ****************************************************************************/ + +.type riscv_syscall_dispatch, function + +riscv_syscall_dispatch: + + addi sp, sp, -XCPTCONTEXT_SIZE /* make room */ + save_ctx sp /* save current context */ + + REGSTORE x1, REG_EPC(sp) /* save ra to epc */ + + addi s0, sp, XCPTCONTEXT_SIZE + REGSTORE s0, REG_SP(sp) /* original SP */ + + /* Set previous privilege, we are in privileged mode now */ + + csrr s0, CSR_STATUS /* read status register */ + li s1, STATUS_PPP /* set previous privilege */ + or s0, s0, s1 + li s1, ~STATUS_PIE /* clear previous interrupt enable */ + and s0, s0, s1 + REGSTORE s0, REG_INT_CTX(sp) /* store status to context */ + +#ifdef CONFIG_ARCH_FPU + mv a0, sp + jal x1, riscv_savefpu /* FP registers */ +#endif + + mv a0, sp /* a0 = context */ + jal x1, riscv_handle_syscall /* run the syscall */ + + j riscv_fullcontextrestore /* resume the user task */ diff --git a/arch/risc-v/src/common/supervisor/riscv_vectors.S b/arch/risc-v/src/common/supervisor/riscv_vectors.S new file mode 100644 index 0000000000000..b77ff3351d182 --- /dev/null +++ b/arch/risc-v/src/common/supervisor/riscv_vectors.S @@ -0,0 +1,52 @@ +/**************************************************************************** + * arch/risc-v/src/common/supervisor/riscv_vectors.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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + .section .text + .balign 8 + .global __trap_vec + .global __irq_vec + +/**************************************************************************** + * Name: __trap_vec + * + * Description: + * All M-mode exceptions and interrupts will be handled from here. + * + ****************************************************************************/ + +__trap_vec: + j trap_vector + nop + + /**************************************************************************** + * Name: __irq_vec + * + * Description: + * All S-mode exceptions and interrupts will be handled from here. + * + ****************************************************************************/ + +__irq_vec: + j exception_common + nop diff --git a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c index 1e420c0c78cbc..a16e6e0175d6d 100755 --- a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c +++ b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c @@ -60,7 +60,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/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c index 3d3f02993867e..bd11c4e3b6ba1 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 f3a5c8a6e4981..dd6bc11fe8817 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 587b4415131ae..6b4e3dbfecb03 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 d06f3e1cd9a16..4fefb06a08592 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 ****************************************************************************/