Index: bsps/powerpc/shared/cpu.c
===================================================================
--- bsps/powerpc/shared/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ bsps/powerpc/shared/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -131,5 +131,5 @@
 
   if ( tls_area != NULL ) {
-    void *tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area );
+    void *tls_block = _TLS_Initialize_area( tls_area );
 
     the_ppc_context->tp = (uintptr_t) tls_block + 0x7000;
Index: cpukit/include/rtems/score/tls.h
===================================================================
--- cpukit/include/rtems/score/tls.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/include/rtems/score/tls.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -11,5 +11,5 @@
 
 /*
- * 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
@@ -38,5 +38,5 @@
 #define _RTEMS_SCORE_TLS_H
 
-#include <rtems/score/cpu.h>
+#include <rtems/score/cpuimpl.h>
 
 #include <string.h>
@@ -117,7 +117,7 @@
 
 /**
- * @brief Gets the TLS size.
- *
- * @return The TLS size.
+ * @brief Gets the size of the thread-local storage data in bytes.
+ *
+ * @return Returns the size of the thread-local storage data in bytes.
  */
 static inline uintptr_t _TLS_Get_size( void )
@@ -136,80 +136,62 @@
 
 /**
- * @brief Returns the value aligned up to the stack alignment.
- *
- * @param val The value to align.
- *
- * @return The value aligned to the stack alignment.
- */
-static inline uintptr_t _TLS_Align_up( uintptr_t val )
-{
-  uintptr_t alignment = CPU_STACK_ALIGNMENT;
-
-  return RTEMS_ALIGN_UP( val, alignment );
-}
-
-/**
- * @brief Returns the size of the thread control block area size for this
- *      alignment, or the minimum size if alignment is too small.
- *
- * @param alignment The alignment for the operation.
- *
- * @return The size of the thread control block area.
- */
-static inline uintptr_t _TLS_Get_thread_control_block_area_size(
-  uintptr_t alignment
-)
-{
-  return alignment <= sizeof(TLS_Thread_control_block) ?
-    sizeof(TLS_Thread_control_block) : alignment;
-}
-
-/**
- * @brief Return the TLS area allocation size.
- *
- * @return The TLS area allocation size.
+ * @brief Gets the size of the thread control block area in bytes.
+ *
+ * @return Returns the size of the thread control block area in bytes.
+ */
+static inline uintptr_t _TLS_Get_thread_control_block_area_size( void )
+{
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
+  uintptr_t alignment;
+
+  alignment = (uintptr_t) _TLS_Alignment;
+
+  return RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), alignment );
+#else
+  return sizeof( TLS_Thread_control_block );
+#endif
+}
+
+/**
+ * @brief Gets the allocation size of the thread-local storage area in bytes.
+ *
+ * @return Returns the allocation size of the thread-local storage area in
+ *   bytes.
  */
 uintptr_t _TLS_Get_allocation_size( void );
 
 /**
- * @brief Copies TLS size bytes from the address tls_area and returns a pointer
- *      to the start of the area after clearing it.
- *
- * @param tls_area The starting address of the area to clear.
- *
- * @return The pointer to the beginning of the cleared section.
- */
-static inline void *_TLS_Copy_and_clear( void *tls_area )
-{
-  tls_area = memcpy(
-    tls_area,
+ * @brief Initializes the thread-local storage data.
+ *
+ * @param[out] tls_data is the thread-local storage data to initialize.
+ */
+static inline void _TLS_Copy_and_clear( void *tls_data )
+{
+  tls_data = memcpy(
+    tls_data,
     _TLS_Data_begin,
     (size_t) ((uintptr_t)_TLS_Data_size)
   );
 
-
   memset(
-    (char *) tls_area + (size_t)((intptr_t) _TLS_BSS_begin) -
+    (char *) tls_data + (size_t)((intptr_t) _TLS_BSS_begin) -
       (size_t)((intptr_t) _TLS_Data_begin),
     0,
     ((size_t) (intptr_t)_TLS_BSS_size)
   );
-
-  return tls_area;
-}
-
-/**
- * @brief Initializes the dynamic thread vector.
- *
- * @param tls_block The tls block for @a dtv.
- * @param tcb The thread control block for @a dtv.
- * @param[out] dtv The dynamic thread vector to initialize.
- *
- * @return Pointer to an area that was copied and cleared from tls_block
- *       onwards (@see _TLS_Copy_and_clear).
- */
-static inline void *_TLS_Initialize(
-  void *tls_block,
-  TLS_Thread_control_block *tcb,
+}
+
+/**
+ * @brief Initializes the thread control block and the dynamic thread vector.
+ *
+ * @param tls_data is the thread-local storage data address.
+ *
+ * @param[out] tcb is the thread control block to initialize.
+ *
+ * @param[out] dtv is the dynamic thread vector to initialize.
+ */
+static inline void _TLS_Initialize_TCB_and_DTV(
+  void                      *tls_data,
+  TLS_Thread_control_block  *tcb,
   TLS_Dynamic_thread_vector *dtv
 )
@@ -221,84 +203,68 @@
   tcb->dtv = dtv;
   dtv->generation_number = 1;
-  dtv->tls_blocks[0] = tls_block;
-#endif
-
-  return _TLS_Copy_and_clear( tls_block );
-}
-
-/**
- * @brief Initializes a dynamic thread vector beginning at the given starting
- *      address.
- *
- * Use Variant I, TLS offsets emitted by linker takes the TCB into account.
- *
- * @param tls_area The tls area for the initialization.
- *
- * @return Pointer to an area that was copied and cleared from tls_block
- *       onwards (@see _TLS_Copy_and_clear).
- */
-static inline void *_TLS_TCB_at_area_begin_initialize( void *tls_area )
-{
-  void *tls_block = (char *) tls_area
-    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
-  TLS_Thread_control_block *tcb = (TLS_Thread_control_block *) tls_area;
-  uintptr_t aligned_size = _TLS_Align_up( (uintptr_t) _TLS_Size );
-  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
-    ((char *) tls_block + aligned_size);
-
-  return _TLS_Initialize( tls_block, tcb, dtv );
-}
-
-/**
- * @brief Initializes a dynamic thread vector with the area before a given
- * starting address as thread control block.
- *
- * Use Variant I, TLS offsets emitted by linker neglects the TCB.
- *
- * @param tls_area The tls area for the initialization.
- *
- * @return Pointer to an area that was copied and cleared from tls_block
- *       onwards (@see _TLS_Copy_and_clear).
- */
-static inline void *_TLS_TCB_before_TLS_block_initialize( void *tls_area )
-{
-  void *tls_block = (char *) tls_area
-    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
-  TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
-    ((char *) tls_block - sizeof(*tcb));
-  uintptr_t aligned_size = _TLS_Align_up( (uintptr_t) _TLS_Size );
-  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
-    ((char *) tls_block + aligned_size);
-
-  return _TLS_Initialize( tls_block, tcb, dtv );
-}
-
-/**
- * @brief Initializes a dynamic thread vector with the area after a given
- * starting address as thread control block.
- *
- * Use Variant II
- *
- * @param tls_area The tls area for the initialization.
- *
- * @return Pointer to an area that was copied and cleared from tls_block
- *       onwards (@see _TLS_Copy_and_clear).
- */
-static inline void *_TLS_TCB_after_TLS_block_initialize( void *tls_area )
-{
-  uintptr_t size = (uintptr_t) _TLS_Size;
-  uintptr_t tls_align = (uintptr_t) _TLS_Alignment;
-  uintptr_t tls_mask = tls_align - 1;
-  uintptr_t heap_align = _TLS_Align_up( tls_align );
-  uintptr_t heap_mask = heap_align - 1;
-  TLS_Thread_control_block *tcb = (TLS_Thread_control_block *)
-    ((char *) tls_area + ((size + heap_mask) & ~heap_mask));
-  void *tls_block = (char *) tcb - ((size + tls_mask) & ~tls_mask);
-  TLS_Dynamic_thread_vector *dtv = (TLS_Dynamic_thread_vector *)
-    ((char *) tcb + sizeof(*tcb));
-
-  _TLS_Initialize( tls_block, tcb, dtv );
-
-  return tcb;
+  dtv->tls_blocks[0] = tls_data;
+#endif
+}
+
+/**
+ * @brief Initializes the thread-local storage area.
+ *
+ * @param tls_area[out] is the thread-local storage area to initialize.
+ *
+ * @return Where the architectures uses Variant I and the TLS offsets emitted
+ *   by the linker neglect the TCB, returns the address of the thread-local
+ *   storage data.  Otherwise, returns the address of the thread control block.
+ */
+static inline void *_TLS_Initialize_area( void *tls_area )
+{
+  uintptr_t                  alignment;
+  void                      *tls_data;
+  TLS_Thread_control_block  *tcb;
+  TLS_Dynamic_thread_vector *dtv;
+  void                      *return_value;
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
+  uintptr_t                  tcb_size;
+#endif
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20
+  uintptr_t                  size;
+  uintptr_t                  alignment_2;
+#endif
+
+  alignment = (uintptr_t) _TLS_Alignment;
+
+#ifdef __i386__
+  dtv = NULL;
+#else
+  dtv = (TLS_Dynamic_thread_vector *) tls_area;
+  tls_area = (char *) tls_area + sizeof( *dtv );
+#endif
+
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 10
+  tls_data = (void *)
+    RTEMS_ALIGN_UP( (uintptr_t) tls_area + sizeof( *tcb ), alignment );
+  tcb = (TLS_Thread_control_block *) ((char *) tls_data - sizeof( *tcb ));
+  return_value = tls_data;
+#elif CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
+  tcb_size = RTEMS_ALIGN_UP( sizeof( *tcb ), alignment );
+  tls_data = (void *)
+    RTEMS_ALIGN_UP( (uintptr_t) tls_area + tcb_size, alignment );
+  tcb = (TLS_Thread_control_block *) ((char *) tls_data - tcb_size);
+  return_value = tcb;
+#elif CPU_THREAD_LOCAL_STORAGE_VARIANT == 20
+  alignment_2 = RTEMS_ALIGN_UP( alignment, CPU_SIZEOF_POINTER );
+  tls_area = (void *) RTEMS_ALIGN_UP( (uintptr_t) tls_area, alignment_2 );
+  size = _TLS_Get_size();
+  tcb = (TLS_Thread_control_block *)
+    ((char *) tls_area + RTEMS_ALIGN_UP( size, alignment_2 ));
+  tls_data = (char *) tcb - RTEMS_ALIGN_UP( size, alignment );
+  return_value = tcb;
+#else
+#error "unexpected CPU_THREAD_LOCAL_STORAGE_VARIANT value"
+#endif
+
+  _TLS_Initialize_TCB_and_DTV( tls_data, tcb, dtv );
+  _TLS_Copy_and_clear( tls_data );
+
+  return return_value;
 }
 
Index: cpukit/score/cpu/aarch64/cpu.c
===================================================================
--- cpukit/score/cpu/aarch64/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/aarch64/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -143,5 +143,5 @@
 
   if ( tls_area != NULL ) {
-    _TLS_TCB_at_area_begin_initialize( tls_area );
+    the_context->thread_id = (uintptr_t) _TLS_Initialize_area( tls_area );
   }
 }
