This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 8b86f5de60 arch/x86_64: add support for thread_local
8b86f5de60 is described below

commit 8b86f5de608f80423a7258efe78fa2d68200a7c9
Author: liwenxiang1 <[email protected]>
AuthorDate: Wed Oct 9 15:28:49 2024 +0800

    arch/x86_64: add support for thread_local
    
    Signed-off-by: liwenxiang1 <[email protected]>
---
 arch/Kconfig                                       |  1 +
 arch/x86_64/src/common/CMakeLists.txt              |  4 ++
 arch/x86_64/src/common/Make.defs                   |  4 ++
 arch/x86_64/src/common/x86_64_internal.h           | 18 ++++++
 arch/x86_64/src/common/x86_64_tls.c                | 71 ++++++++++++++++++++++
 .../src/intel64/intel64_fullcontextrestore.S       |  8 ++-
 arch/x86_64/src/intel64/intel64_initialstate.c     | 23 ++++++-
 .../intel64/qemu-intel64/configs/nsh/defconfig     |  1 +
 boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld | 15 +++++
 9 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 3beab388c2..9237150062 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -138,6 +138,7 @@ config ARCH_X86_64
        select ARCH_HAVE_TESTSET
        select ARCH_HAVE_INTERRUPTSTACK
        select ARCH_HAVE_CUSTOMOPT
+       select ARCH_HAVE_THREAD_LOCAL
        select PCI_LATE_DRIVERS_REGISTER if PCI
        select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF
        select ARCH_TOOLCHAIN_GNU
diff --git a/arch/x86_64/src/common/CMakeLists.txt 
b/arch/x86_64/src/common/CMakeLists.txt
index 3ee09cfdb1..51570e536f 100644
--- a/arch/x86_64/src/common/CMakeLists.txt
+++ b/arch/x86_64/src/common/CMakeLists.txt
@@ -45,6 +45,10 @@ if(CONFIG_ARCH_X86_64_ACPI)
   list(APPEND SRCS x86_64_acpi.c)
 endif()
 
+if(CONFIG_SCHED_THREAD_LOCAL)
+  list(APPEND SRCS x86_64_tls.c)
+endif()
+
 if(CONFIG_ARCH_USE_MMU)
   list(APPEND SRCS x86_64_mmu.c)
 endif()
diff --git a/arch/x86_64/src/common/Make.defs b/arch/x86_64/src/common/Make.defs
index 3c2db5bf01..e18caaa270 100644
--- a/arch/x86_64/src/common/Make.defs
+++ b/arch/x86_64/src/common/Make.defs
@@ -38,6 +38,10 @@ ifeq ($(CONFIG_ARCH_X86_64_ACPI),y)
 CMN_CSRCS += x86_64_acpi.c
 endif
 
+ifeq ($(CONFIG_SCHED_THREAD_LOCAL),y)
+CMN_CSRCS += x86_64_tls.c
+endif
+
 ifeq ($(CONFIG_ARCH_USE_MMU),y)
 CMN_CSRCS += x86_64_mmu.c
 endif
diff --git a/arch/x86_64/src/common/x86_64_internal.h 
b/arch/x86_64/src/common/x86_64_internal.h
index 0a34222b4e..d4089f11b4 100644
--- a/arch/x86_64/src/common/x86_64_internal.h
+++ b/arch/x86_64/src/common/x86_64_internal.h
@@ -134,6 +134,20 @@
 #  define IRQ_STACK_SIZE CONFIG_ARCH_INTERRUPTSTACK
 #endif
 
+/* Linker defined section addresses */
+
+#define _START_TEXT  _stext
+#define _END_TEXT    _etext
+#define _START_BSS   _sbss
+#define _END_BSS     _ebss
+#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
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -171,6 +185,10 @@ extern uint8_t _sdata[];           /* Start of .data */
 extern uint8_t _edata[];           /* End+1 of .data */
 extern uint8_t _sbss[];            /* Start of .bss */
 extern uint8_t _ebss[];            /* End+1 of .bss */
+extern uint8_t _stdata[];          /* Start of .tdata */
+extern uint8_t _etdata[];          /* End+1 of .tdata */
+extern uint8_t _stbss[];           /* Start of .tbss */
+extern uint8_t _etbss[];           /* End+1 of .tbss */
 #endif
 
 /****************************************************************************
diff --git a/arch/x86_64/src/common/x86_64_tls.c 
b/arch/x86_64/src/common/x86_64_tls.c
new file mode 100644
index 0000000000..1a0c32b045
--- /dev/null
+++ b/arch/x86_64/src/common/x86_64_tls.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * arch/x86_64/src/common/x86_64_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 <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/tls.h>
+
+#include "x86_64_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) +
+         _END_TBSS - _START_TDATA + sizeof(void *);
+}
+
+/****************************************************************************
+ * Name: up_tls_initialize
+ *
+ * Description:
+ *   Initialize thread local region.
+ *
+ * Input Parameters:
+ *   info - The TLS structure to initialize.
+ *
+ ****************************************************************************/
+
+void up_tls_initialize(struct tls_info_s *info)
+{
+  uint8_t  *tls_data  = (uint8_t *)(info + 1);
+  uint32_t  tdata_len = _END_TDATA - _START_TDATA;
+  uint32_t  tbss_len  = _END_TBSS - _START_TBSS;
+
+  memcpy(tls_data, _START_TDATA, tdata_len);
+  memset(tls_data + tdata_len, 0, tbss_len);
+}
diff --git a/arch/x86_64/src/intel64/intel64_fullcontextrestore.S 
b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
index d52b7da744..55b1ee871d 100644
--- a/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
+++ b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
@@ -108,7 +108,6 @@ x86_64_fullcontextrestore:
        movq    (8*REG_R10)(%rdi), %r10
        movq    (8*REG_RBP)(%rdi), %rbp
        movq    (8*REG_RBX)(%rdi), %rbx
