score: Add _CPU_Use_thread_local_storage()

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.
This commit is contained in:
Sebastian Huber
2022-07-04 08:30:42 +02:00
parent 9dd4bd3963
commit 03e4d1e931
21 changed files with 223 additions and 4 deletions
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 = ppc_get_context( context )->tp;
/* Make sure that the register assignment is not optimized away */
__asm__ volatile ( "" : : "r" ( tp ) );
}
#ifdef __cplusplus
}
#endif
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
+5
View File
@@ -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
);
}
+16 -4
View File
@@ -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