Index: cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/aarch64/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -51,5 +51,8 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
 #define CPU_INTERRUPT_FRAME_SIZE 0x2E0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 11
 
 #ifndef ASM
Index: cpukit/score/cpu/arm/__aeabi_read_tp.c
===================================================================
--- cpukit/score/cpu/arm/__aeabi_read_tp.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/__aeabi_read_tp.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -43,13 +43,13 @@
     "ldr r0, [r0, %[executingoff]]\n"
 #if defined(__thumb__) && !defined(__thumb2__)
-    "add r0, %[tlsareaoff]\n"
+    "add r0, %[threadidoff]\n"
     "ldr r0, [r0]\n"
 #else
-    "ldr r0, [r0, %[tlsareaoff]]\n"
+    "ldr r0, [r0, %[threadidoff]]\n"
 #endif
     "bx lr\n"
     :
     : [executingoff] "I" (offsetof(Per_CPU_Control, executing)),
-      [tlsareaoff] "I" (offsetof(Thread_Control, Start.tls_area))
+      [threadidoff] "I" (offsetof(Thread_Control, Registers.thread_id))
   );
 }
Index: cpukit/score/cpu/arm/__tls_get_addr.c
===================================================================
--- cpukit/score/cpu/arm/__tls_get_addr.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/__tls_get_addr.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -40,9 +40,9 @@
 {
   const Thread_Control *executing = _Thread_Get_executing();
-  void *tls_block = (char *) executing->Start.tls_area
-    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
+  void *tls_data = (char *) executing->Registers.thread_id
+    + _TLS_Get_thread_control_block_area_size();
 
   assert(ti->module == 1);
 
-  return (char *) tls_block + ti->offset;
+  return (char *) tls_data + ti->offset;
 }
