[rtems commit] sparc: Add support for sptests/spcontext01

Sebastian Huber sebh at rtems.org
Thu May 21 08:26:15 UTC 2015


Module:    rtems
Branch:    master
Commit:    1c59cad4aa40238c1aa3085adf3d079114c077b8
Changeset: http://git.rtems.org/rtems/commit/?id=1c59cad4aa40238c1aa3085adf3d079114c077b8

Author:    Alexander Krutwig <alexander.krutwig at embedded-brains.de>
Date:      Fri Apr 24 16:05:50 2015 +0200

sparc: Add support for sptests/spcontext01

Implement _CPU_Context_validate() and _CPU_Context_volatile_clobber().

Update #2270.

---

 cpukit/score/cpu/sparc/Makefile.am                 |   2 +
 cpukit/score/cpu/sparc/rtems/score/cpu.h           |  12 +-
 cpukit/score/cpu/sparc/sparc-context-validate.S    | 368 +++++++++++++++++++++
 .../cpu/sparc/sparc-context-volatile-clobber.S     | 156 +++++++++
 4 files changed, 528 insertions(+), 10 deletions(-)

diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am
index c6ea1c3..8cf4f4a 100644
--- a/cpukit/score/cpu/sparc/Makefile.am
+++ b/cpukit/score/cpu/sparc/Makefile.am
@@ -11,6 +11,8 @@ include_rtems_score_HEADERS += rtems/score/cpuatomic.h
 
 noinst_LIBRARIES = libscorecpu.a
 libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_SOURCES += sparc-context-volatile-clobber.S
+libscorecpu_a_SOURCES += sparc-context-validate.S
 libscorecpu_a_SOURCES += sparc-counter.c
 libscorecpu_a_SOURCES += sparcv8-atomic.c
 libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index 235b365..64e8750 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -1216,17 +1216,9 @@ void _CPU_Context_restore_fp(
   Context_Control_fp **fp_context_ptr
 );
 
-static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
-{
-  /* TODO */
-}
+void _CPU_Context_volatile_clobber( uintptr_t pattern );
 
