[PATCH] score: Add _CPU_Use_thread_local_storage()

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 29 13:07:33 UTC 2022


At some point during system initialization, the idle threads are created.
Afterwards, the boot processor basically executes within the context of an idle
thread with thread dispatching disabled.  On some architectures, the
thread-local storage area of the associated thread must be set in dedicated
processor registers.  Add the new CPU port function to do this:

void _CPU_Use_thread_local_storage( const Context_Control *context )

Close #4672.
---
 .../cpu/aarch64/include/rtems/score/cpuimpl.h |  9 +++++++
 .../cpu/arm/include/rtems/score/cpuimpl.h     | 13 ++++++++++
 .../cpu/bfin/include/rtems/score/cpuimpl.h    |  7 +++++
 .../cpu/i386/include/rtems/score/cpuimpl.h    | 26 +++++++++++++++++++
 .../cpu/lm32/include/rtems/score/cpuimpl.h    |  7 +++++
 .../cpu/m68k/include/rtems/score/cpuimpl.h    | 11 ++++++++
 .../microblaze/include/rtems/score/cpuimpl.h  | 11 ++++++++
 .../cpu/mips/include/rtems/score/cpuimpl.h    |  7 +++++
 .../cpu/moxie/include/rtems/score/cpuimpl.h   |  7 +++++
 .../cpu/nios2/include/rtems/score/cpuimpl.h   | 12 +++++++++
 .../cpu/no_cpu/include/rtems/score/cpuimpl.h  | 17 ++++++++++++
 .../cpu/or1k/include/rtems/score/cpuimpl.h    |  7 +++++
 .../cpu/powerpc/include/rtems/score/cpuimpl.h | 16 ++++++++++++
 .../cpu/riscv/include/rtems/score/cpuimpl.h   | 12 +++++++++
 .../cpu/sh/include/rtems/score/cpuimpl.h      |  7 +++++
 .../cpu/sparc/include/rtems/score/cpuimpl.h   | 12 +++++++++
 .../cpu/sparc64/include/rtems/score/cpuimpl.h |  7 +++++
 .../cpu/v850/include/rtems/score/cpuimpl.h    |  7 +++++
 .../cpu/x86_64/include/rtems/score/cpuimpl.h  |  7 +++++
 cpukit/score/src/threadcreateidle.c           |  5 ++++
 testsuites/sptests/sptls01/init.c             | 20 +++++++++++---
 21 files changed, 223 insertions(+), 4 deletions(-)