Index: cpukit/score/cpu/arm/armv7m-context-initialize.c
===================================================================
--- cpukit/score/cpu/arm/armv7m-context-initialize.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/armv7m-context-initialize.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -62,5 +62,5 @@
 
   if ( tls_area != NULL ) {
-    _TLS_TCB_at_area_begin_initialize( tls_area );
+    _TLS_Initialize_area( tls_area );
   }
 }
Index: cpukit/score/cpu/arm/cpu.c
===================================================================
--- cpukit/score/cpu/arm/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -57,11 +57,9 @@
 #endif
 
-#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
-  RTEMS_STATIC_ASSERT(
-    offsetof( Context_Control, thread_id )
-      == ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET,
-    ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET
-  );
-#endif
+RTEMS_STATIC_ASSERT(
+  offsetof( Context_Control, thread_id )
+    == ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET,
+  ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET
+);
 
 #ifdef ARM_MULTILIB_ARCH_V4
@@ -119,11 +117,8 @@
   the_context->register_lr = (uint32_t) entry_point;
   the_context->isr_dispatch_disable = 0;
-
-#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
   the_context->thread_id = (uint32_t) tls_area;
-#endif
 
   if ( tls_area != NULL ) {
-    _TLS_TCB_at_area_begin_initialize( tls_area );
+    the_context->thread_id = (uint32_t) _TLS_Initialize_area( tls_area );
   }
 }
