sparc: Add support for sptests/spcontext01

Implement _CPU_Context_validate() and _CPU_Context_volatile_clobber().

Update #2270.
This commit is contained in:
Alexander Krutwig
2015-04-24 16:05:50 +02:00
committed by Sebastian Huber
parent a9c4f15dbe
commit 1c59cad4aa
4 changed files with 528 additions and 10 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -0,0 +1,368 @@
/*
* Copyright (c) 2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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