-static inline void _CPU_Context_validate( uintptr_t pattern )
-{
-  while (1) {
-    /* TODO */
-  }
-}
+void _CPU_Context_validate( uintptr_t pattern );
 
 typedef struct {
   uint32_t trap;
diff --git a/cpukit/score/cpu/sparc/sparc-context-validate.S b/cpukit/score/cpu/sparc/sparc-context-validate.S
new file mode 100644
index 0000000..0ee7177
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-validate.S
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+#define FRAME_OFFSET_BUFFER (CPU_MINIMUM_STACK_FRAME_SIZE)
+#define FRAME_OFFSET_L0 (FRAME_OFFSET_BUFFER + 0x04)
+#define FRAME_OFFSET_L1 (FRAME_OFFSET_L0 + 0x04)
+#define FRAME_OFFSET_L2 (FRAME_OFFSET_L1 + 0x04)
+#define FRAME_OFFSET_L3 (FRAME_OFFSET_L2 + 0x04)
+#define FRAME_OFFSET_L4 (FRAME_OFFSET_L3 + 0x04)
+#define FRAME_OFFSET_L5 (FRAME_OFFSET_L4 + 0x04)
+#define FRAME_OFFSET_L6 (FRAME_OFFSET_L5 + 0x04)
+#define FRAME_OFFSET_L7 (FRAME_OFFSET_L6 + 0x04)
+#define FRAME_OFFSET_I0 (FRAME_OFFSET_L7 + 0x04)
+#define FRAME_OFFSET_I1 (FRAME_OFFSET_I0 + 0x04)
+#define FRAME_OFFSET_I2 (FRAME_OFFSET_I1 + 0x04)
+#define FRAME_OFFSET_I3 (FRAME_OFFSET_I2 + 0x04)
+#define FRAME_OFFSET_I4 (FRAME_OFFSET_I3 + 0x04)
+#define FRAME_OFFSET_I5 (FRAME_OFFSET_I4 + 0x04)
+#define FRAME_OFFSET_I6 (FRAME_OFFSET_I5 + 0x04)
+#define FRAME_OFFSET_I7 (FRAME_OFFSET_I6 + 0x04)
+#define FRAME_OFFSET_SP (FRAME_OFFSET_I7 + 0x04)
+#define FRAME_END (FRAME_OFFSET_SP + 0x04)
+#define FRAME_SIZE \
+  ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
+
+.macro check_register reg
+	sub	%g1, 1, %g1
+	cmp	%g1, \reg
+	bne	restore_registers
+	 nop
+.endm
+
+.macro check_float_register reg
+	sub	%g1, 1, %g1
+	st	\reg, [%sp + FRAME_OFFSET_BUFFER]
+	ld	[%sp + FRAME_OFFSET_BUFFER], %o1
+	cmp	%g1, %o1
+	bne	restore_registers
+	 nop
+.endm
+
+.macro check_fsr_register reg
+	st	\reg, [%sp + FRAME_OFFSET_BUFFER]
+	ld	[%sp + FRAME_OFFSET_BUFFER], %o1
+	sub	%g1, 1, %g1
+	clr	%g3
+	sethi	%hi(0xCF800000), %g3
+	or	%g3, %lo(0x0FFF), %g3
+	and	%g1, %g3, %g3
+	and	%o1, %g3, %o1
+	cmp	%o1, %g3
+	bne	restore_registers
+	 nop
+.endm
+
+.macro write_register reg
+	add	%g1, 1, %g1
+	mov	%g1, \reg
+.endm
+
+.macro write_float_register reg
+	add	%g1, 1, %g1
+	st	%g1, [%sp + FRAME_OFFSET_BUFFER]
+	ld	[%sp + FRAME_OFFSET_BUFFER], \reg
+.endm
+
+.macro write_fsr_register reg
+	st	\reg, [%sp + FRAME_OFFSET_BUFFER]
+	ld	[%sp + FRAME_OFFSET_BUFFER], %o1
+	add	%g1, 1, %g1
+	clr	%g3
+
+	/*
+	 * FSR is masked with undefined, reserved or system-specific values
+	 * (e.g. FPU architecture version, FP queue).
+	 */
+	sethi	%hi(0xCF800000), %g3
+	or	%g3, %lo(0x0FFF), %g3
+	and	%g1, %g3, %g3
+	or	%o1, %g3, %g3
+	st	%g3, [%sp + FRAME_OFFSET_BUFFER]
+	ld	[%sp + FRAME_OFFSET_BUFFER], \reg
+.endm
+
+        .align 4
+        PUBLIC(_CPU_Context_validate)
+SYM(_CPU_Context_validate):
+
+	/*
+	 * g2 checks if the Floating Point Unit in the Processor Status
+	 * Register (PSR) is set.
+	 */
+	mov	%psr, %g2
+	sethi	%hi(SPARC_PSR_EF_MASK), %g3
+	and	%g2, %g3, %g2
+
+	/* g1 is used to save the original pattern */
+	mov	%o0, %g1
+
+	/* g4 establishes window counter */
+	clr	%g4
+
+	add	%sp, -FRAME_SIZE, %sp
+
+	st	%l0, [%sp + FRAME_OFFSET_L0]
+	st	%l1, [%sp + FRAME_OFFSET_L1]
+	st	%l2, [%sp + FRAME_OFFSET_L2]
+	st	%l3, [%sp + FRAME_OFFSET_L3]
+	st	%l4, [%sp + FRAME_OFFSET_L4]
+	st	%l5, [%sp + FRAME_OFFSET_L5]
+	st	%l6, [%sp + FRAME_OFFSET_L6]
+	st	%l7, [%sp + FRAME_OFFSET_L7]
+	st	%i0, [%sp + FRAME_OFFSET_I0]
+	st	%i1, [%sp + FRAME_OFFSET_I1]
+	st	%i2, [%sp + FRAME_OFFSET_I2]
+	st	%i3, [%sp + FRAME_OFFSET_I3]
+	st	%i4, [%sp + FRAME_OFFSET_I4]
+	st	%i5, [%sp + FRAME_OFFSET_I5]
+	st	%i6, [%sp + FRAME_OFFSET_I6]
+	st	%i7, [%sp + FRAME_OFFSET_I7]
+	st	%sp, [%sp + FRAME_OFFSET_SP]
+
+	cmp	%g4, 0
+	bne	write_locals_and_outputs
+	 nop
+	be	check_for_fp
+	 nop
+
+new_check_cycle:
+	clr	%g4
+	sub	%g1, 1, %g1
+
+	/* Write pattern values into registers */
+
+check_for_fp:
+	cmp	%g2, 0
+	be	write_y
+	 nop
+
+	write_fsr_register	%fsr
+	write_float_register	%f0
+	write_float_register	%f1
+	write_float_register	%f2
+	write_float_register	%f3
+	write_float_register	%f4
+	write_float_register	%f5
+	write_float_register	%f6
+	write_float_register	%f7
+	write_float_register	%f8
+	write_float_register	%f9
+	write_float_register	%f10
+	write_float_register	%f11
+	write_float_register	%f12
+	write_float_register	%f13
+	write_float_register	%f14
+	write_float_register	%f15
+	write_float_register	%f16
+	write_float_register	%f17
+	write_float_register	%f18
+	write_float_register	%f19
+	write_float_register	%f20
+	write_float_register	%f21
+	write_float_register	%f22
+	write_float_register	%f23
+	write_float_register	%f24
+	write_float_register	%f25
+	write_float_register	%f26
+	write_float_register	%f27
+	write_float_register	%f28
+	write_float_register	%f29
+	write_float_register	%f30
+	write_float_register	%f31
+
+write_y:
+	write_register	%y
+
+	write_register	%i0
+	write_register	%i1
+	write_register	%i2
+	write_register	%i3
+	write_register	%i4
+	write_register	%i5
+	/* Don't write register $i6 => frame pointer */
+	/* Don't write register $i7 => return address */
+	b	write_locals_and_outputs
+	 nop
+
+switch_to_next_window:
+	save	%sp, -FRAME_SIZE, %sp
+
+write_locals_and_outputs:
+	/* l0 is used as a scratch register */
+	write_register	%l1
+	write_register	%l2
+	write_register	%l3
+	write_register	%l4
+	write_register	%l5
+	write_register	%l6
+	write_register	%l7
+	write_register	%o1
+	write_register	%o2
+	write_register	%o3
+	write_register	%o4
+	write_register	%o5
+	/* Don't write register $o6 => stack pointer */
+	/* Don't write register $o7 => return address */
+
+	add	%g4, 1, %g4
+	cmp	%g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+	bne	switch_to_next_window
+	 nop
+
+	/* Dummy increment to set up reverse mechanism for checking process */
+	add	%g1, 1, %g1
+	clr	%g4
+
+	/* Checking begins here */
+window_checking:
+	cmp	%g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+	be	y_checking
+	 nop
+
+further_checking:
+	cmp	%g4, 0
+	bne	goto_local_registers
+	 nop
+
+	/* Check normal registers */
+	check_register	%o5
+	check_register	%o4
+	check_register	%o3
+	check_register	%o2
+	check_register	%o1
+
+goto_local_registers:
+	check_register	%l7
+	check_register	%l6
+	check_register	%l5
+	check_register	%l4
+	check_register	%l3
+	check_register	%l2
+	check_register	%l1
+
+	check_register	%i5
+	check_register	%i4
+	check_register	%i3
+	check_register	%i2
+	check_register	%i1
+	/*
+	For the last window i0 also needs to be checked as this variable
+	is not overwritten by the outputs of another window.
+	*/
+	add	%g4, 1, %g4
+	cmp	%g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+	bne	dont_check_i0
+	 nop
+	check_register	%i0
+	b	y_checking
+	 nop
+
+dont_check_i0:
+	restore
+
+	ba	window_checking
+	 nop
+
+	/* Check Y register */
+y_checking:
+	mov	%y, %o1
+	check_register	%o1
+	cmp	%g2, 0
+	be	new_check_cycle
+	 nop
+
+	/* Check floating point registers */
+	check_float_register	%f31
+	check_float_register	%f30
+	check_float_register	%f29
+	check_float_register	%f28
+	check_float_register	%f27
+	check_float_register	%f26
+	check_float_register	%f25
+	check_float_register	%f24
+	check_float_register	%f23
+	check_float_register	%f22
+	check_float_register	%f21
+	check_float_register	%f20
+	check_float_register	%f19
+	check_float_register	%f18
+	check_float_register	%f17
+	check_float_register	%f16
+	check_float_register	%f15
+	check_float_register	%f14
+	check_float_register	%f13
+	check_float_register	%f12
+	check_float_register	%f11
+	check_float_register	%f10
+	check_float_register	%f9
+	check_float_register	%f8
+	check_float_register	%f7
+	check_float_register	%f6
+	check_float_register	%f5
+	check_float_register	%f4
+	check_float_register	%f3
+	check_float_register	%f2
+	check_float_register	%f1
+	check_float_register	%f0
+	check_fsr_register	%fsr
+
+	be	new_check_cycle
+	 nop
+
+	/****** RESTORE STARTS HERE *******/
+
+	/* Restore non-volatile registers */
+
+restore_registers:
+	and	%g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4
+	cmp	%g4, 0
+	be	real_restore
+	 nop
+	restore
+	sub	%g4, 1, %g4
+	bne	restore_registers
+	 nop
+
+real_restore:
+	ld	[%sp + FRAME_OFFSET_L0], %l0
+	ld	[%sp + FRAME_OFFSET_L1], %l1
+	ld	[%sp + FRAME_OFFSET_L2], %l2
+	ld	[%sp + FRAME_OFFSET_L3], %l3
+	ld	[%sp + FRAME_OFFSET_L4], %l4
+	ld	[%sp + FRAME_OFFSET_L5], %l5
+	ld	[%sp + FRAME_OFFSET_L6], %l6
+	ld	[%sp + FRAME_OFFSET_L7], %l7
+	ld	[%sp + FRAME_OFFSET_I0], %i0
+	ld	[%sp + FRAME_OFFSET_I1], %i1
+	ld	[%sp + FRAME_OFFSET_I2], %i2
+	ld	[%sp + FRAME_OFFSET_I3], %i3
+	ld	[%sp + FRAME_OFFSET_I4], %i4
+	ld	[%sp + FRAME_OFFSET_I5], %i5
+	ld	[%sp + FRAME_OFFSET_I6], %i6
+	ld	[%sp + FRAME_OFFSET_I7], %i7
+
+	sub	%sp, -FRAME_SIZE, %sp
+
+return_value:
+	/* Load callback address and jump back */
+	jmp	%o7 + 8
+	 add	%sp, FRAME_SIZE, %sp
diff --git a/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
new file mode 100644
index 0000000..6e364cd
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+#define SCRATCH_0 (CPU_MINIMUM_STACK_FRAME_SIZE)
+#define SCRATCH_1 (SCRATCH_0 + 0x04)
+#define FRAME_END (SCRATCH_1 + 0x04)
+#define FRAME_SIZE \
+  ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
+
+.macro clobber_register reg
+	sub	%g2, 1, %g2
+	mov	%g2, \reg
+.endm
+
+.macro clobber_fp_register reg
+	sub	%g2, 1, %g2
+	st	%g2, [%sp + SCRATCH_0]
+	ld	[%sp + SCRATCH_0], \reg
+.endm
+
+	.section	".bss"
+	.align 4
+
+	/*
+	 * Use a global variable to vary the clobbered windows in each
+	 * invocation to test the window overflow and underflow conditions.
+	 */
+window_clobber_count:
+	.skip	4
+
+	.section	".text"
+	.align	4
+
+        PUBLIC(_CPU_Context_volatile_clobber)
+SYM(_CPU_Context_volatile_clobber):
+
+	/* Increment number of flushed windows by one */
+	sethi	%hi(window_clobber_count), %o1
+	ld	[%o1 + %lo(window_clobber_count)], %o2
+	add	%o2, 1, %o2
+	st	%o2, [%o1 + %lo(window_clobber_count)]
+
+	/* Clear window counter number */
+	clr	%g1
+
+	/* Save pattern to global register */
+	mov	%o0, %g2
+
+window_clobber:
+
+	/* Switch window */
+
+	save	%sp, -FRAME_SIZE, %sp
+
+	/* Check how many windows shall be flushed */
+	sethi	%hi(window_clobber_count), %o1
+	ld	[%o1 + %lo(window_clobber_count)], %o2
+	st	%o2, [%o1 + %lo(window_clobber_count)]
+	and	%o2, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %o1
+	cmp	%o1, 0
+	bne	no_manual_update
+	 nop
+	add	%o1, SPARC_NUMBER_OF_REGISTER_WINDOWS, %o1
+
+no_manual_update:
+	/* Register to determine whether FPU is switched on */
+	mov	%psr, %o2
+	sethi	%hi(SPARC_PSR_EF_MASK), %o3
+	and 	%o3, %o2, %o2
+
+	clobber_register	%o3
+	clobber_register	%o4
+	clobber_register	%o5
+	/* Don't overwrite return address $o7 */
+	clobber_register	%g3
+	clobber_register	%g4
+	clobber_register	%y
+
+	cmp	%o2, 0
+	be	window_update_check
+	 nop
+
+	clobber_fp_register	%f0
+	clobber_fp_register	%f1
+	clobber_fp_register	%f2
+	clobber_fp_register	%f3
+	clobber_fp_register	%f4
+	clobber_fp_register	%f5
+	clobber_fp_register	%f6
+	clobber_fp_register	%f7
+	clobber_fp_register	%f8
+	clobber_fp_register	%f9
+	clobber_fp_register	%f10
+	clobber_fp_register	%f11
+	clobber_fp_register	%f12
+	clobber_fp_register	%f13
+	clobber_fp_register	%f14
+	clobber_fp_register	%f15
+	clobber_fp_register	%f16
+	clobber_fp_register	%f17
+	clobber_fp_register	%f18
+	clobber_fp_register	%f19
+	clobber_fp_register	%f20
+	clobber_fp_register	%f21
+	clobber_fp_register	%f22
+	clobber_fp_register	%f23
+	clobber_fp_register	%f24
+	clobber_fp_register	%f25
+	clobber_fp_register	%f26
+	clobber_fp_register	%f27
+	clobber_fp_register	%f28
+	clobber_fp_register	%f29
+	clobber_fp_register	%f30
+	clobber_fp_register	%f31
+
+window_update_check:
+
+	/* Counter to how many windows were switched */
+	add	%g1, 1, %g1
+	cmp	%g1, %o1
+	bl	window_clobber
+	 nop
+
+restore_check:
+
+	cmp	%g1, 0
+	be	clobber_return
+	 nop
+
+	restore
+	sub	%g1, 1, %g1
+	ba	restore_check
+	 nop
+
+clobber_return:
+
+	jmp	%o7 + 8
+	 add	%sp, FRAME_SIZE, %sp




More information about the vc mailing list