Index: cpukit/score/cpu/arm/include/rtems/score/cpu.h
===================================================================
--- cpukit/score/cpu/arm/include/rtems/score/cpu.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/include/rtems/score/cpu.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -177,7 +177,5 @@
 #define CPU_MAXIMUM_PROCESSORS 32
 
-#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
-  #define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
-#endif
+#define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
 
 #ifdef ARM_MULTILIB_VFP
@@ -192,8 +190,6 @@
   #if defined(ARM_MULTILIB_VFP)
     #define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 112
-  #elif defined(ARM_MULTILIB_HAS_THREAD_ID_REGISTER)
+  #else
     #define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 48
-  #else
-    #define ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 44
   #endif
 #endif
@@ -241,7 +237,5 @@
   void *register_sp;
 #endif
-#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
   uint32_t thread_id;
-#endif
 #ifdef ARM_MULTILIB_VFP
   uint64_t register_d8;
Index: cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/arm/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -60,4 +60,6 @@
 
 #endif /* ARM_MULTILIB_ARCH_V4 */
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 11
 
 #ifndef ASM
Index: cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/bfin/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -29,4 +29,6 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #ifndef ASM
Index: cpukit/score/cpu/i386/cpu.c
===================================================================
--- cpukit/score/cpu/i386/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/i386/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -194,5 +194,5 @@
 
   if ( tls_area != NULL ) {
-    tcb = (uint32_t) _TLS_TCB_after_TLS_block_initialize( tls_area );
+    tcb = (uint32_t) _TLS_Initialize_area( tls_area );
   } else {
     tcb = 0;
Index: cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/i386/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -50,4 +50,6 @@
 
 #define CPU_INTERRUPT_FRAME_SIZE 52
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
 
 #ifndef ASM
Index: cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/lm32/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -28,4 +28,6 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #ifndef ASM
Index: cpukit/score/cpu/m68k/__m68k_read_tp.c
===================================================================
--- cpukit/score/cpu/m68k/__m68k_read_tp.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/m68k/__m68k_read_tp.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -38,7 +38,5 @@
 {
   const Thread_Control *executing = _Thread_Get_executing();
-  void *tp = (char *) executing->Start.tls_area +
-    _TLS_Get_thread_control_block_area_size((uintptr_t) _TLS_Alignment)
-    + 0x7000;
+  void *tp = executing->Registers.thread_pointer;
 
   __asm__ volatile (
Index: cpukit/score/cpu/m68k/cpu.c
===================================================================
--- cpukit/score/cpu/m68k/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/m68k/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -280,5 +280,8 @@
 
   if ( tls_area != NULL ) {
-    _TLS_TCB_before_TLS_block_initialize( tls_area );
+    the_context->thread_pointer =
+      (char *) _TLS_Initialize_area( tls_area ) + 0x7000;
+  } else {
+    the_context->thread_pointer = NULL;
   }
 }
Index: cpukit/score/cpu/m68k/include/rtems/score/cpu.h
===================================================================
--- cpukit/score/cpu/m68k/include/rtems/score/cpu.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/m68k/include/rtems/score/cpu.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -146,4 +146,5 @@
     uint8_t   fpu_dis;
   #endif
+  void       *thread_pointer;
 } Context_Control;
 
Index: cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/m68k/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -48,4 +48,6 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #ifndef ASM
Index: cpukit/score/cpu/microblaze/__tls_get_addr.c
===================================================================
--- cpukit/score/cpu/microblaze/__tls_get_addr.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/microblaze/__tls_get_addr.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -47,8 +47,10 @@
 void *__tls_get_addr( const TLS_Index *ti )
 {
-  const Thread_Control *executing = _Thread_Get_executing();
-  void *tls_block = (char *) executing->Start.tls_area
-    + _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment );
+  const Thread_Control *executing;
 
-  return (char *) tls_block + ti->offset;
+  (void) ti;
+
+  executing = _Thread_Get_executing();
+
+  return executing->Registers.thread_pointer;
 }
