sparc: add support for thread local storage

Adds the necessary bits to initialize TLS in the stack
area and sets up CPU registers during context switch. Register g7 is
used to point to the thread data. Thread data is accessed with negative
offsets from g7.

Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
diff --git a/arch/Kconfig b/arch/Kconfig
index 274d5bd..3934ce8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -45,6 +45,7 @@
 	select BIG_ENDIAN
 	select ATOMIC_OPERATIONS_BUILTIN if SPARC_CASA
 	select ATOMIC_OPERATIONS_C if !SPARC_CASA
+	select ARCH_HAS_THREAD_LOCAL_STORAGE
 	help
 	  SPARC architecture
 
diff --git a/arch/sparc/core/CMakeLists.txt b/arch/sparc/core/CMakeLists.txt
index 28b5559..82ff790 100644
--- a/arch/sparc/core/CMakeLists.txt
+++ b/arch/sparc/core/CMakeLists.txt
@@ -17,3 +17,4 @@
 )
 
 zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
+zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
diff --git a/arch/sparc/core/switch.S b/arch/sparc/core/switch.S
index 17b12ce..1fe71ed 100644
--- a/arch/sparc/core/switch.S
+++ b/arch/sparc/core/switch.S
@@ -118,6 +118,9 @@
 
 	/* restore output registers */
 	ldd	[%o0 + _thread_offset_to_o6], %o6
+#ifdef CONFIG_THREAD_LOCAL_STORAGE
+	ld	[%o0 + _thread_offset_to_tls], %g7
+#endif
 
 	ld	[%o0 + _thread_offset_to_psr], %g1  /* %g1 = new thread psr */
 
diff --git a/arch/sparc/core/tls.c b/arch/sparc/core/tls.c
new file mode 100644
index 0000000..8e9d5be
--- /dev/null
+++ b/arch/sparc/core/tls.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019-2020 Cobham Gaisler AB
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <kernel_structs.h>
+#include <kernel_internal.h>
+#include <kernel_tls.h>
+#include <app_memory/app_memdomain.h>
+#include <sys/util.h>
+
+size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
+{
+	new_thread->tls = POINTER_TO_UINT(stack_ptr);
+
+	stack_ptr -= z_tls_data_size();
+	z_tls_copy(stack_ptr);
+
+	return z_tls_data_size();
+}
diff --git a/include/arch/sparc/linker.ld b/include/arch/sparc/linker.ld
index f7b1fb0..486845d 100644
--- a/include/arch/sparc/linker.ld
+++ b/include/arch/sparc/linker.ld
@@ -42,6 +42,7 @@
     _image_text_end = .;
 
 #include <linker/common-rom.ld>
+#include <linker/thread-local-storage.ld>
 
     SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
 	{