summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2018-01-23 12:50:56 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2020-09-02 10:53:07 +0200
commitc451018877f3539d775ca0e1fee24ad896e66b68 (patch)
tree18705dcadd09ed9b8447952ddf8144b979ece178
parentc3ef58c1ade42a479d411e9e7389ce0a8db422c3 (diff)
sparc: auto detect FPU present in HW or not
When kernel is built soft-float this patch allows to kernel to use the HW/FPU for tasks enabling floating point context. If FPU is not present the floating point task attribute will always be zero, meaning that no floating point context is available. With this patch the per-cpu and task structures will be of equal sizes and field offsets regardless of soft/hard float compiliation settings. As consequence compiling parts of the application with soft-float will not crash looking up RTEMS task/per-cpu structures wrongly. However, it is not recommended to link soft and hard float code togerther since they are not ABI compliant when it comes to functions returning floats/doubles (stored in %f0/%f1 FPU register).
-rw-r--r--bsps/sparc/shared/start/bsp_fpu_detection.c20
-rw-r--r--bsps/sparc/shared/start/start.S13
-rw-r--r--c/src/lib/libbsp/sparc/erc32/Makefile.am2
-rw-r--r--c/src/lib/libbsp/sparc/leon2/Makefile.am1
-rw-r--r--c/src/lib/libbsp/sparc/leon3/Makefile.am1
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/sparc.h21
-rw-r--r--cpukit/score/src/threadinitialize.c11
7 files changed, 65 insertions, 4 deletions
diff --git a/bsps/sparc/shared/start/bsp_fpu_detection.c b/bsps/sparc/shared/start/bsp_fpu_detection.c
new file mode 100644
index 0000000000..f6130a2062
--- /dev/null
+++ b/bsps/sparc/shared/start/bsp_fpu_detection.c
@@ -0,0 +1,20 @@
+/**
+ * @file
+ * @ingroup sparc_bsp
+ * @brief ERC32/LEON2/LEON3 BSP FPU run-time detection.
+ */
+
+/*
+ * COPYRIGHT (c) 2018.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/cpu.h>
+
+#ifdef SPARC_DYNAMIC_FPU_DETECTION
+int sparc_fpu_present;
+#endif
diff --git a/bsps/sparc/shared/start/start.S b/bsps/sparc/shared/start/start.S
index 5fc1248a24..a43e00e212 100644
--- a/bsps/sparc/shared/start/start.S
+++ b/bsps/sparc/shared/start/start.S
@@ -282,12 +282,20 @@ SYM(hard_reset):
mov %g3, %wim
or %g1, 0xf20, %g1
+ sethi %hi(0x1000), %g6
+ or %g1, %g6, %g1 ! enable FPU if present in HW
wr %g1, %psr ! enable traps and disable ints
nop
nop
nop
+#if SPARC_DYNAMIC_FPU_DETECTION
+ mov %psr, %g7
+ and %g7, %g6, %g7
+ srl %g7, 12, %g7 ! save PSR.EF for later in g7
+#endif
+
sethi %hi(_Per_CPU_Information), %g6 ! get per-CPU control
add %g6, %lo(_Per_CPU_Information), %g6
@@ -374,6 +382,11 @@ zerobss:
bleu,a zerobss
nop
+#if SPARC_DYNAMIC_FPU_DETECTION
+ sethi %hi(sparc_fpu_present), %g3 ! Save FPU.EF in memory
+ st %g7, [%g3 + %lo(sparc_fpu_present)]
+#endif
+
mov %g0, %o0 ! command line
call SYM(boot_card) ! does not return
sub %sp, 0x60, %sp ! room for boot_card to save args
diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am
index 8cdd4581bf..d6860c1842 100644
--- a/c/src/lib/libbsp/sparc/erc32/Makefile.am
+++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am
@@ -34,6 +34,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/bspidle.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/start/bspdelay.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_exit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_halt.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fpu_detection.c
+
# gnatsupp
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/gnatsupp/gnatsupp.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gnatcommon.c
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 8ab87e5191..946a7d4664 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -34,6 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspidle.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspdelay.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_exit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_halt.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fpu_detection.c
# gnatsupp
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/gnatsupp/gnatsupp.c
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index 7933a48024..dae4873f55 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -38,6 +38,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/cpucounter.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_exit.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/bsp_fatal_halt.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fpu_detection.c
# gnatsupp
librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/gnatsupp/gnatsupp.c
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
index 4846520b46..7821c0455f 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
@@ -72,12 +72,23 @@ extern "C" {
#define SPARC_LEON3FT_B2BST_NOP
#endif
+/*
+ * Compile the SPARC kernel with runtime FPU detection. This is used
+ * by RTEMS kernels built without FPU but still need to be able to
+ * run tasks with FPU enabled. This way the kernel is SPARC (v7/v8)
+ * with or without FPU compatible.
+ */
+
+#define SPARC_DYNAMIC_FPU_DETECTION 1
+
/**
* This macro indicates whether this multilib variation has hardware
* floating point or not. We use the gcc cpp predefine _SOFT_FLOAT
* to determine that.
*/
-#if defined(_SOFT_FLOAT)
+#if SPARC_DYNAMIC_FPU_DETECTION
+ #define SPARC_HAS_FPU 1
+#elif defined(_SOFT_FLOAT)
#define SPARC_HAS_FPU 0
#else
#define SPARC_HAS_FPU 1
@@ -87,7 +98,9 @@ extern "C" {
* This macro contains a string describing the multilib variant being
* build.
*/
-#if SPARC_HAS_FPU
+#if SPARC_DYNAMIC_FPU_DETECTION
+ #define CPU_MODEL_NAME "w/FPU-detect"
+#elif SPARC_HAS_FPU
#define CPU_MODEL_NAME "w/FPU"
#else
#define CPU_MODEL_NAME "w/soft-float"
@@ -245,6 +258,10 @@ uint32_t _SPARC_Get_TBR( void );
#endif /* RTEMS_PARAVIRT */
+#ifdef SPARC_DYNAMIC_FPU_DETECTION
+extern int sparc_fpu_present;
+#endif
+
/**
* @brief Macro to set the TBR.
*
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 691f56388e..3f4565e095 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -44,6 +44,13 @@ bool _Thread_Initialize(
#endif
size_t scheduler_index;
Per_CPU_Control *cpu = _Per_CPU_Get_by_index( 0 );
+ bool is_fp = config->is_fp;
+
+#if SPARC_DYNAMIC_FPU_DETECTION
+ /* Always disable FPU context on systems without FPU in HW */
+ if (sparc_fpu_present == 0)
+ is_fp = 0;
+#endif
memset(
&the_thread->Join_queue,
@@ -87,7 +94,7 @@ bool _Thread_Initialize(
/* Allocate floating-point context in stack area */
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
- if ( config->is_fp ) {
+ if ( is_fp ) {
the_thread->fp_context = ( Context_Control_fp *) stack_area;
the_thread->Start.fp_context = ( Context_Control_fp *) stack_area;
stack_size -= CONTEXT_FP_SIZE;
@@ -126,7 +133,7 @@ bool _Thread_Initialize(
* General initialization
*/
- the_thread->is_fp = config->is_fp;
+ the_thread->is_fp = is_fp;
the_thread->Start.isr_level = config->isr_level;
the_thread->Start.is_preemptible = config->is_preemptible;
the_thread->Start.budget_algorithm = config->budget_algorithm;