diff options
author | Daniel Cederman <cederman@gaisler.com> | 2017-07-13 09:26:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-07-17 07:41:38 +0200 |
commit | 2f8704b6c8c3ce65cdf2b589a98de1d1d9dc8ffa (patch) | |
tree | bd540adf388432ec7db34e5d2c4a3d4b8574b344 | |
parent | psxtests: Add a mmap dedicated test case (diff) | |
download | rtems-2f8704b6c8c3ce65cdf2b589a98de1d1d9dc8ffa.tar.bz2 |
sparc: Add assembly workaround for LEON3FT B2BST errata
This patch adds NOP instructions to prevent instruction sequences
that are sensitive to the LEON3FT B2BST errata. See GRLIB-TN-0009:
"LEON3FT Stale Cache Entry After Store with Data Tag Parity Error"
for more information.
The sequences are only modified if __FIX_LEON3FT_B2BST is defined.
The patch works in conjunction with the -mfix-ut700, -mfix-gr712rc,
and -mfix-ut699 GCC flags that prevents the sensitive sequences from
being generated.
Update #3057.
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/irq_asm.S | 47 | ||||
-rw-r--r-- | c/src/lib/libcpu/sparc/access/access.S | 28 | ||||
-rw-r--r-- | c/src/lib/libcpu/sparc/reg_win/window.S | 12 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/cpu_asm.S | 22 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/rtems/score/sparc.h | 10 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/sparc-context-validate.S | 1 |
6 files changed, 120 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S index 075c7808d3..b4374c381c 100644 --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S @@ -66,14 +66,22 @@ SYM(_CPU_Context_switch): */ std %l0, [%o0 + L0_OFFSET] ! save the local registers + SPARC_LEON3FT_B2BST_NOP std %l2, [%o0 + L2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l4, [%o0 + L4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l6, [%o0 + L6_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i0, [%o0 + I0_OFFSET] ! save the input registers + SPARC_LEON3FT_B2BST_NOP std %i2, [%o0 + I2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i4, [%o0 + I4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i6, [%o0 + I6_FP_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %o6, [%o0 + O6_SP_OFFSET] ! save the output registers @@ -158,14 +166,22 @@ save_frame_loop: */ std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + SPARC_LEON3FT_B2BST_NOP ba save_frame_loop nop @@ -375,13 +391,20 @@ win_ovflow: */ std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] restore @@ -406,15 +429,21 @@ dont_do_the_window: ! make space for ISF std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC + SPARC_LEON3FT_B2BST_NOP st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC st %g1, [%sp + ISF_G1_OFFSET] ! save g1 std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3 + SPARC_LEON3FT_B2BST_NOP std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above + SPARC_LEON3FT_B2BST_NOP st %g7, [%sp + ISF_G7_OFFSET] ! save g7 std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1 + SPARC_LEON3FT_B2BST_NOP std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3 + SPARC_LEON3FT_B2BST_NOP std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5 + SPARC_LEON3FT_B2BST_NOP std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7 rd %y, %g1 @@ -440,6 +469,7 @@ dont_do_the_window: add %l7, 1, %l7 st %l7, [%g6 + PER_CPU_ISR_NEST_LEVEL] + SPARC_LEON3FT_B2BST_NOP add %l6, 1, %l6 st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] @@ -587,6 +617,7 @@ profiling_not_outer_most_exit: ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %o2 ld [%g6 + PER_CPU_ISR_DISPATCH_DISABLE], %o3 st %l7, [%g6 + PER_CPU_ISR_NEST_LEVEL] + SPARC_LEON3FT_B2BST_NOP sub %l6, 1, %l6 st %l6, [%g6 + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL] @@ -635,21 +666,37 @@ isr_dispatch: */ sub %sp, FP_FRAME_SIZE, %sp std %f0, [%sp + FP_FRAME_OFFSET_FO_F1] + SPARC_LEON3FT_B2BST_NOP std %f2, [%sp + FP_FRAME_OFFSET_F2_F3] + SPARC_LEON3FT_B2BST_NOP std %f4, [%sp + FP_FRAME_OFFSET_F4_F5] + SPARC_LEON3FT_B2BST_NOP std %f6, [%sp + FP_FRAME_OFFSET_F6_F7] + SPARC_LEON3FT_B2BST_NOP std %f8, [%sp + FP_FRAME_OFFSET_F8_F9] + SPARC_LEON3FT_B2BST_NOP std %f10, [%sp + FP_FRAME_OFFSET_F1O_F11] + SPARC_LEON3FT_B2BST_NOP std %f12, [%sp + FP_FRAME_OFFSET_F12_F13] + SPARC_LEON3FT_B2BST_NOP std %f14, [%sp + FP_FRAME_OFFSET_F14_F15] + SPARC_LEON3FT_B2BST_NOP std %f16, [%sp + FP_FRAME_OFFSET_F16_F17] + SPARC_LEON3FT_B2BST_NOP std %f18, [%sp + FP_FRAME_OFFSET_F18_F19] + SPARC_LEON3FT_B2BST_NOP std %f20, [%sp + FP_FRAME_OFFSET_F2O_F21] + SPARC_LEON3FT_B2BST_NOP std %f22, [%sp + FP_FRAME_OFFSET_F22_F23] + SPARC_LEON3FT_B2BST_NOP std %f24, [%sp + FP_FRAME_OFFSET_F24_F25] + SPARC_LEON3FT_B2BST_NOP std %f26, [%sp + FP_FRAME_OFFSET_F26_F27] + SPARC_LEON3FT_B2BST_NOP std %f28, [%sp + FP_FRAME_OFFSET_F28_F29] + SPARC_LEON3FT_B2BST_NOP std %f30, [%sp + FP_FRAME_OFFSET_F3O_F31] + SPARC_LEON3FT_B2BST_NOP st %fsr, [%sp + FP_FRAME_OFFSET_FSR] call SYM(_Thread_Do_dispatch) mov %g6, %o0 diff --git a/c/src/lib/libcpu/sparc/access/access.S b/c/src/lib/libcpu/sparc/access/access.S index cb8693b776..9397cb815b 100644 --- a/c/src/lib/libcpu/sparc/access/access.S +++ b/c/src/lib/libcpu/sparc/access/access.S @@ -59,6 +59,33 @@ SYM(_ld64): retl ldd [%o0], %o0 +#if defined(__FIX_LEON3FT_B2BST) + +SYM(_st8): + stub %o1, [%o0] + retl + nop + +SYM(_st_be16): +SYM(_st16): + stuh %o1, [%o0] + retl + nop + +SYM(_st_be32): +SYM(_st32): + st %o1, [%o0] + retl + nop + +SYM(_st_be64): +SYM(_st64): + std %o1, [%o0] + retl + nop + +#else + SYM(_st8): retl stb %o1, [%o0] @@ -79,3 +106,4 @@ SYM(_st64): mov %o1, %o2 retl std %o2, [%o0] +#endif diff --git a/c/src/lib/libcpu/sparc/reg_win/window.S b/c/src/lib/libcpu/sparc/reg_win/window.S index b8745593f5..5a36fd65be 100644 --- a/c/src/lib/libcpu/sparc/reg_win/window.S +++ b/c/src/lib/libcpu/sparc/reg_win/window.S @@ -51,19 +51,24 @@ SYM(window_overflow_trap_handler): */ std %l0, [%sp + 0x00] ! save local register set + SPARC_LEON3FT_B2BST_NOP std %l2, [%sp + 0x08] mov %wim, %l3 sll %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l2 ! l2 = WIM << (Number Windows - 1) std %l4, [%sp + 0x10] + SPARC_LEON3FT_B2BST_NOP std %l6, [%sp + 0x18] srl %l3, 1, %l3 ! l3 = WIM >> 1 wr %l3, %l2, %wim ! WIM = (WIM >> 1) ^ ! (WIM << (Number Windows - 1)) ! 3 instruction delay not needed here std %i0, [%sp + 0x20] ! save input register set + SPARC_LEON3FT_B2BST_NOP std %i2, [%sp + 0x28] + SPARC_LEON3FT_B2BST_NOP std %i4, [%sp + 0x30] + SPARC_LEON3FT_B2BST_NOP std %i6, [%sp + 0x38] restore ! Go back to trap window. jmp %l1 ! Re-execute save. @@ -206,13 +211,20 @@ save_frame_loop: */ std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] ba save_frame_loop diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S index 4e683dae0d..399c95508b 100644 --- a/cpukit/score/cpu/sparc/cpu_asm.S +++ b/cpukit/score/cpu/sparc/cpu_asm.S @@ -46,23 +46,45 @@ SYM(_CPU_Context_save_fp): ld [%o0], %o1 std %f0, [%o1 + FO_F1_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f2, [%o1 + F2_F3_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f4, [%o1 + F4_F5_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f6, [%o1 + F6_F7_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f8, [%o1 + F8_F9_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f10, [%o1 + F1O_F11_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f12, [%o1 + F12_F13_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f14, [%o1 + F14_F15_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f16, [%o1 + F16_F17_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f18, [%o1 + F18_F19_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f20, [%o1 + F2O_F21_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f22, [%o1 + F22_F23_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f24, [%o1 + F24_F25_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f26, [%o1 + F26_F27_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f28, [%o1 + F28_F29_OFFSET] + SPARC_LEON3FT_B2BST_NOP std %f30, [%o1 + F3O_F31_OFFSET] + SPARC_LEON3FT_B2BST_NOP +#if defined(__FIX_LEON3FT_B2BST) + st %fsr, [%o1 + FSR_OFFSET] + jmp %o7 + 8 + nop +#else jmp %o7 + 8 st %fsr, [%o1 + FSR_OFFSET] +#endif /* * void _CPU_Context_restore_fp( diff --git a/cpukit/score/cpu/sparc/rtems/score/sparc.h b/cpukit/score/cpu/sparc/rtems/score/sparc.h index 5fe8b6ada7..747d013559 100644 --- a/cpukit/score/cpu/sparc/rtems/score/sparc.h +++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h @@ -63,6 +63,16 @@ extern "C" { #define SPARC_NUMBER_OF_REGISTER_WINDOWS 8 /** + * See GRLIB-TN-0009: "LEON3FT Stale Cache Entry After Store with + * Data Tag Parity Error" + */ +#if defined(__FIX_LEON3FT_B2BST) + #define SPARC_LEON3FT_B2BST_NOP nop +#else + #define SPARC_LEON3FT_B2BST_NOP +#endif + +/** * This macro indicates whether this multilib variation has hardware * floating point or not. We use the gcc cpp predefine _SOFT_FLOAT * to determine that. diff --git a/cpukit/score/cpu/sparc/sparc-context-validate.S b/cpukit/score/cpu/sparc/sparc-context-validate.S index e0724e0e94..777f4dd8a6 100644 --- a/cpukit/score/cpu/sparc/sparc-context-validate.S +++ b/cpukit/score/cpu/sparc/sparc-context-validate.S @@ -282,6 +282,7 @@ y_checking: nop st %o1, [%sp + FRAME_OFFSET_BUFFER_2] + SPARC_LEON3FT_B2BST_NOP /* Check floating point registers */ check_float_register %f31 check_float_register %f30 |