Index: cpukit/score/cpu/microblaze/cpu.c
===================================================================
--- cpukit/score/cpu/microblaze/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/microblaze/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -74,5 +74,5 @@
 
   if ( tls_area != NULL ) {
-    _TLS_TCB_at_area_begin_initialize( tls_area );
+    context->thread_pointer = _TLS_Initialize_area( tls_area );
   }
 }
Index: cpukit/score/cpu/microblaze/include/rtems/score/cpu.h
===================================================================
--- cpukit/score/cpu/microblaze/include/rtems/score/cpu.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/microblaze/include/rtems/score/cpu.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -138,4 +138,5 @@
   uint32_t r31;
   uint32_t rmsr;
+  void *thread_pointer;
 } Context_Control;
 
Index: cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/microblaze/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -50,5 +50,8 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
 #define CPU_INTERRUPT_FRAME_SIZE 56
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #define MICROBLAZE_INTERRUPT_FRAME_R3   0
Index: cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/mips/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/moxie/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/nios2/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/nios2/nios2-context-initialize.c
===================================================================
--- cpukit/score/cpu/nios2/nios2-context-initialize.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/nios2/nios2-context-initialize.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -91,8 +91,5 @@
 
   if ( tls_area != NULL ) {
-    context->r23 = (uintptr_t) tls_area +
-      _TLS_Get_thread_control_block_area_size( (uintptr_t) _TLS_Alignment ) +
-       0x7000;
-    _TLS_TCB_before_TLS_block_initialize( tls_area );
+    context->r23 = (uintptr_t) _TLS_Initialize_area( tls_area ) + 0x7000;
   }
 }
Index: cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/no_cpu/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -55,4 +55,22 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+/**
+ * @brief Defines the thread-local storage (TLS) variant.
+ *
+ * Use one of the following values:
+ *
+ * 10: The architecture uses Variant I and the TLS offsets emitted by the
+ *     linker neglect the TCB (examples: nios2, m68k, microblaze, powerpc,
+ *     riscv).  The thread pointer directly references the thread-local data
+ *     area.
+ *
+ * 11: The architecture uses Variant I and the TLS offsets emitted by the
+ *     linker take the TCB into account (examples: arm, aarch64).
+ *     The thread pointer references the TCB.
+ *
+ * 20: The architecture uses Variant II (examples: i386, sparc).
+ */
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/or1k/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/powerpc/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -152,4 +152,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifdef RTEMS_SMP
 
Index: cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -54,4 +54,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 16
 #endif
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #ifdef RTEMS_SMP
Index: cpukit/score/cpu/riscv/riscv-context-initialize.c
===================================================================
--- cpukit/score/cpu/riscv/riscv-context-initialize.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/riscv/riscv-context-initialize.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -69,5 +69,5 @@
     void *tls_block;
 
-    tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area );
+    tls_block = _TLS_Initialize_area( tls_area );
     context->tp = (uintptr_t) tls_block;
   }
Index: cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/sh/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -29,4 +29,6 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
 
 #ifndef ASM
Index: cpukit/score/cpu/sparc/cpu.c
===================================================================
--- cpukit/score/cpu/sparc/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/sparc/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -320,5 +320,5 @@
 
   if ( tls_area != NULL ) {
-    void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area );
+    void *tcb = _TLS_Initialize_area( tls_area );
 
     the_context->g7 = (uintptr_t) tcb;