diff --git a/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h
index ffdef2f30a..14836965ef 100644
--- a/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h
@@ -162,6 +162,15 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  __asm__ volatile (
+    "msr TPIDR_EL0, %0" : : "r" ( context->thread_id ) : "memory"
+  );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h
index 0ce347c86f..4f20113b71 100644
--- a/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h
@@ -160,6 +160,19 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
+  __asm__ volatile (
+    "mcr p15, 0, %0, c13, c0, 3" : : "r" ( context->thread_id ) : "memory"
+  );
+#else
+  (void) context;
+#endif
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h
index 1485abd365..91e57da4a0 100644
--- a/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h
@@ -59,6 +59,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h
index 31ec0ac8bb..71f2679dde 100644
--- a/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h
@@ -80,6 +80,32 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  uint32_t tmp;
+  uint32_t cpu_index;
+
+#ifdef RTEMS_SMP
+  cpu_index = _CPU_SMP_Get_current_processor();
+#else
+  cpu_index = 0;
+#endif
+
+  __asm__ volatile (
+    "movl " RTEMS_XSTRING( I386_CONTEXT_CONTROL_GS_0_OFFSET ) "(%2), %0\n"
+    "movl %0, _Global_descriptor_table+24(,%1,8)\n"
+    "movl " RTEMS_XSTRING( I386_CONTEXT_CONTROL_GS_1_OFFSET ) "(%2), %0\n"
+    "movl %0, _Global_descriptor_table+28(,%1,8)\n"
+    "leal 24(,%1,8), %0\n"
+    "movl %0, %%gs\n"
+    : "=&r" ( tmp )
+    : "r" ( cpu_index ), "r" ( context )
+    : "memory"
+  );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h
index eb0c058723..24e8e5cb41 100644
--- a/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h
@@ -58,6 +58,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h
index e3b61efd9f..5c7c35943a 100644
--- a/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h
@@ -78,6 +78,17 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  /*
+   * There is nothing to do since the thread-local storage area is obtained by
+   * calling __m68k_read_tp().
+   */
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h
index 0573759d52..e4f0303ad8 100644
--- a/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h
@@ -86,6 +86,17 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  /*
+   * There is nothing to do since the thread-local storage area is obtained by
+   * calling __tls_get_addr().
+   */
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h
index 0568134351..23d3f35960 100644
--- a/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h
@@ -78,6 +78,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h
index 038a1326cc..a54824f16b 100644
--- a/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h
@@ -78,6 +78,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h
index 215df68f67..518fac4308 100644
--- a/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h
@@ -70,6 +70,18 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+   register uint32_t r23 __asm__( "r23" );
+
+   r23 = context->r23;
+
+   /* Make sure that the register assignment is not optimized away */
+   __asm__ volatile ( "" : : "r" ( r23 ) );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h
index 6f4abfcfc3..1eec4e6b7a 100644
--- a/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h
@@ -166,6 +166,23 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+/**
+ * @brief Uses the thread-local storage area of the context.
+ *
+ * Some architectures may use dedicated registers to reference the thread-local
+ * storage area of the associated thread.  This function should set these
+ * registers to the values defined by the specified processor context.
+ *
+ * @param context is the processor context defining the thread-local storage
+ *   area to use.
+ */
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h
index 37cd1db436..35d186990d 100644
--- a/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h
@@ -70,6 +70,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "l.nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h
index cfed43ced4..80c8445ff5 100644
--- a/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h
@@ -283,6 +283,22 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+#ifdef __powerpc64__
+   register uintptr_t tp __asm__( "13" );
+#else
+   register uintptr_t tp __asm__( "2" );
+#endif
+
+   tp = context->tp;
+
+   /* Make sure that the register assignment is not optimized away */
+   __asm__ volatile ( "" : : "r" ( tp ) );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
index 5162cbbd51..ca09832d0e 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
@@ -430,6 +430,18 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+   register uintptr_t tp __asm__( "tp" );
+
+   tp = context->tp;
+
+   /* Make sure that the register assignment is not optimized away */
+   __asm__ volatile ( "" : : "r" ( tp ) );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h
index 745a185d1a..cb20bab616 100644
--- a/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h
@@ -59,6 +59,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
index 7197eb960e..2a200be7e3 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
@@ -234,6 +234,18 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+   register uint32_t g7 __asm__( "g7" );
+
+   g7 = context->g7;
+
+   /* Make sure that the register assignment is not optimized away */
+   __asm__ volatile ( "" : : "r" ( g7 ) );
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h
index c026687d01..23aed1a8d6 100644
--- a/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h
@@ -78,6 +78,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h
index 23c1437ba0..8f73b45ad6 100644
--- a/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h
@@ -78,6 +78,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h
index d3a4b848e6..680c61ae20 100644
--- a/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h
@@ -62,6 +62,13 @@ RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
   __asm__ volatile ( "nop" );
 }
 
+RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
+  const Context_Control *context
+)
+{
+  (void) context;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index 9f3c01d118..be3cbca842 100644
--- a/cpukit/score/src/threadcreateidle.c
+++ b/cpukit/score/src/threadcreateidle.c
@@ -40,6 +40,7 @@
 #endif
 
 #include <rtems/score/threadidledata.h>
+#include <rtems/score/cpuimpl.h>
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/assert.h>
 #include <rtems/score/schedulerimpl.h>
@@ -124,4 +125,8 @@ void _Thread_Create_idle( void )
       _Thread_Create_idle_for_CPU( cpu );
     }
   }
+
+  _CPU_Use_thread_local_storage(
+    &_Per_CPU_Get_executing( _Per_CPU_Get() )->Registers
+  );
 }
diff --git a/testsuites/sptests/sptls01/init.c b/testsuites/sptests/sptls01/init.c
index 5b5d274d3c..efd0fb4c6c 100644
--- a/testsuites/sptests/sptls01/init.c
+++ b/testsuites/sptests/sptls01/init.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 
 /*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (C) 2014, 2022 embedded brains GmbH
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,7 +29,8 @@
 #include "config.h"
 #endif
 
-#include <stdio.h>
+#include <rtems/bspIo.h>
+#include <rtems/sysinit.h>
 
 #include "tmacros.h"
 
@@ -45,7 +46,7 @@ static const volatile uint32_t read_only_small = 0x601dc0feUL;
 
 static void check_tls_item(uint32_t expected)
 {
-  printf("TLS item = %i\n", tls_item);
+  printk("TLS item = %i\n", tls_item);
   rtems_test_assert(tls_item == expected);
 }
 
@@ -97,10 +98,15 @@ static void test(void)
   check_tls_item(5);
 }
 
-static void Init(rtems_task_argument arg)
+static void test_idle_during_system_init(void)
 {
   TEST_BEGIN();
 
+  check_tls_item(123);
+}
+
+static void Init(rtems_task_argument arg)
+{
   test();
 
   TEST_END();
@@ -108,6 +114,12 @@ static void Init(rtems_task_argument arg)
   rtems_test_exit(0);
 }
 
+RTEMS_SYSINIT_ITEM(
+  test_idle_during_system_init,
+  RTEMS_SYSINIT_IDLE_THREADS,
+  RTEMS_SYSINIT_ORDER_LAST
+);
+
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
 
-- 
2.35.3



More information about the devel mailing list