-       movq    (8*REG_RAX)(%rdi), %rax
 
        /* Restore the data segment register.  I think there is an issue that 
will
        * need to be address here at some time:  If the register save area is in
@@ -124,6 +123,13 @@ x86_64_fullcontextrestore:
        * XXX: Should use wrgsbase and wrfsbase to restore the gs and fs 
register
        */
 
+#ifdef CONFIG_SCHED_THREAD_LOCAL
+       mov     (8*REG_FS)(%rdi), %rax
+       wrfsbase  %rax
+#endif
+
+       movq    (8*REG_RAX)(%rdi), %rax
+
        /* Restore the correct value of EAX and then return */
 
        popq    %rdi
diff --git a/arch/x86_64/src/intel64/intel64_initialstate.c 
b/arch/x86_64/src/intel64/intel64_initialstate.c
index 1c482fccbe..0b0ad138f5 100644
--- a/arch/x86_64/src/intel64/intel64_initialstate.c
+++ b/arch/x86_64/src/intel64/intel64_initialstate.c
@@ -30,6 +30,10 @@
 #include <nuttx/arch.h>
 #include <arch/arch.h>
 
+#ifdef CONFIG_SCHED_THREAD_LOCAL
+#  include <nuttx/tls.h>
+#endif
+
 #include "x86_64_internal.h"
 #include "sched/sched.h"
 
@@ -132,12 +136,25 @@ void up_initial_state(struct tcb_s *tcb)
   xcp->regs[REG_SS]     = up_getss();
   xcp->regs[REG_ES]     = up_getes();
 
-  /* Aux GS and FS are set to be 0 */
+/* FS used by for TLS
+ * used by some libc for TLS and segment reference
+ */
 
-  /* used by some libc for TLS and segment reference */
+#ifdef CONFIG_SCHED_THREAD_LOCAL
+  xcp->regs[REG_FS]     = (uintptr_t)tcb->stack_alloc_ptr
+                          + sizeof(struct tls_info_s)
+                          + (_END_TBSS - _START_TDATA);
 
-  xcp->regs[REG_GS]     = 0;
+  *(uint64_t *)(xcp->regs[REG_FS]) = xcp->regs[REG_FS];
+
+  write_fsbase(xcp->regs[REG_FS]);
+#else
   xcp->regs[REG_FS]     = 0;
+#endif
+
+  /* GS used for CPU private data */
+
+  xcp->regs[REG_GS]     = 0;
 
   /* Set supervisor- or user-mode, depending on how NuttX is configured and
    * what kind of thread is being started.  Disable FIQs in any event
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/nsh/defconfig 
b/boards/x86_64/intel64/qemu-intel64/configs/nsh/defconfig
index b1e799c472..53b3678530 100644
--- a/boards/x86_64/intel64/qemu-intel64/configs/nsh/defconfig
+++ b/boards/x86_64/intel64/qemu-intel64/configs/nsh/defconfig
@@ -45,6 +45,7 @@ CONFIG_PTHREAD_STACK_MIN=4194304
 CONFIG_RAM_SIZE=268435456
 CONFIG_SCHED_CHILD_STATUS=y
 CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_THREAD_LOCAL=y
 CONFIG_SCHED_TICKLESS=y
 CONFIG_SCHED_TICKLESS_ALARM=y
 CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
diff --git a/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld 
b/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld
index df9abc7f1c..85351ae7f7 100644
--- a/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld
+++ b/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld
@@ -48,6 +48,11 @@ SECTIONS
         *(.loader.rodata)
     }
 
+    .loader.tdata_tbss : {
+        *(.loader.tdata)
+        *(.loader.tbss)
+    }
+
     .loader.data : {
         *(.loader.data)
     }
@@ -89,6 +94,16 @@ SECTIONS
         _erodata = ABSOLUTE(.);
     }
 
+    .tdata_tbss ALIGN(0x1000) :
+    {
+        _stdata = ABSOLUTE(.);
+        *(.tdata .tdata.* .gnu.linkonce.td.*);
+        _etdata = ABSOLUTE(.);
+        _stbss = ABSOLUTE(.);
+        *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
+        _etbss = ABSOLUTE(.);
+    }
+
     .data ALIGN(0x1000) :
     {
         _sdata = ABSOLUTE(.);

Reply via email to