Index: cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/sparc/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -120,4 +120,6 @@
   #define CPU_PER_CPU_CONTROL_SIZE 0
 #endif
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
 
 #if ( SPARC_HAS_FPU == 1 )
Index: cpukit/score/cpu/sparc64/cpu.c
===================================================================
--- cpukit/score/cpu/sparc64/cpu.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/sparc64/cpu.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -133,5 +133,5 @@
 
   if ( tls_area != NULL ) {
-    void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area );
+    void *tcb = _TLS_Initialize_area( tls_area );
 
     the_context->g7 = (uintptr_t) tcb;
Index: cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/sparc64/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
+
 #ifndef ASM
 
Index: cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/v850/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -49,4 +49,6 @@
 #define CPU_PER_CPU_CONTROL_SIZE 0
 
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
+
 #ifndef ASM
 
Index: cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h
===================================================================
--- cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/cpu/x86_64/include/rtems/score/cpuimpl.h	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -32,4 +32,6 @@
 
 #define CPU_PER_CPU_CONTROL_SIZE 0
+
+#define CPU_THREAD_LOCAL_STORAGE_VARIANT 20
 
 #ifndef ASM
Index: cpukit/score/src/threadinitialize.c
===================================================================
--- cpukit/score/src/threadinitialize.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/src/threadinitialize.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -268,10 +268,6 @@
   /* Allocate thread-local storage (TLS) area in stack area */
   if ( tls_size > 0 ) {
-    uintptr_t tls_align;
-
     stack_end -= tls_size;
-    tls_align = (uintptr_t) _TLS_Alignment;
-    the_thread->Start.tls_area = (void *)
-      ( ( (uintptr_t) stack_end + tls_align - 1 ) & ~( tls_align - 1 ) );
+    the_thread->Start.tls_area = stack_end;
   }
 
Index: cpukit/score/src/tlsallocsize.c
===================================================================
--- cpukit/score/src/tlsallocsize.c	(revision 15bba4aecfca407d67e495b7a26c84929202d05f)
+++ cpukit/score/src/tlsallocsize.c	(revision 4c89fbcd316ca99fa16a0acc31f88fb80cb3060f)
@@ -11,5 +11,5 @@
 
 /*
- * Copyright (C) 2014, 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2014, 2022 embedded brains GmbH
  *
  * Redistribution and use in source and binary forms, with or without
@@ -59,13 +59,6 @@
 
   if ( allocation_size == 0 ) {
-    uintptr_t alignment;
-
-    alignment = _TLS_Align_up( (uintptr_t) _TLS_Alignment );
-
-    allocation_size = size;
-    allocation_size += _TLS_Get_thread_control_block_area_size( alignment );
-#ifndef __i386__
-    allocation_size += sizeof( TLS_Dynamic_thread_vector );
-#endif
+    uintptr_t tls_align;
+    uintptr_t stack_align;
 
     /*
@@ -73,5 +66,28 @@
      * shall meet the stack alignment requirement.
      */
-    allocation_size = _TLS_Align_up( allocation_size );
+    stack_align = CPU_STACK_ALIGNMENT;
+    tls_align = RTEMS_ALIGN_UP( (uintptr_t) _TLS_Alignment, stack_align );
+
+#ifndef __i386__
+    /* Reserve space for the dynamic thread vector */
+    allocation_size +=
+      RTEMS_ALIGN_UP( sizeof( TLS_Dynamic_thread_vector ), stack_align );
+#endif
+
+    /* Reserve space for the thread control block */
+    allocation_size +=
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 11
+      RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), tls_align );
+#else
+      RTEMS_ALIGN_UP( sizeof( TLS_Thread_control_block ), stack_align );
+#endif
+
+    /* Reserve space for the thread-local storage data */
+    allocation_size +=
+#if CPU_THREAD_LOCAL_STORAGE_VARIANT == 20
+      RTEMS_ALIGN_UP( size, tls_align );
+#else
+      RTEMS_ALIGN_UP( size, stack_align );
+#endif
 
     /*
@@ -79,7 +95,7 @@
      * enough to do the alignment manually.
      */
-    if ( alignment > CPU_STACK_ALIGNMENT ) {
-      _Assert( alignment % CPU_STACK_ALIGNMENT == 0 );
-      allocation_size += alignment - CPU_STACK_ALIGNMENT;
+    if ( tls_align > stack_align ) {
+      _Assert( tls_align % stack_align == 0 );
+      allocation_size += tls_align - stack_align;
     }
 
