diff --git a/arch/Kconfig b/arch/Kconfig index 127ca685326..557f31a182e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -65,6 +65,7 @@ config ARCH_RISCV select ARCH_HAVE_STDARG_H select ARCH_HAVE_SYSCALL_HOOKS select ARCH_HAVE_RDWR_MEM_CPU_RUN + select ARCH_HAVE_THREAD_LOCAL ---help--- RISC-V 32 and 64-bit RV32 / RV64 architectures. diff --git a/arch/risc-v/include/rv32im/irq.h b/arch/risc-v/include/rv32im/irq.h index 62b39566636..8f94dfabeba 100644 --- a/arch/risc-v/include/rv32im/irq.h +++ b/arch/risc-v/include/rv32im/irq.h @@ -56,7 +56,7 @@ #define REG_X1_NDX 1 -/* $2: Stack POinter +/* $2: Stack Pointer * $3: Global Pointer * $4: Thread Pointer */ diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index dbea140ec3c..87ff92aaba3 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -64,6 +64,10 @@ #define _DATA_INIT &_eronly #define _START_DATA &_sdata #define _END_DATA &_edata +#define _START_TDATA &_stdata +#define _END_TDATA &_etdata +#define _START_TBSS &_stbss +#define _END_TBSS &_etbss /* Determine which (if any) console driver to use. If a console is enabled * and no other console device is specified, then a serial console is @@ -138,6 +142,10 @@ EXTERN uint32_t _sdata; /* Start of .data */ EXTERN uint32_t _edata; /* End+1 of .data */ EXTERN uint32_t _sbss; /* Start of .bss */ EXTERN uint32_t _ebss; /* End+1 of .bss */ +EXTERN uint32_t _stdata; /* Start of .tdata */ +EXTERN uint32_t _etdata; /* End+1 of .tdata */ +EXTERN uint32_t _stbss; /* Start of .tbss */ +EXTERN uint32_t _etbss; /* End+1 of .tbss */ #endif /* __ASSEMBLY__ */ diff --git a/arch/risc-v/src/common/riscv_tls.c b/arch/risc-v/src/common/riscv_tls.c new file mode 100644 index 00000000000..64c1854f677 --- /dev/null +++ b/arch/risc-v/src/common/riscv_tls.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_tls.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" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_tls_size + * + * Description: + * Get TLS (sizeof(struct tls_info_s) + tdata + tbss) section size. + * + * Returned Value: + * Size of (sizeof(struct tls_info_s) + tdata + tbss). + * + ****************************************************************************/ + +int up_tls_size(void) +{ + return sizeof(struct tls_info_s) + + sizeof(uint32_t) * (_END_TBSS - _START_TDATA); +} + +/**************************************************************************** + * Name: up_tls_initialize + * + * Description: + * Initialize thread local region. + * + * Input Parameters: + * info - The TLS structure to initialize. + * + ****************************************************************************/ + +void up_tls_initialize(FAR struct tls_info_s *info) +{ + FAR uint8_t *tls_data = info->tl_data; + + uint32_t tdata_len = sizeof(uint32_t) * (_END_TDATA - _START_TDATA); + uint32_t tbss_len = sizeof(uint32_t) * (_END_TBSS - _START_TBSS); + + memcpy(tls_data, _START_TDATA, tdata_len); + memset(tls_data + tdata_len, 0, tbss_len); +} diff --git a/arch/risc-v/src/qemu-rv32/Make.defs b/arch/risc-v/src/qemu-rv32/Make.defs index cb579f96e0b..30677bb30f5 100644 --- a/arch/risc-v/src/qemu-rv32/Make.defs +++ b/arch/risc-v/src/qemu-rv32/Make.defs @@ -42,6 +42,10 @@ ifeq ($(CONFIG_ARCH_HAVE_VFORK),y) CMN_CSRCS += riscv_vfork.c endif +ifeq ($(CONFIG_SCHED_THREAD_LOCAL),y) +CMN_CSRCS += riscv_tls.c +endif + # Specify our C code within this directory to be included CHIP_CSRCS = qemu_rv32_start.c qemu_rv32_irq_dispatch.c qemu_rv32_irq.c CHIP_CSRCS += qemu_rv32_idle.c qemu_rv32_timerisr.c diff --git a/arch/risc-v/src/rv32im/riscv_initialstate.c b/arch/risc-v/src/rv32im/riscv_initialstate.c index 55983a24741..24b965e7804 100644 --- a/arch/risc-v/src/rv32im/riscv_initialstate.c +++ b/arch/risc-v/src/rv32im/riscv_initialstate.c @@ -55,6 +55,11 @@ void up_initial_state(struct tcb_s *tcb) { struct xcptcontext *xcp = &tcb->xcp; + +#ifdef CONFIG_SCHED_THREAD_LOCAL + struct tls_info_s *info = tcb->stack_alloc_ptr; +#endif + uint32_t regval; /* Initialize the idle thread stack */ @@ -93,6 +98,12 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_EPC] = (uint32_t)tcb->start; + /* Setup thread local storage pointer */ + +#ifdef CONFIG_SCHED_THREAD_LOCAL + xcp->regs[REG_TP] = (uint32_t)info->tl_data; +#endif + /* If this task is running PIC, then set the PIC base register to the * address of the allocated D-Space region. */ diff --git a/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script b/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script index 929e66c14e5..c0d6d83cca1 100644 --- a/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script +++ b/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script @@ -53,6 +53,18 @@ SECTIONS _erodata = . ; } + .tdata : { + _stdata = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*); + _etdata = ABSOLUTE(.); + } + + .tbss : { + _stbss = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon); + _etbss = ABSOLUTE(.); + } + _eronly = ABSOLUTE(.); .data :