diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 422c61f88a9..c45d64505c1 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -282,6 +282,9 @@ config RISCV_MISALIGNED_HANDLER # 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. +# +# Note that S-mode requires a companion software (SBI) +# config ARCH_USE_S_MODE bool "Run the NuttX kernel in S-mode" @@ -378,6 +381,7 @@ endchoice endif source "arch/risc-v/src/opensbi/Kconfig" +source "arch/risc-v/src/nuttsbi/Kconfig" if ARCH_CHIP_FE310 source "arch/risc-v/src/fe310/Kconfig" diff --git a/arch/risc-v/src/Makefile b/arch/risc-v/src/Makefile index c61f29de569..4118775cf72 100644 --- a/arch/risc-v/src/Makefile +++ b/arch/risc-v/src/Makefile @@ -22,6 +22,8 @@ include $(TOPDIR)/Make.defs include chip/Make.defs ifeq ($(CONFIG_OPENSBI),y) include opensbi/Make.defs +else ifeq ($(CONFIG_NUTTSBI),y) +include nuttsbi/Make.defs endif # Kernel runs in supervisor mode or machine mode ? diff --git a/arch/risc-v/src/nuttsbi/Kconfig b/arch/risc-v/src/nuttsbi/Kconfig new file mode 100644 index 00000000000..004ef2745a1 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/Kconfig @@ -0,0 +1,30 @@ + +# S-mode requires a Supervisor Binary Interface (SBI) in order to access +# M-mode ISA. A minimalistic SBI is provided here natively. + +config NUTTSBI + bool "Use NuttX native SBI" + default n + depends on ARCH_RISCV && ARCH_USE_S_MODE + ---help--- + Use NuttX minimalistic SBI + +if NUTTSBI + +config NUTTSBI_HART_CNT + int "Amount of harts in SoC" + default 1 + +config NUTTSBI_MTIME_BASE + hex "MTIME base address" + default 0 + ---help--- + Sets the address of mtime memory mapped register + +config NUTTSBI_MTIMECMP_BASE + hex "MTIMECMP base address" + default 0 + ---help--- + Sets the address of mtimecmp memory mapped register + +endif diff --git a/arch/risc-v/src/nuttsbi/Make.defs b/arch/risc-v/src/nuttsbi/Make.defs new file mode 100644 index 00000000000..2052c8e108e --- /dev/null +++ b/arch/risc-v/src/nuttsbi/Make.defs @@ -0,0 +1,33 @@ +############################################################################ +# arch/risc-v/src/nuttsbi/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 NuttX SBI is needed + +ifeq ($(CONFIG_NUTTSBI),y) + +SBI_ASRCS += sbi_mtrap.S sbi_vectors.S sbi_head.S +SBI_CSRCS += sbi_mscratch.c sbi_mcall.c sbi_start.c +SBI_CSRCS += sbi_mexception.c sbi_mtimer.c + +INCLUDES += ${shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)nuttsbi} + +SBI_DIR := nuttsbi + +endif diff --git a/arch/risc-v/src/nuttsbi/sbi_head.S b/arch/risc-v/src/nuttsbi/sbi_head.S new file mode 100644 index 00000000000..745565d29a0 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_head.S @@ -0,0 +1,131 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_head.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 "sbi_internal.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + /* Imported symbols */ + + .extern __mtrap_vec + + .section .text + .global __start + +__start: + + /* Disable all interrupts (i.e. timer, external) in mie */ + + csrw mie, zero + csrw mip, zero + + /* Initialize the Machine Trap Vector */ + + la t0, __mtrap_vec + csrw mtvec, t0 + + /* Make sure that mtvec is updated before continuing */ + +1: + csrr t1, mtvec + bne t0, t1, 1b + + /* mscratch must be init to zero- we are not using scratch memory */ + + csrw mscratch, zero + csrw mcause, zero + csrw mepc, zero + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + /* Delegation registers must be explicitly reset */ + + csrw mideleg, 0 + csrw medeleg, 0 + + /* Remove MMU mappings (if any) */ + + csrw satp, zero + fence + + /* Flush TLB (does not make a difference really) */ + + sfence.vma x0, x0 + + /* Clear PMP */ + + csrw pmpcfg0, 0 + csrw pmpcfg2, 0 + + /* Set up a temporary stack */ + +#if MMODE_HART_CNT > 1 + /* REVISIT: This requires that hartID is sequential, and starts from 0 */ + + csrr a0, mhartid + li s0, TEMP_STACK_SIZE + mul s0, a0, s0 + la s1, TEMP_STACK_BASE + sub sp, s1, s0 +#else + la sp, TEMP_STACK_BASE +#endif + + /* Jump to start */ + + j sbi_start diff --git a/arch/risc-v/src/nuttsbi/sbi_internal.h b/arch/risc-v/src/nuttsbi/sbi_internal.h new file mode 100644 index 00000000000..79e4690135a --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_internal.h @@ -0,0 +1,144 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_internal.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_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H +#define __ARCH_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Amount of harts, based on chip capability, not utilization */ + +#define MMODE_HART_CNT (CONFIG_NUTTSBI_HART_CNT) + +/* The machine mode interrupts should not be too complex */ + +#define MMODE_IRQSTACK (1024) + +/* Timer interrupt is the only one we handle, others are discarded */ + +#define MTIMER_IRQ (7) + +/* Timer memory mapped registers */ + +#define MTIMER_TIME_BASE (CONFIG_NUTTSBI_MTIME_BASE) +#define MTIMER_CMP_BASE (CONFIG_NUTTSBI_MTIMECMP_BASE) + +/* For stack alignment */ + +#define STACK_ALIGNMENT 16 +#define STACK_ALIGN_MASK (STACK_ALIGNMENT - 1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/* Temporary stack placement and size */ + +#define TEMP_STACK_BASE (_ebss) +#define TEMP_STACK (1024) +#define TEMP_STACK_SIZE (STACK_ALIGN_DOWN(TEMP_STACK)) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: riscv_mscratch_assign + * + * Description: + * Assign the mscratch register for hartid. Sets the M-mode interrupt stack + * which is a must because M-mode deals with flat addressing and cannot + * share the user stack for exception handling. + * + * Input Parameters: + * hartid - Hartid. + * + ****************************************************************************/ + +void sbi_mscratch_assign(uintptr_t hartid); + +/**************************************************************************** + * Name: sbi_start + * + * Description: + * Sets up entry to board specific start routine in S-mode. Mandatory + * trampoline function when the native SBI is used. Called from M-mode. + * + ****************************************************************************/ + +void sbi_start(void) noreturn_function; + +/**************************************************************************** + * Name: sbi_init_mtimer + * + * Description: + * Set up access to mtimer for SBI. This is an extremely light weight way + * of provisioning the mtimer memory mapped registers to SBI. + * + * Input Parameters: + * mtime - Pointer to machine time memory mapped register. + * mtimecmp - Pointer to the base of the mtimecmp memory mapped registers, + * implementation assumes there is 1 per hart and that they + * follow each other. + * + ****************************************************************************/ + +void sbi_init_mtimer(uintptr_t mtime, uintptr_t mtimecmp); + +/**************************************************************************** + * Name: sbi_get_mtime + * + * Description: + * Read value of mtime + * + * Returned value: + * Full 64-bit system time + * + ****************************************************************************/ + +uint64_t sbi_get_mtime(void); + +/**************************************************************************** + * Name: sbi_set_mtimecmp + * + * Description: + * Set value of mtimecmp. + * + * Input Parameters: + * value - Value for mtimecmp. + * + ****************************************************************************/ + +void sbi_set_mtimecmp(uint64_t value); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISC_V_SRC_NUTTSBI_SBI_INTERNAL_H */ diff --git a/arch/risc-v/src/nuttsbi/sbi_mcall.c b/arch/risc-v/src/nuttsbi/sbi_mcall.c new file mode 100644 index 00000000000..1f8596b3f57 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mcall.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_mcall.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 + +#include "riscv_internal.h" + +#include "sbi_mcall.h" +#include "sbi_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sbi_mcall_handle + * + * Description: + * Handle environment call to machine mode + * + * Input Parameters: + * regs - User context + * + ****************************************************************************/ + +void sbi_mcall_handle(uintptr_t *regs) +{ + /* Check the environment call number */ + + switch (regs[REG_A0]) + { + case MCALL_GET_TIMER: +#ifdef CONFIG_ARCH_RV64 + regs[REG_A0] = sbi_get_mtime(); +#else + { + uint64_t time = sbi_get_mtime(); + regs[REG_A0] = (uint32_t)time; + regs[REG_A1] = (uint32_t)(time >> 32); + } +#endif + break; + + case MCALL_SET_TIMER: +#ifdef CONFIG_ARCH_RV64 + sbi_set_mtimecmp(regs[REG_A1]); +#else + sbi_set_mtimecmp(regs[REG_A1] + ((uint64_t)regs[REG_A2] << 32)); +#endif + CLEAR_CSR(mip, MIP_STIP); + SET_CSR(mie, MIE_MTIE); + break; + + default: + break; + } +} diff --git a/arch/risc-v/src/nuttsbi/sbi_mcall.h b/arch/risc-v/src/nuttsbi/sbi_mcall.h new file mode 100644 index 00000000000..95154a2eacb --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mcall.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_mcall.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_RISC_V_SRC_NUTTSBI_SBI_MCALL_H +#define __ARCH_RISC_V_SRC_NUTTSBI_SBI_MCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum mcall_num_e +{ + MCALL_INVALID, + MCALL_GET_TIMER, + MCALL_SET_TIMER, + MCALL_LAST +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mcall0 + * + * Description: + * Generate an environment call to machine mode + * + * Input Parameters: + * nbr - Environment call number + * + ****************************************************************************/ + +static inline uintptr_t mcall0(unsigned int nbr) +{ + register long r0 asm("a0") = (long)(nbr); + + asm volatile + ( + "ecall" + :: "r"(r0) + : "memory" + ); + + asm volatile("nop" : "=r"(r0)); + + return r0; +} + +/**************************************************************************** + * Name: mcall1 + * + * Description: + * Generate an environment call to machine mode + * + * Input Parameters: + * nbr - Environment call number + * parm1 - Argument for ecall + * + ****************************************************************************/ + +static inline uintptr_t mcall1(unsigned int nbr, uintptr_t parm1) +{ + register long r0 asm("a0") = (long)(nbr); + register long r1 asm("a1") = (long)(parm1); + + asm volatile + ( + "ecall" + :: "r"(r0), "r"(r1) + : "memory" + ); + + asm volatile("nop" : "=r"(r0)); + + return r0; +} + +/**************************************************************************** + * Name: sbi_mcall_get_time + * + * Description: + * Read the current system time (mtime) + * + * Returned Value: + * time - Value of mtime + * + ****************************************************************************/ + +#define sbi_mcall_get_time() \ + mcall0(MCALL_GET_TIMER) + +/**************************************************************************** + * Name: sbi_mcall_set_timer + * + * Description: + * Set new compare match value for timer. Time is in absolute time, so + * user must either obtain system time and calculate the offset, or keep + * the old compare match value in memory + * + * Input Parameters: + * stime_value - Absolute time for next compare match event + * + ****************************************************************************/ + +#define sbi_mcall_set_timer(stime_value) \ + (void)mcall1(MCALL_SET_TIMER, stime_value) + +#endif /* __ARCH_RISC_V_SRC_NUTTSBI_SBI_MCALL_H */ diff --git a/arch/risc-v/src/nuttsbi/sbi_mexception.c b/arch/risc-v/src/nuttsbi/sbi_mexception.c new file mode 100644 index 00000000000..27cd033a358 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mexception.c @@ -0,0 +1,37 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_mexception.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 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void sbi_mexception(uintptr_t mcause, uintptr_t *mepc) +{ + (void) mcause; + (void) mepc; +} diff --git a/arch/risc-v/src/nuttsbi/sbi_mscratch.c b/arch/risc-v/src/nuttsbi/sbi_mscratch.c new file mode 100644 index 00000000000..7010678a699 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mscratch.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_mscratch.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 + +#include + +#include "riscv_internal.h" + +#include "sbi_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STACK_SIZE (STACK_ALIGN_DOWN(MMODE_IRQSTACK)) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern uintptr_t g_mintstacktop; +extern uintptr_t g_mintstackalloc; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sbi_mscratch_assign + * + * Description: + * Assign the mscratch register for hartid. Sets the M-mode interrupt stack + * which is a must because M-mode deals with flat addressing and cannot + * share the user stack for exception handling. + * + * Input Parameters: + * hartid - Hartid + * + ****************************************************************************/ + +void sbi_mscratch_assign(uintptr_t hartid) +{ + uintptr_t stack_top; +#if MMODE_HART_CNT > 1 + /* Calculate offset first (stack size * hartid) */ + + /* REVISIT: This requires that hartID is sequential, and starts from 0 */ + + stack_top = (uintptr_t)&g_mintstacktop - hartid * STACK_SIZE; +#else + UNUSED(hartid); + stack_top = (uintptr_t)&g_mintstacktop; +#endif + + WRITE_CSR(mscratch, stack_top); + + /* Make sure mscratch is updated before continuing */ + + __DMB(); +} diff --git a/arch/risc-v/src/nuttsbi/sbi_mtimer.c b/arch/risc-v/src/nuttsbi/sbi_mtimer.c new file mode 100644 index 00000000000..a6771bdbf52 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mtimer.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_mtimer.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 + +#include + +#include + +#include "riscv_internal.h" + +#include "sbi_internal.h" +#include "sbi_mcall.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Memory mapped register base addresses */ + +static volatile uintptr_t g_mtimecmp locate_data(".noinit"); +static volatile uintptr_t g_mtime locate_data(".noinit"); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void sbi_init_mtimer(uintptr_t mtime, uintptr_t mtimecmp) +{ + /* Set the memory mapped register bases */ + + g_mtimecmp = mtimecmp; + g_mtime = mtime; +} + +uint64_t sbi_get_mtime(void) +{ +#ifdef CONFIG_ARCH_RV64 + return getreg64(g_mtime); +#else + uint32_t hi; + uint32_t lo; + + do + { + hi = getreg32(g_mtime + 4); + lo = getreg32(g_mtime); + } + while (getreg32(g_mtime + 4) != hi); + + return ((uint64_t)hi << 32) | lo; +#endif +} + +void sbi_set_mtimecmp(uint64_t value) +{ + uintptr_t mtimecmp = g_mtimecmp + READ_CSR(mhartid) * sizeof(uintptr_t); +#ifdef CONFIG_ARCH_RV64 + putreg64(value, mtimecmp); +#else + putreg32(UINT32_MAX, mtimecmp + 4); + putreg32(value, mtimecmp); + putreg32(value >> 32, mtimecmp + 4); +#endif + + /* Make sure it sticks */ + + __DMB(); +} diff --git a/arch/risc-v/src/nuttsbi/sbi_mtrap.S b/arch/risc-v/src/nuttsbi/sbi_mtrap.S new file mode 100644 index 00000000000..52809cae0a0 --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_mtrap.S @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_machine_trap.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_macros.S" + +#include "riscv_internal.h" + +#include "sbi_internal.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + +/**************************************************************************** + * Name: machine_trap + * + * Description: + * Machine mode trap handler. Handles Mtimer and simple mcall interface. + * + ****************************************************************************/ + + .section .text + .global machine_trap + .align 8 + +machine_trap: + + /* Switch to M-mode IRQ stack */ + + csrrw sp, mscratch, sp /* mscratch has user stack */ + beqz sp, .Lmtrap /* Detect recursive traps */ + + addi sp, sp, -XCPTCONTEXT_SIZE + save_ctx sp + + csrr a0, mcause /* exception cause */ + + csrrw s0, mscratch, x0 /* read user stack */ + REGSTORE s0, REG_X2(sp) /* original SP */ + + /* Check if this is an exception */ + + bgez a0, .Lmexception + + /* Figure out which interrupt this is */ + + sll a0, a0, 1 /* Shift msbit out */ + li a1, MTIMER_IRQ * 2 /* Machine timer irq ? (shifted left) */ + bne a0, a1, 1f + + /* Delegate interrupt to S-mode handler */ + + li a0, MIP_MTIP + csrc mie, a0 + li a0, MIP_STIP + csrs mip, a0 + +1: + /* Restore mscratch */ + + addi s0, sp, XCPTCONTEXT_SIZE + csrw mscratch, s0 /* original mscratch */ + + /* Restore original context */ + + load_ctx sp + + REGLOAD sp, REG_SP(sp) /* restore original sp */ + + /* Return from Machine Interrupt */ + + mret + +.Lmexception: + + /* Handle exception, only accepted source is ecall */ + + sll a0, a0, 1 + li a1, RISCV_IRQ_ECALLS * 2 + bne a0, a1, .Lmtrap + + /* Handle ecall */ + + mv a0, sp + jal x1, sbi_mcall_handle + csrr a0, mepc + addi a0, a0, 4 + csrw mepc, a0 + j 1b + + /* An unhandled trap to M-mode: this is an error and we cannot proceed */ + +.Lmtrap: + + csrr a0, mcause /* Interrupt cause [arg0] */ + csrr a1, mepc /* Interrupt PC (instruction) [arg1] */ + jal x1, sbi_mexception + j __start + +.Lmtraploop: + + /* If we somehow get here, prevent the software from running away */ + + nop + nop + j .Lmtraploop + +/***************************************************************************** + * Name: m_intstackalloc / m_intstacktop + * + * Description: + * Allocate separate stack(s) for machine mode interrupts, only if kernel + * runs in S-mode. Separate stacks are needed as M-mode interrupts can + * pre-empt S-mode interrupts. + * + ****************************************************************************/ + +#define STACK_ALLOC_SIZE (MMODE_IRQSTACK * CONFIG_SMP_NCPUS) + + .bss + .balign 16 + .global g_mintstackalloc + .global g_mintstacktop + .type g_mintstackalloc, object + .type g_mintstacktop, object +g_mintstackalloc: + .skip STACK_ALIGN_UP(STACK_ALLOC_SIZE) +g_mintstacktop: + .size g_mintstacktop, 0 + .size g_mintstackalloc, STACK_ALIGN_DOWN(STACK_ALLOC_SIZE) diff --git a/arch/risc-v/src/nuttsbi/sbi_start.c b/arch/risc-v/src/nuttsbi/sbi_start.c new file mode 100644 index 00000000000..b968302d03d --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_start.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_start.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 + +#include + +#include "riscv_internal.h" + +#include "sbi_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void __trap_vec_tmp(void) noreturn_function; +static void __trap_vec_tmp(void) +{ + for (; ; ) + { + asm("WFI"); + } +} + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +extern void __start_s(void); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void sbi_start(void) +{ + uintptr_t reg; + uintptr_t hartid; + + /* Read hart ID */ + + hartid = READ_CSR(mhartid); + + /* Set mscratch, mtimer */ + + sbi_mscratch_assign(hartid); + sbi_init_mtimer(MTIMER_TIME_BASE, MTIMER_CMP_BASE); + + /* Setup system to enter S-mode */ + + reg = READ_CSR(mstatus); + reg &= ~MSTATUS_MPPM; /* Clear MPP */ + reg &= ~MSTATUS_MPIE; /* Clear MPIE */ + reg &= ~MSTATUS_TW; /* Do not trap WFI */ + reg &= ~MSTATUS_TSR; /* Do not trap sret */ + reg &= ~MSTATUS_TVM; /* Allow satp writes from S-mode */ + reg |= MSTATUS_SUM; /* Allow supervisor to access user memory */ + reg |= MSTATUS_MPPS; /* Set next context = supervisor */ + + /* Setup next context */ + + WRITE_CSR(mstatus, reg); + + /* Setup a temporary S-mode interrupt vector */ + + WRITE_CSR(stvec, __trap_vec_tmp); + + /* Delegate interrupts */ + + reg = (MIP_SSIP | MIP_STIP | MIP_SEIP); + WRITE_CSR(mideleg, reg); + + /* Delegate exceptions (all of them) */ + + reg = ((1 << RISCV_IRQ_IAMISALIGNED) | + (1 << RISCV_IRQ_INSTRUCTIONPF) | + (1 << RISCV_IRQ_LOADPF) | + (1 << RISCV_IRQ_STOREPF) | + (1 << RISCV_IRQ_ECALLU)); + WRITE_CSR(medeleg, reg); + + /* Enable access to all counters for S- and U-mode */ + + WRITE_CSR(mcounteren, UINT32_C(~0)); + WRITE_CSR(scounteren, UINT32_C(~0)); + + /* Set program counter to __start_s */ + + WRITE_CSR(mepc, __start_s); + + /* Open everything for PMP */ + + WRITE_CSR(pmpaddr0, -1); + WRITE_CSR(pmpcfg0, (PMPCFG_A_NAPOT | PMPCFG_R | PMPCFG_W | PMPCFG_X)); + + /* Then jump to the S-mode start function */ + + register long r0 asm("a0") = (long) hartid; + __asm__ __volatile__("mret" : : "r"(r0)); + + PANIC(); +} diff --git a/arch/risc-v/src/nuttsbi/sbi_vectors.S b/arch/risc-v/src/nuttsbi/sbi_vectors.S new file mode 100644 index 00000000000..90d3f6c804f --- /dev/null +++ b/arch/risc-v/src/nuttsbi/sbi_vectors.S @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/risc-v/src/nuttsbi/sbi_machine_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 __mtrap_vec + +/**************************************************************************** + * Name: __mtrap_vec + * + * Description: + * All M-mode exceptions and interrupts will be handled from here. + * + ****************************************************************************/ + +__mtrap_vec: + j machine_trap + nop