cpukit/score/cpu/mips: Add thread-local storage

The port declared CPU_THREAD_LOCAL_STORAGE_VARIANT but implemented none
of it.  _CPU_Context_Initialize() ignored its thread-local storage area,
_CPU_Get_TLS_thread_pointer() returned NULL, and there was nothing to
give the compiler the thread pointer, so every access to a thread-local
object read the wrong memory.

Keep the thread pointer in the context.  It follows the registers saved
by _CPU_Context_switch(), which addresses the members before it through
the offsets defined in cpu_asm.S, so nothing in the assembly changes.

The ABI places the thread pointer 0x7000 bytes above the thread-local
storage data, so that the signed 16-bit offsets emitted by the linker
reach a larger part of the area.

The compiler reads the thread pointer with rdhwr, which this processor
does not have.  Supplying it is the task of the exception handler.

Update #5689.

Assisted-by: Claude:claude-opus-5 claude-code
Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
Sebastian Huber
2026-09-11 00:01:29 +00:00
parent b03d4c0119
commit d4207b7fbe
3 changed files with 27 additions and 3 deletions
+8 -1
View File
@@ -73,6 +73,7 @@
#include <rtems/score/cpuimpl.h>
#include <rtems/score/isr.h>
#include <rtems/score/tls.h>
#if CPU_HARDWARE_FP
Context_Control_fp _CPU_Null_fp_context;
@@ -150,7 +151,6 @@ void _CPU_Context_Initialize(
)
{
(void) is_fp;
(void) tls_area;
uintptr_t stack_tmp;
__MIPS_REGISTER_TYPE intlvl = new_level & 0xff;
@@ -181,6 +181,13 @@ void _CPU_Context_Initialize(
}
#endif
the_context->c0_sr = c0_sr;
if ( tls_area != NULL ) {
the_context->thread_pointer = (char *) _TLS_Initialize_area( tls_area ) +
MIPS_TLS_THREAD_POINTER_OFFSET;
} else {
the_context->thread_pointer = NULL;
}
}
/*
* _CPU_Internal_threads_Idle_thread_body
@@ -295,6 +295,12 @@ typedef struct {
__MIPS_REGISTER_TYPE ra;
__MIPS_REGISTER_TYPE c0_sr;
__MIPS_REGISTER_TYPE c0_epc;
/*
* The thread pointer of the thread-local storage area. It follows the
* registers saved by _CPU_Context_switch(), which addresses the members
* above through the offsets defined in cpu_asm.S.
*/
void *thread_pointer;
} Context_Control;
#define _CPU_Context_Get_SP( _context ) \
@@ -53,6 +53,13 @@
#define CPU_THREAD_LOCAL_STORAGE_VARIANT 10
/*
* The ABI places the thread pointer this many bytes above the thread-local
* storage data, so that the signed 16-bit offsets emitted by the linker reach
* a larger part of the area.
*/
#define MIPS_TLS_THREAD_POINTER_OFFSET 0x7000
#ifndef ASM
#ifdef __cplusplus
@@ -77,6 +84,11 @@ static inline void _CPU_Use_thread_local_storage(
const Context_Control *context
)
{
/*
* There is no register which holds the thread pointer. The compiler reads
* it with rdhwr, which the exception handler emulates for processors which
* lack the instruction.
*/
(void) context;
}
@@ -84,8 +96,7 @@ static inline void *_CPU_Get_TLS_thread_pointer(
const Context_Control *context
)
{
(void) context;
return NULL;
return context->thread_pointer;
}
#ifdef __cplusplus