diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index bfc4c66a8e..0e601a1b27 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -19,6 +19,7 @@ config ARCH_CHIP_FE310 config ARCH_CHIP_K210 bool "Kendryte K210" select ARCH_RV64GC + select ARCH_HAVE_MPU select ARCH_HAVE_TESTSET select ARCH_HAVE_MULTICPU select ARCH_GLOBAL_IRQDISABLE diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs index c8dd3cfdf8..8b3032f08d 100644 --- a/arch/risc-v/src/k210/Make.defs +++ b/arch/risc-v/src/k210/Make.defs @@ -35,7 +35,7 @@ HEAD_ASRC = k210_vectors.S # Specify our general Assembly files -CHIP_ASRCS = k210_head.S up_syscall.S +CHIP_ASRCS = k210_head.S CMN_ASRCS += up_testset.S @@ -66,3 +66,11 @@ ifeq ($(CONFIG_SMP), y) CHIP_CSRCS += k210_cpuidlestack.c k210_cpuindex.c CHIP_CSRCS += k210_cpupause.c k210_cpustart.c endif + +ifeq ($(CONFIG_BUILD_PROTECTED),y) +CMN_CSRCS += up_task_start.c up_pthread_start.c +CMN_CSRCS += up_signal_dispatch.c +CMN_UASRCS += up_signal_handler.S + +CHIP_CSRCS += k210_userspace.c +endif diff --git a/arch/risc-v/src/k210/k210_allocateheap.c b/arch/risc-v/src/k210/k210_allocateheap.c index eca9365cb8..e2f420e9bc 100644 --- a/arch/risc-v/src/k210/k210_allocateheap.c +++ b/arch/risc-v/src/k210/k210_allocateheap.c @@ -35,15 +35,64 @@ ****************************************************************************/ #include +#include +#include #include #include "k210.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SRAM1_END CONFIG_RAM_END + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * (and protects) the kernel-space heap. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) +{ + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend; + ubase += CONFIG_MM_KERNEL_HEAPSIZE; + + size_t usize = SRAM1_END - ubase; + + DEBUGASSERT(ubase < (uintptr_t)SRAM1_END); + + /* TODO: Adjust that size to account for MPU alignment requirements. + * NOTE that there is an implicit assumption that the SRAM1_END + * is aligned to the MPU requirement. + */ + + ubase = SRAM1_END - usize; + + /* Return the kernel heap settings (i.e., the part of the heap region + * that was not dedicated to the user heap). + */ + + *heap_start = (FAR void *)USERSPACE->us_bssend; + *heap_size = ubase - (uintptr_t)USERSPACE->us_bssend; +} +#endif + /**************************************************************************** * Name: up_addregion ****************************************************************************/ diff --git a/arch/risc-v/src/k210/k210_irq.c b/arch/risc-v/src/k210/k210_irq.c index 6d064c3153..7812351cb3 100644 --- a/arch/risc-v/src/k210/k210_irq.c +++ b/arch/risc-v/src/k210/k210_irq.c @@ -122,6 +122,10 @@ void up_irqinitialize(void) irq_attach(K210_IRQ_ECALLM, up_swint, NULL); +#ifdef CONFIG_BUILD_PROTECTED + irq_attach(K210_IRQ_ECALLU, up_swint, NULL); +#endif + #ifdef CONFIG_SMP /* Clear MSOFT for CPU0 */ @@ -237,8 +241,12 @@ void up_enable_irq(int irq) uint32_t up_get_newintctx(void) { - /* Set machine previous privilege mode to machine mode. - * Also set machine previous interrupt enable + /* Set machine previous privilege mode to machine mode. Reegardless 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. */ return (MSTATUS_MPPM | MSTATUS_MPIE); diff --git a/arch/risc-v/src/k210/k210_irq_dispatch.c b/arch/risc-v/src/k210/k210_irq_dispatch.c index 04b16f026c..ced4c40e27 100644 --- a/arch/risc-v/src/k210/k210_irq_dispatch.c +++ b/arch/risc-v/src/k210/k210_irq_dispatch.c @@ -70,7 +70,7 @@ void *k210_dispatch_irq(uint64_t vector, uint64_t *regs) /* Check if fault happened */ - if (vector < 11) + if (vector < K210_IRQ_ECALLU) { up_fault((int)irq, regs); } @@ -88,7 +88,7 @@ void *k210_dispatch_irq(uint64_t vector, uint64_t *regs) /* NOTE: In case of ecall, we need to adjust mepc in the context */ - if (K210_IRQ_ECALLM == irq) + if (K210_IRQ_ECALLM == irq || K210_IRQ_ECALLU == irq) { *mepc += 4; } diff --git a/arch/risc-v/src/k210/k210_start.c b/arch/risc-v/src/k210/k210_start.c index f1289f1778..194bbd1eac 100644 --- a/arch/risc-v/src/k210/k210_start.c +++ b/arch/risc-v/src/k210/k210_start.c @@ -41,6 +41,7 @@ #include "up_arch.h" #include "k210_clockconfig.h" +#include "k210_userspace.h" #include "k210.h" #include "chip.h" @@ -137,6 +138,17 @@ void __k210_start(uint32_t mhartid) showprogress('C'); + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + +#ifdef CONFIG_BUILD_PROTECTED + k210_userspace(); + showprogress('D'); +#endif + /* Call nx_start() */ nx_start(); diff --git a/arch/risc-v/src/k210/k210_userspace.c b/arch/risc-v/src/k210/k210_userspace.c new file mode 100644 index 0000000000..00575d23c7 --- /dev/null +++ b/arch/risc-v/src/k210/k210_userspace.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/risc-v/src/k210/k210_userspace.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 "k210_userspace.h" + +#ifdef CONFIG_BUILD_PROTECTED + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k210_userspace + * + * Description: + * For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + * + ****************************************************************************/ + +void k210_userspace(void) +{ + uint8_t *src; + uint8_t *dest; + uint8_t *end; + + /* Clear all of user-space .bss */ + + DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 && + USERSPACE->us_bssstart <= USERSPACE->us_bssend); + + dest = (uint8_t *)USERSPACE->us_bssstart; + end = (uint8_t *)USERSPACE->us_bssend; + + while (dest != end) + { + *dest++ = 0; + } + + /* Initialize all of user-space .data */ + + DEBUGASSERT(USERSPACE->us_datasource != 0 && + USERSPACE->us_datastart != 0 && USERSPACE->us_dataend != 0 && + USERSPACE->us_datastart <= USERSPACE->us_dataend); + + src = (uint8_t *)USERSPACE->us_datasource; + dest = (uint8_t *)USERSPACE->us_datastart; + end = (uint8_t *)USERSPACE->us_dataend; + + while (dest != end) + { + *dest++ = *src++; + } + + /* TODO: + * Configure the MPU to permit user-space access to its FLASH and RAM + */ +} + +#endif /* CONFIG_BUILD_PROTECTED */ diff --git a/arch/risc-v/src/k210/k210_userspace.h b/arch/risc-v/src/k210/k210_userspace.h new file mode 100644 index 0000000000..b184ac263b --- /dev/null +++ b/arch/risc-v/src/k210/k210_userspace.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * arch/risc-v/src/k210/k210_userspace.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_SRC_K210_K210_USERSPACE_H +#define __ARCH_RISCV_SRC_K210_K210_USERSPACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: k210_userspace + * + * Description: + * For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_PROTECTED +void k210_userspace(void); +#endif + +#endif /* __ARCH_RISCV_SRC_K210_K210_USERSPACE_H */ diff --git a/arch/risc-v/src/k210/up_schedulesigaction.c b/arch/risc-v/src/k210/up_schedulesigaction.c index 24f3896aaf..8ab12b681a 100644 --- a/arch/risc-v/src/k210/up_schedulesigaction.c +++ b/arch/risc-v/src/k210/up_schedulesigaction.c @@ -152,13 +152,17 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.saved_int_ctx = CURRENT_REGS[REG_INT_CTX]; /* Then set up to vector to the trampoline with interrupts - * disabled + * disabled. The kernel-space trampoline must run in + * privileged thread mode. */ CURRENT_REGS[REG_EPC] = (uintptr_t)up_sigdeliver; int_ctx = CURRENT_REGS[REG_INT_CTX]; int_ctx &= ~MSTATUS_MIE; +#ifdef CONFIG_BUILD_PROTECTED + int_ctx |= MSTATUS_MPPM; +#endif CURRENT_REGS[REG_INT_CTX] = int_ctx; @@ -192,7 +196,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX]; /* Then set up to vector to the trampoline with interrupts - * disabled + * disabled. We must already be in privileged thread mode to be + * here. */ tcb->xcp.regs[REG_EPC] = (uintptr_t)up_sigdeliver; @@ -324,6 +329,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) int_ctx = CURRENT_REGS[REG_INT_CTX]; int_ctx &= ~MSTATUS_MIE; +#ifdef CONFIG_BUILD_PROTECTED + int_ctx |= MSTATUS_MPPM; +#endif CURRENT_REGS[REG_INT_CTX] = int_ctx;