Skip to content

Commit

Permalink
RISC-V: Implement option to run NuttX in supervisor mode (S-mode)
Browse files Browse the repository at this point in the history
- Add config "ARCH_USE_S_MODE" which controls whether the kernel
  runs in M-mode or S-mode
- Add more MSTATUS and most of the SSTATUS register definitions
- Add more MIP flags for interrupt delegation
- Add handling of interrupts from S-mode
- Add handling of FPU from S-mode
- Add new context handling functions that are not dependent on the trap
  handlers / ecall

NOTE: S-mode requires a companion SW (SBI) which is not yet implemented,
      thus S-mode is not usable as is, yet.
  • Loading branch information
pussuw committed Mar 29, 2022
1 parent 0460367 commit 645147a
Show file tree
Hide file tree
Showing 24 changed files with 1,050 additions and 112 deletions.
22 changes: 22 additions & 0 deletions arch/risc-v/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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.

Expand Down
54 changes: 50 additions & 4 deletions arch/risc-v/include/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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) \
({ \
Expand Down Expand Up @@ -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 */
Expand Down
23 changes: 17 additions & 6 deletions arch/risc-v/include/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <nuttx/irq.h>
#include <arch/csr.h>
#include <arch/chip/irq.h>
#include <arch/mode.h>
#endif

/****************************************************************************
Expand All @@ -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 */
Expand All @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
);

Expand All @@ -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"
Expand Down
93 changes: 93 additions & 0 deletions arch/risc-v/include/mode.h
Original file line number Diff line number Diff line change
@@ -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 <nuttx/config.h>

#include <arch/csr.h>
#include <arch/irq.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#ifdef CONFIG_ARCH_USE_S_MODE

/* CSR definitions */

# define CSR_STATUS sstatus /* Global status register */
# define CSR_EPC sepc /* Exception program counter */
# define CSR_IE sie /* Interrupt enable register */

/* 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 */
Loading

0 comments on commit 645147a

Please sign in to comment.