summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsps/sparc/leon3/config/gr712rc.cfg5
-rw-r--r--bsps/sparc/leon3/config/ut699.cfg3
-rw-r--r--bsps/sparc/leon3/config/ut700.cfg3
-rw-r--r--cpukit/score/cpu/sparc/cpu_asm.S3
-rw-r--r--cpukit/score/cpu/sparc/headers.am1
-rw-r--r--cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h58
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/sparc.h4
-rw-r--r--cpukit/score/cpu/sparc/sparc-counter-asm.S4
-rw-r--r--cpukit/score/cpu/sparc/window.S9
9 files changed, 85 insertions, 5 deletions
diff --git a/bsps/sparc/leon3/config/gr712rc.cfg b/bsps/sparc/leon3/config/gr712rc.cfg
index 385293275c..e8f07315e7 100644
--- a/bsps/sparc/leon3/config/gr712rc.cfg
+++ b/bsps/sparc/leon3/config/gr712rc.cfg
@@ -10,10 +10,11 @@ RTEMS_CPU=sparc
# and (hopefully) optimize for it.
# GCC and clang use different switches to select target:
ifneq (,$(findstring clang,$(CC)))
- CPU_CFLAGS = -mcpu=gr712rc
+ CPU_CFLAGS = -mcpu=gr712rc -D__FIX_LEON3FT_TN0018
else
- CPU_CFLAGS = -mcpu=leon3 -mfix-gr712rc
+ CPU_CFLAGS = -mcpu=leon3 -mfix-gr712rc -D__FIX_LEON3FT_TN0018
endif
+# -D__FIX_LEON3FT_TN0018 enables kernel work around for GRLIB-TN-0018 errata
# optimize flag: typically -O2
CFLAGS_OPTIMIZE_V = -O2 -g
diff --git a/bsps/sparc/leon3/config/ut699.cfg b/bsps/sparc/leon3/config/ut699.cfg
index a8fff49b3a..ed70cf5ee1 100644
--- a/bsps/sparc/leon3/config/ut699.cfg
+++ b/bsps/sparc/leon3/config/ut699.cfg
@@ -8,7 +8,8 @@ RTEMS_CPU=sparc
# This contains the compiler options necessary to select the CPU model
# and (hopefully) optimize for it.
-CPU_CFLAGS = -mcpu=leon -mfix-ut699
+# -D__FIX_LEON3FT_TN0018 enables kernel work around for GRLIB-TN-0018 errata
+CPU_CFLAGS = -mcpu=leon -mfix-ut699 -D__FIX_LEON3FT_TN0018
# optimize flag: typically -O2
CFLAGS_OPTIMIZE_V = -O2 -g
diff --git a/bsps/sparc/leon3/config/ut700.cfg b/bsps/sparc/leon3/config/ut700.cfg
index bcca9010ed..5c6fff8098 100644
--- a/bsps/sparc/leon3/config/ut700.cfg
+++ b/bsps/sparc/leon3/config/ut700.cfg
@@ -8,7 +8,8 @@ RTEMS_CPU=sparc
# This contains the compiler options necessary to select the CPU model
# and (hopefully) optimize for it.
-CPU_CFLAGS = -mcpu=leon3 -mfix-ut700
+# -D__FIX_LEON3FT_TN0018 enables kernel work around for GRLIB-TN-0018 errata
+CPU_CFLAGS = -mcpu=leon3 -mfix-ut700 -D__FIX_LEON3FT_TN0018
# optimize flag: typically -O2
CFLAGS_OPTIMIZE_V = -O2 -g
diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S
index 1251faa2f7..e884fb2f9e 100644
--- a/cpukit/score/cpu/sparc/cpu_asm.S
+++ b/cpukit/score/cpu/sparc/cpu_asm.S
@@ -23,6 +23,7 @@
#include <rtems/asm.h>
#include <rtems/score/percpu.h>
+#include <libcpu/grlib-tn-0018.h>
#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
#define FP_FRAME_OFFSET_FO_F1 (SPARC_MINIMUM_STACK_FRAME_SIZE + 0)
@@ -895,11 +896,13 @@ simple_return:
save ! Back to ISR dispatch window
good_task_window:
+ TN0018_WAIT_IFLUSH %l3,%l4 ! GRLIB-TN-0018 work around macro
mov %l0, %psr ! **** DISABLE TRAPS ****
nop; nop; nop
! and restore condition codes.
ld [%g1 + ISF_G1_OFFSET], %g1 ! restore g1
+ TN0018_FIX %l3,%l4 ! GRLIB-TN-0018 work around macro
jmp %l1 ! transfer control and
rett %l2 ! go back to tasks window
diff --git a/cpukit/score/cpu/sparc/headers.am b/cpukit/score/cpu/sparc/headers.am
index f5fc1aa9e2..25eaeaa74a 100644
--- a/cpukit/score/cpu/sparc/headers.am
+++ b/cpukit/score/cpu/sparc/headers.am
@@ -1,6 +1,7 @@
## This file was generated by "./boostrap -H".
include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/access.h
include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/byteorder.h
+include_libcpu_HEADERS += score/cpu/sparc/include/libcpu/grlib-tn-0018.h
include_machine_HEADERS += score/cpu/sparc/include/machine/elf_machdep.h
include_rtems_HEADERS += score/cpu/sparc/include/rtems/asm.h
include_rtems_score_HEADERS += score/cpu/sparc/include/rtems/score/cpu.h
diff --git a/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h
new file mode 100644
index 0000000000..f0154ab636
--- /dev/null
+++ b/cpukit/score/cpu/sparc/include/libcpu/grlib-tn-0018.h
@@ -0,0 +1,58 @@
+/* NOTE: the lda should be on offset 0x18 */
+#if defined(__FIX_LEON3FT_TN0018)
+
+/* LEON3 Cache controller register accessed via ASI 2 */
+#define ASI_CTRL 0x02
+#define CCTRL_IP_BIT 15
+#define CCTRL_ICS 0x3
+
+/*
+ * l3: (out) original cctrl
+ * l4: (out) original cctrl with ics=0
+ * NOTE: This macro modifies psr.icc.
+ */
+.macro TN0018_WAIT_IFLUSH out1 out2
+1:
+ ! wait for pending iflush to complete
+ lda [%g0] ASI_CTRL, \out1
+ srl \out1, CCTRL_IP_BIT, \out2
+ andcc \out2, 1, %g0
+ bne 1b
+ andn \out1, CCTRL_ICS, \out2
+.endm
+
+
+.macro TN0018_WRITE_PSR src
+ wr \src, %psr
+.endm
+
+/* Prevent following jmp;rett sequence from "re-executing" due to cached RETT or source
+ * registers (l1 and l2) containing bit faults triggering ECC.
+ *
+ * l3: (in) original cctrl
+ * l4: (in) original cctrl with ics=0
+ * NOTE: This macro MUST be immediately followed by the "jmp;rett" pair.
+ */
+.macro TN0018_FIX in1 in2
+ .align 0x20 ! align the sta for performance
+ sta \in2, [%g0] ASI_CTRL ! disable icache
+ nop ! delay for sta to have effect on rett
+ or %l1, %l1, %l1 ! delay + catch rf parity error on l1
+ or %l2, %l2, %l2 ! delay + catch rf parity error on l2
+ sta \in1, [%g0] ASI_CTRL ! re-enable icache after rett
+ nop ! delay ensures insn after gets cached
+.endm
+
+#else
+
+.macro TN0018_WAIT_IFLUSH out1 out2
+.endm
+
+.macro TN0018_WRITE_PSR src
+.endm
+
+.macro TN0018_FIX in1 in2
+.endm
+
+#endif
+
diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
index 4846520b46..3ef3d17847 100644
--- a/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
+++ b/cpukit/score/cpu/sparc/include/rtems/score/sparc.h
@@ -319,7 +319,11 @@ void _SPARC_Set_TBR( uint32_t new_tbr );
static inline uint32_t sparc_disable_interrupts(void)
{
register uint32_t psr __asm__("g1"); /* return value of trap handler */
+#ifdef __FIX_LEON3FT_TN0018
+ __asm__ volatile ( "ta %1\n\tnop\n\t" : "=r" (psr) : "i" (SPARC_SWTRAP_IRQDIS));
+#else
__asm__ volatile ( "ta %1\n\t" : "=r" (psr) : "i" (SPARC_SWTRAP_IRQDIS));
+#endif
return psr;
}
diff --git a/cpukit/score/cpu/sparc/sparc-counter-asm.S b/cpukit/score/cpu/sparc/sparc-counter-asm.S
index fb7783e096..44c3fa8edb 100644
--- a/cpukit/score/cpu/sparc/sparc-counter-asm.S
+++ b/cpukit/score/cpu/sparc/sparc-counter-asm.S
@@ -116,6 +116,10 @@ SYM(_SPARC_Get_timecount_clock):
bne .Lpending
ld [%o5 + 20], %o4
ta SPARC_SWTRAP_IRQEN
+#ifdef __FIX_LEON3FT_TN0018
+ /* A nop is added to work around the GRLIB-TN-0018 errata */
+ nop
+#endif
jmp %o7 + 8
sub %o4, %o0, %o0
.Lpending:
diff --git a/cpukit/score/cpu/sparc/window.S b/cpukit/score/cpu/sparc/window.S
index 5a36fd65be..4675248fe0 100644
--- a/cpukit/score/cpu/sparc/window.S
+++ b/cpukit/score/cpu/sparc/window.S
@@ -22,6 +22,7 @@
*/
#include <rtems/asm.h>
+#include <libcpu/grlib-tn-0018.h>
.section ".text"
/*
@@ -247,12 +248,18 @@ done_flushing:
* Restore the global registers we used
*/
- mov %l3, %g1
mov %l4, %g2
mov %l5, %g3
+
+ TN0018_WAIT_IFLUSH %l4,%l5
+ TN0018_WRITE_PSR %g1
+
+ mov %l3, %g1
mov %l6, %g4
mov %l7, %g5
+ TN0018_FIX %l4,%l5
+
jmpl %l2, %g0
rett %l2 + 4