[PATCH 2/4] score: Add CPU context validation

Gedare Bloom gedare at rtems.org
Wed May 8 13:32:59 UTC 2013


This change needs some explanation and documentation in the CPU
Porting Guide. What are the two new CPU functions supposed to do?

On Wed, May 8, 2013 at 5:48 AM, Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
> ---
>  cpukit/score/cpu/arm/Makefile.am                   |    2 +
>  cpukit/score/cpu/arm/arm-context-validate.S        |  139 +++++++++++
>  .../score/cpu/arm/arm-context-volatile-clobber.S   |   37 +++
>  cpukit/score/cpu/arm/rtems/score/cpu.h             |    4 +
>  cpukit/score/cpu/avr/rtems/score/cpu.h             |   12 +
>  cpukit/score/cpu/bfin/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/h8300/rtems/score/cpu.h           |   12 +
>  cpukit/score/cpu/i386/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/lm32/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/m32c/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/m32r/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/m68k/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/mips/rtems/score/cpu.h            |   12 +
>  cpukit/score/cpu/moxie/rtems/score/cpu.h           |   12 +
>  cpukit/score/cpu/nios2/Makefile.am                 |    2 +
>  cpukit/score/cpu/nios2/nios2-context-validate.S    |  146 +++++++++++
>  .../cpu/nios2/nios2-context-volatile-clobber.S     |   42 +++
>  cpukit/score/cpu/nios2/rtems/score/cpu.h           |    4 +
>  cpukit/score/cpu/no_cpu/rtems/score/cpu.h          |   27 ++
>  cpukit/score/cpu/powerpc/Makefile.am               |    2 +
>  cpukit/score/cpu/powerpc/ppc-context-validate.S    |  263 ++++++++++++++++++++
>  .../cpu/powerpc/ppc-context-volatile-clobber.S     |   45 ++++
>  cpukit/score/cpu/powerpc/rtems/score/cpu.h         |    4 +
>  cpukit/score/cpu/sh/rtems/score/cpu.h              |   12 +
>  cpukit/score/cpu/sparc/rtems/score/cpu.h           |   12 +
>  cpukit/score/cpu/sparc64/rtems/score/cpu.h         |   12 +
>  cpukit/score/cpu/v850/rtems/score/cpu.h            |   12 +
>  testsuites/sptests/Makefile.am                     |    1 +
>  testsuites/sptests/configure.ac                    |    1 +
>  testsuites/sptests/spcontext01/Makefile.am         |   19 ++
>  testsuites/sptests/spcontext01/init.c              |  188 ++++++++++++++
>  testsuites/sptests/spcontext01/spcontext01.doc     |   11 +
>  testsuites/sptests/spcontext01/spcontext01.scn     |    2 +
>  33 files changed, 1107 insertions(+), 0 deletions(-)
>  create mode 100644 cpukit/score/cpu/arm/arm-context-validate.S
>  create mode 100644 cpukit/score/cpu/arm/arm-context-volatile-clobber.S
>  create mode 100644 cpukit/score/cpu/nios2/nios2-context-validate.S
>  create mode 100644 cpukit/score/cpu/nios2/nios2-context-volatile-clobber.S
>  create mode 100644 cpukit/score/cpu/powerpc/ppc-context-validate.S
>  create mode 100644 cpukit/score/cpu/powerpc/ppc-context-volatile-clobber.S
>  create mode 100644 testsuites/sptests/spcontext01/Makefile.am
>  create mode 100644 testsuites/sptests/spcontext01/init.c
>  create mode 100644 testsuites/sptests/spcontext01/spcontext01.doc
>  create mode 100644 testsuites/sptests/spcontext01/spcontext01.scn
>
> diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am
> index 61a278b..37ab901 100644
> --- a/cpukit/score/cpu/arm/Makefile.am
> +++ b/cpukit/score/cpu/arm/Makefile.am
> @@ -16,6 +16,8 @@ libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
>  libscorecpu_a_SOURCES =
>  libscorecpu_a_SOURCES += cpu.c
>  libscorecpu_a_SOURCES += cpu_asm.S
> +libscorecpu_a_SOURCES += arm-context-validate.S
> +libscorecpu_a_SOURCES += arm-context-volatile-clobber.S
>  libscorecpu_a_SOURCES += arm_exc_abort.S
>  libscorecpu_a_SOURCES += arm_exc_interrupt.S
>  libscorecpu_a_SOURCES += arm_exc_handler_low.S
> diff --git a/cpukit/score/cpu/arm/arm-context-validate.S b/cpukit/score/cpu/arm/arm-context-validate.S
> new file mode 100644
> index 0000000..4591d20
> --- /dev/null
> +++ b/cpukit/score/cpu/arm/arm-context-validate.S
> @@ -0,0 +1,139 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +
> +#define FRAME_OFFSET_R4 0
> +#define FRAME_OFFSET_R5 4
> +#define FRAME_OFFSET_R6 8
> +#define FRAME_OFFSET_R7 12
> +#define FRAME_OFFSET_R8 16
> +#define FRAME_OFFSET_R9 20
> +#define FRAME_OFFSET_R10 24
> +#define FRAME_OFFSET_R11 28
> +#define FRAME_OFFSET_LR 32
> +
> +#define FRAME_SIZE (FRAME_OFFSET_LR + 4)
> +
> +       .section        .text
> +
> +FUNCTION_THUMB_ENTRY(_CPU_Context_validate)
> +
> +       /* Save */
> +
> +       sub     sp, sp, #FRAME_SIZE
> +
> +       mov     r1, r4
> +       str     r1, [sp, #FRAME_OFFSET_R4]
> +       mov     r1, r5
> +       str     r1, [sp, #FRAME_OFFSET_R5]
> +       mov     r1, r6
> +       str     r1, [sp, #FRAME_OFFSET_R6]
> +       mov     r1, r7
> +       str     r1, [sp, #FRAME_OFFSET_R7]
> +       mov     r1, r8
> +       str     r1, [sp, #FRAME_OFFSET_R8]
> +       mov     r1, r9
> +       str     r1, [sp, #FRAME_OFFSET_R9]
> +       mov     r1, r10
> +       str     r1, [sp, #FRAME_OFFSET_R10]
> +       mov     r1, r11
> +       str     r1, [sp, #FRAME_OFFSET_R11]
> +       mov     r1, lr
> +       str     r1, [sp, #FRAME_OFFSET_LR]
> +
> +       /* Fill */
> +
> +       /* R1 is used for temporary values */
> +       mov     r1, r0
> +
> +       /* R2 contains the stack pointer */
> +       mov     r2, sp
> +
> +.macro fill_register reg
> +       add     r1, r1, #1
> +       mov     \reg, r1
> +.endm
> +
> +       fill_register   r3
> +       fill_register   r4
> +       fill_register   r5
> +       fill_register   r6
> +       fill_register   r7
> +       fill_register   r8
> +       fill_register   r9
> +       fill_register   r10
> +       fill_register   r11
> +       fill_register   r12
> +       fill_register   lr
> +
> +       /* Check */
> +check:
> +
> +.macro check_register reg
> +       add     r1, r1, #1
> +       cmp     \reg, r1
> +       bne     restore
> +.endm
> +
> +       cmp     r2, sp
> +       bne     restore
> +
> +       mov     r1, r0
> +
> +       check_register  r3
> +       check_register  r4
> +       check_register  r5
> +       check_register  r6
> +       check_register  r7
> +       check_register  r8
> +       check_register  r9
> +       check_register  r10
> +       check_register  r11
> +       check_register  r12
> +       check_register  lr
> +
> +       b       check
> +
> +       /* Restore */
> +restore:
> +
> +       ldr     r1, [sp, #FRAME_OFFSET_R4]
> +       mov     r4, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R5]
> +       mov     r5, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R6]
> +       mov     r6, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R7]
> +       mov     r7, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R8]
> +       mov     r8, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R9]
> +       mov     r9, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R10]
> +       mov     r10, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_R11]
> +       mov     r11, r1
> +       ldr     r1, [sp, #FRAME_OFFSET_LR]
> +       mov     lr, r1
> +
> +       add     sp, sp, #FRAME_SIZE
> +
> +       bx      lr
> +
> +FUNCTION_END(_CPU_Context_validate)
> diff --git a/cpukit/score/cpu/arm/arm-context-volatile-clobber.S b/cpukit/score/cpu/arm/arm-context-volatile-clobber.S
> new file mode 100644
> index 0000000..b79e570
> --- /dev/null
> +++ b/cpukit/score/cpu/arm/arm-context-volatile-clobber.S
> @@ -0,0 +1,37 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +
> +       .section        .text
> +
> +FUNCTION_THUMB_ENTRY(_CPU_Context_volatile_clobber)
> +
> +.macro clobber_register reg
> +       sub     r0, r0, #1
> +       mov     \reg, r0
> +.endm
> +
> +       clobber_register        r1
> +       clobber_register        r2
> +       clobber_register        r3
> +       clobber_register        r12
> +
> +       bx      lr
> +
> +FUNCTION_END(_CPU_Context_volatile_clobber)
> diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h
> index 5ed6b9b..b6f39ac 100644
> --- a/cpukit/score/cpu/arm/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h
> @@ -423,6 +423,10 @@ void _CPU_Context_save_fp( Context_Control_fp **fp_context_ptr );
>
>  void _CPU_Context_restore_fp( Context_Control_fp **fp_context_ptr );
>
> +void _CPU_Context_volatile_clobber( uintptr_t pattern );
> +
> +void _CPU_Context_validate( uintptr_t pattern );
> +
>  static inline uint32_t CPU_swap_u32( uint32_t value )
>  {
>  #if defined(__thumb2__)
> diff --git a/cpukit/score/cpu/avr/rtems/score/cpu.h b/cpukit/score/cpu/avr/rtems/score/cpu.h
> index 5f1577a..080f387 100644
> --- a/cpukit/score/cpu/avr/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/avr/rtems/score/cpu.h
> @@ -1114,6 +1114,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /* FIXME */
>  typedef CPU_Interrupt_frame CPU_Exception_frame;
>
> diff --git a/cpukit/score/cpu/bfin/rtems/score/cpu.h b/cpukit/score/cpu/bfin/rtems/score/cpu.h
> index 1b26527..aba01e9 100644
> --- a/cpukit/score/cpu/bfin/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/bfin/rtems/score/cpu.h
> @@ -1213,6 +1213,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /** @} */
>
>  /* FIXME */
> diff --git a/cpukit/score/cpu/h8300/rtems/score/cpu.h b/cpukit/score/cpu/h8300/rtems/score/cpu.h
> index 6031f96..ea0ee7c 100644
> --- a/cpukit/score/cpu/h8300/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/h8300/rtems/score/cpu.h
> @@ -1097,6 +1097,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /* FIXME */
>  typedef CPU_Interrupt_frame CPU_Exception_frame;
>
> diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h
> index 6667604..6a19fb1 100644
> --- a/cpukit/score/cpu/i386/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/i386/rtems/score/cpu.h
> @@ -667,6 +667,18 @@ void _CPU_Context_restore_fp(
>    } while (0)
>  #endif
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
>
>  #endif /* ASM */
> diff --git a/cpukit/score/cpu/lm32/rtems/score/cpu.h b/cpukit/score/cpu/lm32/rtems/score/cpu.h
> index 1f8a370..eef9ac8 100644
> --- a/cpukit/score/cpu/lm32/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/lm32/rtems/score/cpu.h
> @@ -1202,6 +1202,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /** @} */
>
>  /* FIXME */
> diff --git a/cpukit/score/cpu/m32c/rtems/score/cpu.h b/cpukit/score/cpu/m32c/rtems/score/cpu.h
> index 8d9acc3..ccb9e38 100644
> --- a/cpukit/score/cpu/m32c/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/m32c/rtems/score/cpu.h
> @@ -1153,6 +1153,18 @@ void _CPU_Context_restore(
>    Context_Control *new_context
>  ) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /* FIXME */
>  typedef CPU_Interrupt_frame CPU_Exception_frame;
>
> diff --git a/cpukit/score/cpu/m32r/rtems/score/cpu.h b/cpukit/score/cpu/m32r/rtems/score/cpu.h
> index 8c8a9c1..2c97ddb 100644
> --- a/cpukit/score/cpu/m32r/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/m32r/rtems/score/cpu.h
> @@ -1194,6 +1194,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /** @} */
>
>  /* FIXME */
> diff --git a/cpukit/score/cpu/m68k/rtems/score/cpu.h b/cpukit/score/cpu/m68k/rtems/score/cpu.h
> index 0f244e1..2af5be8 100644
> --- a/cpukit/score/cpu/m68k/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/m68k/rtems/score/cpu.h
> @@ -711,6 +711,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /**
>   *  This method prints the CPU exception frame.
>   *
> diff --git a/cpukit/score/cpu/mips/rtems/score/cpu.h b/cpukit/score/cpu/mips/rtems/score/cpu.h
> index 130c960..229490b 100644
> --- a/cpukit/score/cpu/mips/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/mips/rtems/score/cpu.h
> @@ -1125,6 +1125,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  void _BSP_Exception_frame_print( const CPU_Exception_frame *frame );
>
>  static inline void _CPU_Exception_frame_print(
> diff --git a/cpukit/score/cpu/moxie/rtems/score/cpu.h b/cpukit/score/cpu/moxie/rtems/score/cpu.h
> index e51798b..7c48d7b 100644
> --- a/cpukit/score/cpu/moxie/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/moxie/rtems/score/cpu.h
> @@ -970,6 +970,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /**
>   * @brief The set of registers that specifies the complete processor state.
>   *
> diff --git a/cpukit/score/cpu/nios2/Makefile.am b/cpukit/score/cpu/nios2/Makefile.am
> index 27bfb30..6fdc786 100644
> --- a/cpukit/score/cpu/nios2/Makefile.am
> +++ b/cpukit/score/cpu/nios2/Makefile.am
> @@ -23,6 +23,8 @@ noinst_LIBRARIES = libscorecpu.a
>  libscorecpu_a_SOURCES =
>  libscorecpu_a_SOURCES += nios2-context-initialize.c
>  libscorecpu_a_SOURCES += nios2-context-switch.S
> +libscorecpu_a_SOURCES += nios2-context-validate.S
> +libscorecpu_a_SOURCES += nios2-context-volatile-clobber.S
>  libscorecpu_a_SOURCES += nios2-eic-il-low-level.S
>  libscorecpu_a_SOURCES += nios2-eic-rsie-low-level.S
>  libscorecpu_a_SOURCES += nios2-exception-frame-print.c
> diff --git a/cpukit/score/cpu/nios2/nios2-context-validate.S b/cpukit/score/cpu/nios2/nios2-context-validate.S
> new file mode 100644
> index 0000000..9a5f5e1
> --- /dev/null
> +++ b/cpukit/score/cpu/nios2/nios2-context-validate.S
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +
> +#define FRAME_OFFSET_R16 0
> +#define FRAME_OFFSET_R17 4
> +#define FRAME_OFFSET_R18 8
> +#define FRAME_OFFSET_R19 12
> +#define FRAME_OFFSET_R20 16
> +#define FRAME_OFFSET_R21 20
> +#define FRAME_OFFSET_R22 24
> +#define FRAME_OFFSET_R23 28
> +#define FRAME_OFFSET_FP 32
> +#define FRAME_OFFSET_RA 36
> +
> +#define FRAME_SIZE (FRAME_OFFSET_RA + 4)
> +
> +       .set    noat
> +       .section        .text
> +
> +       .global _CPU_Context_validate
> +
> +_CPU_Context_validate:
> +
> +       /* Save */
> +       subi    sp, sp, FRAME_SIZE
> +       stw     r16, FRAME_OFFSET_R16(sp)
> +       stw     r17, FRAME_OFFSET_R17(sp)
> +       stw     r18, FRAME_OFFSET_R18(sp)
> +       stw     r19, FRAME_OFFSET_R19(sp)
> +       stw     r20, FRAME_OFFSET_R20(sp)
> +       stw     r21, FRAME_OFFSET_R21(sp)
> +       stw     r22, FRAME_OFFSET_R22(sp)
> +       stw     r23, FRAME_OFFSET_R23(sp)
> +       stw     fp, FRAME_OFFSET_FP(sp)
> +       stw     ra, FRAME_OFFSET_RA(sp)
> +
> +       /* Fill */
> +
> +       /* AT contains the stack pointer */
> +       mov     at, sp
> +
> +       /* R2 is used for temporary values */
> +
> +       subi    r3, r4, 1
> +       addi    r5, r4, 1
> +       addi    r6, r4, 2
> +       addi    r7, r4, 3
> +       addi    r8, r4, 4
> +       addi    r9, r4, 5
> +       addi    r10, r4, 6
> +       addi    r11, r4, 7
> +       addi    r12, r4, 8
> +       addi    r13, r4, 9
> +       addi    r14, r4, 10
> +       addi    r15, r4, 11
> +       addi    r16, r4, 12
> +       addi    r17, r4, 13
> +       addi    r18, r4, 14
> +       addi    r19, r4, 15
> +       addi    r20, r4, 16
> +       addi    r21, r4, 17
> +       addi    r22, r4, 18
> +       addi    r23, r4, 19
> +       addi    fp, r4, 20
> +       addi    ra, r4, 21
> +
> +       /* Check */
> +check:
> +       bne     sp, at, restore
> +       subi    r2, r4, 1
> +       bne     r2, r3, restore
> +       addi    r2, r4, 1
> +       bne     r2, r5, restore
> +       addi    r2, r4, 2
> +       bne     r2, r6, restore
> +       addi    r2, r4, 3
> +       bne     r2, r7, restore
> +       addi    r2, r4, 4
> +       bne     r2, r8, restore
> +       addi    r2, r4, 5
> +       bne     r2, r9, restore
> +       addi    r2, r4, 6
> +       bne     r2, r10, restore
> +       addi    r2, r4, 7
> +       bne     r2, r11, restore
> +       addi    r2, r4, 8
> +       bne     r2, r12, restore
> +       addi    r2, r4, 9
> +       bne     r2, r13, restore
> +       addi    r2, r4, 10
> +       bne     r2, r14, restore
> +       addi    r2, r4, 11
> +       bne     r2, r15, restore
> +       addi    r2, r4, 12
> +       bne     r2, r16, restore
> +       addi    r2, r4, 13
> +       bne     r2, r17, restore
> +       addi    r2, r4, 14
> +       bne     r2, r18, restore
> +       addi    r2, r4, 15
> +       bne     r2, r19, restore
> +       addi    r2, r4, 16
> +       bne     r2, r20, restore
> +       addi    r2, r4, 17
> +       bne     r2, r21, restore
> +       addi    r2, r4, 18
> +       bne     r2, r22, restore
> +       addi    r2, r4, 19
> +       bne     r2, r23, restore
> +       addi    r2, r4, 20
> +       bne     r2, fp, restore
> +       addi    r2, r4, 21
> +       bne     r2, ra, restore
> +       br      check
> +
> +       /* Restore */
> +restore:
> +       ldw     ra, FRAME_OFFSET_RA(sp)
> +       ldw     fp, FRAME_OFFSET_FP(sp)
> +       ldw     r23, FRAME_OFFSET_R23(sp)
> +       ldw     r22, FRAME_OFFSET_R22(sp)
> +       ldw     r21, FRAME_OFFSET_R21(sp)
> +       ldw     r20, FRAME_OFFSET_R20(sp)
> +       ldw     r19, FRAME_OFFSET_R19(sp)
> +       ldw     r18, FRAME_OFFSET_R18(sp)
> +       ldw     r17, FRAME_OFFSET_R17(sp)
> +       ldw     r16, FRAME_OFFSET_R16(sp)
> +       addi    sp, sp, FRAME_SIZE
> +       ret
> diff --git a/cpukit/score/cpu/nios2/nios2-context-volatile-clobber.S b/cpukit/score/cpu/nios2/nios2-context-volatile-clobber.S
> new file mode 100644
> index 0000000..7b484e7
> --- /dev/null
> +++ b/cpukit/score/cpu/nios2/nios2-context-volatile-clobber.S
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +
> +       .set    noat
> +       .section        .text
> +
> +       .global _CPU_Context_volatile_clobber
> +
> +_CPU_Context_volatile_clobber:
> +
> +       subi    at, r4, 11
> +       subi    r2, r4, 12
> +       subi    r3, r4, 13
> +       subi    r5, r4, 1
> +       subi    r6, r4, 2
> +       subi    r7, r4, 3
> +       subi    r8, r4, 4
> +       subi    r9, r4, 5
> +       subi    r10, r4, 6
> +       subi    r11, r4, 7
> +       subi    r12, r4, 8
> +       subi    r13, r4, 9
> +       subi    r14, r4, 10
> +       subi    r15, r4, 11
> +       ret
> diff --git a/cpukit/score/cpu/nios2/rtems/score/cpu.h b/cpukit/score/cpu/nios2/rtems/score/cpu.h
> index b0e94c5..d3b5046 100644
> --- a/cpukit/score/cpu/nios2/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/nios2/rtems/score/cpu.h
> @@ -333,6 +333,10 @@ void _CPU_Context_restore(
>    Context_Control *new_context
>  ) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
>
> +void _CPU_Context_volatile_clobber( uintptr_t pattern );
> +
> +void _CPU_Context_validate( uintptr_t pattern );
> +
>  void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
>
>  static inline uint32_t CPU_swap_u32( uint32_t value )
> diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
> index 8c4a61b..fae7677 100644
> --- a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
> @@ -1295,6 +1295,33 @@ void _CPU_Context_restore_fp(
>  );
>
>  /**
> + * @ingroup CPUContext
> + *
> + * @brief Clobbers all volatile registers with values derived from the pattern
> + * parameter.
> + *
> + * This function is used in test sptests/spcontext01.
> + *
> + * @param[in] pattern Pattern used to generate distinct register values.
> + */
> +void _CPU_Context_volatile_clobber( uintptr_t pattern );
> +
> +/**
> + * @ingroup CPUContext
> + *
> + * @brief Initializes and validates the CPU context with values derived from
> + * the pattern parameter.
> + *
> + * This function will not return if the CPU context remains consistent.  In
> + * case this function returns the CPU port is broken.
> + *
> + * This function is used in test sptests/spcontext01.
> + *
> + * @param[in] pattern Pattern used to generate distinct register values.
> + */
> +void _CPU_Context_validate( uintptr_t pattern );
> +
> +/**
>   * @brief The set of registers that specifies the complete processor state.
>   *
>   * The CPU exception frame may be available in fatal error conditions like for
> diff --git a/cpukit/score/cpu/powerpc/Makefile.am b/cpukit/score/cpu/powerpc/Makefile.am
> index 7fd64ef..b205762 100644
> --- a/cpukit/score/cpu/powerpc/Makefile.am
> +++ b/cpukit/score/cpu/powerpc/Makefile.am
> @@ -14,6 +14,8 @@ include_rtems_powerpc_HEADERS = rtems/powerpc/registers.h
>
>  noinst_LIBRARIES = libscorecpu.a
>  libscorecpu_a_SOURCES = cpu.c
> +libscorecpu_a_SOURCES += ppc-context-volatile-clobber.S
> +libscorecpu_a_SOURCES += ppc-context-validate.S
>  libscorecpu_a_SOURCES += ppc-isr-vector-install.c
>  libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
>
> diff --git a/cpukit/score/cpu/powerpc/ppc-context-validate.S b/cpukit/score/cpu/powerpc/ppc-context-validate.S
> new file mode 100644
> index 0000000..0e3154e
> --- /dev/null
> +++ b/cpukit/score/cpu/powerpc/ppc-context-validate.S
> @@ -0,0 +1,263 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +#include <rtems/score/cpu.h>
> +
> +#define LR_OFFSET 8
> +#define CR_OFFSET 12
> +#define OFFSET(i) ((i) * PPC_GPR_SIZE + 16)
> +#define GPR14_OFFSET OFFSET(0)
> +#define GPR15_OFFSET OFFSET(1)
> +#define GPR16_OFFSET OFFSET(2)
> +#define GPR17_OFFSET OFFSET(3)
> +#define GPR18_OFFSET OFFSET(4)
> +#define GPR19_OFFSET OFFSET(5)
> +#define GPR20_OFFSET OFFSET(6)
> +#define GPR21_OFFSET OFFSET(7)
> +#define GPR22_OFFSET OFFSET(8)
> +#define GPR23_OFFSET OFFSET(9)
> +#define GPR24_OFFSET OFFSET(10)
> +#define GPR25_OFFSET OFFSET(11)
> +#define GPR26_OFFSET OFFSET(12)
> +#define GPR27_OFFSET OFFSET(13)
> +#define GPR28_OFFSET OFFSET(14)
> +#define GPR29_OFFSET OFFSET(15)
> +#define GPR30_OFFSET OFFSET(16)
> +#define GPR31_OFFSET OFFSET(17)
> +#define FRAME_SIZE \
> +  ((OFFSET(18) + CPU_STACK_ALIGNMENT - 1) & (CPU_STACK_ALIGNMENT - 1))
> +
> +       .global _CPU_Context_validate
> +
> +_CPU_Context_validate:
> +
> +       /* Save */
> +       stwu    r1, -FRAME_SIZE(r1)
> +       mflr    r4
> +       stw     r4, LR_OFFSET(r1)
> +       mfcr    r4
> +       stw     r4, CR_OFFSET(r1)
> +       stw     r14, GPR14_OFFSET(r1)
> +       stw     r15, GPR15_OFFSET(r1)
> +       stw     r16, GPR16_OFFSET(r1)
> +       stw     r17, GPR17_OFFSET(r1)
> +       stw     r18, GPR18_OFFSET(r1)
> +       stw     r19, GPR19_OFFSET(r1)
> +       stw     r20, GPR20_OFFSET(r1)
> +       stw     r21, GPR21_OFFSET(r1)
> +       stw     r22, GPR22_OFFSET(r1)
> +       stw     r23, GPR23_OFFSET(r1)
> +       stw     r24, GPR24_OFFSET(r1)
> +       stw     r25, GPR25_OFFSET(r1)
> +       stw     r26, GPR26_OFFSET(r1)
> +       stw     r27, GPR27_OFFSET(r1)
> +       stw     r28, GPR28_OFFSET(r1)
> +       stw     r29, GPR29_OFFSET(r1)
> +       stw     r30, GPR30_OFFSET(r1)
> +       stw     r31, GPR31_OFFSET(r1)
> +
> +       /* Fill */
> +
> +       /* CR and GPR29 are equal most of the time */
> +       addi    r4, r3, 24
> +       mtcr    r4
> +
> +       addi    r4, r3, 25
> +       mtlr    r4
> +       addi    r4, r3, 26
> +       mtctr   r4
> +       addi    r4, r3, 27
> +       mtxer   r4
> +       addi    r0, r3, 28
> +
> +       /* GPR4 is used for temporary values */
> +
> +       addi    r5, r3, 1
> +       addi    r6, r3, 2
> +       addi    r7, r3, 3
> +       addi    r8, r3, 4
> +       addi    r9, r3, 5
> +       addi    r10, r3, 6
> +       addi    r11, r3, 7
> +       addi    r12, r3, 8
> +       addi    r14, r3, 9
> +       addi    r15, r3, 10
> +       addi    r16, r3, 11
> +       addi    r17, r3, 12
> +       addi    r18, r3, 13
> +       addi    r19, r3, 14
> +       addi    r20, r3, 15
> +       addi    r21, r3, 16
> +       addi    r22, r3, 17
> +       addi    r23, r3, 18
> +       addi    r24, r3, 19
> +       addi    r25, r3, 20
> +       addi    r26, r3, 21
> +       addi    r27, r3, 22
> +       addi    r28, r3, 23
> +
> +       /* GPR29 and CR are equal most of the time */
> +       addi    r29, r3, 24
> +
> +       /* GPR30 contains the MSR pattern */
> +       mfmsr   r30
> +       xor     r30, r30, r3
> +
> +       /* GPR31 contains the stack pointer */
> +       mr      r31, r1
> +
> +       /* Check */
> +check:
> +       mfcr    r4
> +       cmpw    r4, r29
> +       bne     restore
> +       addi    r4, r3, 1
> +       cmpw    r4, r5
> +       bne     restore
> +       addi    r4, r3, 2
> +       cmpw    r4, r6
> +       bne     restore
> +       addi    r4, r3, 3
> +       cmpw    r4, r7
> +       bne     restore
> +       addi    r4, r3, 4
> +       cmpw    r4, r8
> +       bne     restore
> +       addi    r4, r3, 5
> +       cmpw    r4, r9
> +       bne     restore
> +       addi    r4, r3, 6
> +       cmpw    r4, r10
> +       bne     restore
> +       addi    r4, r3, 7
> +       cmpw    r4, r11
> +       bne     restore
> +       addi    r4, r3, 8
> +       cmpw    r4, r12
> +       bne     restore
> +       lis     r4, _SDA_BASE_ at h
> +       ori     r4, r4, _SDA_BASE_ at l
> +       cmpw    r4, r13
> +       bne     restore
> +       addi    r4, r3, 9
> +       cmpw    r4, r14
> +       bne     restore
> +       addi    r4, r3, 10
> +       cmpw    r4, r15
> +       bne     restore
> +       addi    r4, r3, 11
> +       cmpw    r4, r16
> +       bne     restore
> +       addi    r4, r3, 12
> +       cmpw    r4, r17
> +       bne     restore
> +       addi    r4, r3, 13
> +       cmpw    r4, r18
> +       bne     restore
> +       addi    r4, r3, 14
> +       cmpw    r4, r19
> +       bne     restore
> +       addi    r4, r3, 15
> +       cmpw    r4, r20
> +       bne     restore
> +       addi    r4, r3, 16
> +       cmpw    r4, r21
> +       bne     restore
> +       addi    r4, r3, 17
> +       cmpw    r4, r22
> +       bne     restore
> +       addi    r4, r3, 18
> +       cmpw    r4, r23
> +       bne     restore
> +       addi    r4, r3, 19
> +       cmpw    r4, r24
> +       bne     restore
> +       addi    r4, r3, 20
> +       cmpw    r4, r25
> +       bne     restore
> +       addi    r4, r3, 21
> +       cmpw    r4, r26
> +       bne     restore
> +       addi    r4, r3, 22
> +       cmpw    r4, r27
> +       bne     restore
> +       addi    r4, r3, 23
> +       cmpw    r4, r28
> +       bne     restore
> +       addi    r4, r3, 24
> +       cmpw    r4, r29
> +       bne     restore
> +       mfmsr   r4
> +       xor     r4, r4, r3
> +       cmpw    r4, r30
> +       bne     restore
> +       addi    r4, r3, 25
> +       mflr    r5
> +       cmpw    r4, r5
> +       bne     restore
> +       addi    r4, r3, 26
> +       mfctr   r5
> +       cmpw    r4, r5
> +       bne     restore
> +       addi    r4, r3, 27
> +       mfxer   r5
> +       cmpw    r4, r5
> +       bne     restore
> +       addi    r4, r3, 28
> +       cmpw    r4, r0
> +       bne     restore
> +       cmpw    r31, r1
> +       bne     restore
> +#if 0
> +       /* This is only valid if we use the EABI */
> +       lis     r4, _SDA2_BASE_ at h
> +       ori     r4, r4, _SDA2_BASE_ at l
> +       cmpw    r4, r2
> +       bne     restore
> +#endif
> +       mtcr    r29
> +       addi    r5, r3, 1
> +       b       check
> +
> +       /* Restore */
> +restore:
> +       lwz     r31, GPR31_OFFSET(r1)
> +       lwz     r30, GPR30_OFFSET(r1)
> +       lwz     r29, GPR29_OFFSET(r1)
> +       lwz     r28, GPR28_OFFSET(r1)
> +       lwz     r27, GPR27_OFFSET(r1)
> +       lwz     r26, GPR26_OFFSET(r1)
> +       lwz     r25, GPR25_OFFSET(r1)
> +       lwz     r24, GPR24_OFFSET(r1)
> +       lwz     r23, GPR23_OFFSET(r1)
> +       lwz     r22, GPR22_OFFSET(r1)
> +       lwz     r21, GPR21_OFFSET(r1)
> +       lwz     r20, GPR20_OFFSET(r1)
> +       lwz     r19, GPR19_OFFSET(r1)
> +       lwz     r18, GPR18_OFFSET(r1)
> +       lwz     r17, GPR17_OFFSET(r1)
> +       lwz     r16, GPR16_OFFSET(r1)
> +       lwz     r15, GPR15_OFFSET(r1)
> +       lwz     r14, GPR14_OFFSET(r1)
> +       lwz     r4, CR_OFFSET(r1)
> +       mtcr    r4
> +       lwz     r4, LR_OFFSET(r1)
> +       mtlr    r4
> +       addi    r1, r1, FRAME_SIZE
> +       blr
> diff --git a/cpukit/score/cpu/powerpc/ppc-context-volatile-clobber.S b/cpukit/score/cpu/powerpc/ppc-context-volatile-clobber.S
> new file mode 100644
> index 0000000..f4a5721
> --- /dev/null
> +++ b/cpukit/score/cpu/powerpc/ppc-context-volatile-clobber.S
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/asm.h>
> +
> +       .global _CPU_Context_volatile_clobber
> +
> +_CPU_Context_volatile_clobber:
> +
> +       addi    r4, r3, 10
> +       rlwinm  r4, r4, 0, 20, 7
> +       mfcr    r5
> +       rlwinm  r5, r5, 0, 8, 19
> +       or      r4, r4, r5
> +       mtcr    r4
> +       addi    r4, r3, 11
> +       mtctr   r4
> +       addi    r4, r3, 12
> +       mtxer   r4
> +       addi    r0, r3, 13
> +       addi    r4, r3, 1
> +       addi    r5, r3, 2
> +       addi    r6, r3, 3
> +       addi    r7, r3, 4
> +       addi    r8, r3, 5
> +       addi    r9, r3, 6
> +       addi    r10, r3, 7
> +       addi    r11, r3, 8
> +       addi    r12, r3, 9
> +       blr
> diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpu.h b/cpukit/score/cpu/powerpc/rtems/score/cpu.h
> index 37d8c34..080c5bb 100644
> --- a/cpukit/score/cpu/powerpc/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/powerpc/rtems/score/cpu.h
> @@ -992,6 +992,10 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +void _CPU_Context_volatile_clobber( uintptr_t pattern );
> +
> +void _CPU_Context_validate( uintptr_t pattern );
> +
>  typedef struct {
>    uint32_t EXC_SRR0;
>    uint32_t EXC_SRR1;
> diff --git a/cpukit/score/cpu/sh/rtems/score/cpu.h b/cpukit/score/cpu/sh/rtems/score/cpu.h
> index f5ad90c..d4412f6 100644
> --- a/cpukit/score/cpu/sh/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/sh/rtems/score/cpu.h
> @@ -886,6 +886,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /* FIXME */
>  typedef CPU_Interrupt_frame CPU_Exception_frame;
>
> diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
> index b95d411..2209c89 100644
> --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
> @@ -1227,6 +1227,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  typedef struct {
>    uint32_t trap;
>    CPU_Interrupt_frame *isf;
> diff --git a/cpukit/score/cpu/sparc64/rtems/score/cpu.h b/cpukit/score/cpu/sparc64/rtems/score/cpu.h
> index 36c7144..314143b 100644
> --- a/cpukit/score/cpu/sparc64/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/sparc64/rtems/score/cpu.h
> @@ -1028,6 +1028,18 @@ void _CPU_Context_restore_fp(
>    Context_Control_fp **fp_context_ptr
>  );
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /* FIXME */
>  typedef CPU_Interrupt_frame CPU_Exception_frame;
>
> diff --git a/cpukit/score/cpu/v850/rtems/score/cpu.h b/cpukit/score/cpu/v850/rtems/score/cpu.h
> index c0b6f9e..12c824b 100644
> --- a/cpukit/score/cpu/v850/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/v850/rtems/score/cpu.h
> @@ -1128,6 +1128,18 @@ void _CPU_Context_restore_fp(
>  );
>  #endif
>
> +static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
> +{
> +  /* TODO */
> +}
> +
> +static inline void _CPU_Context_validate( uintptr_t pattern )
> +{
> +  while (1) {
> +    /* TODO */
> +  }
> +}
> +
>  /** @} */
>
>  /* FIXME */
> diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
> index c9d20dd..4b0fff6 100644
> --- a/testsuites/sptests/Makefile.am
> +++ b/testsuites/sptests/Makefile.am
> @@ -30,6 +30,7 @@ SUBDIRS = \
>      spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \
>      spatomic01 spatomic02 spatomic03 spatomic04 spatomic05 \
>      spatomic06 spatomic07
> +SUBDIRS += spcontext01
>  SUBDIRS += spfatal26
>  SUBDIRS += speventtransient01
>  SUBDIRS += speventsystem01
> diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
> index a43a1ad..ba3aa92 100644
> --- a/testsuites/sptests/configure.ac
> +++ b/testsuites/sptests/configure.ac
> @@ -27,6 +27,7 @@ AC_CHECK_SIZEOF([time_t])
>
>  # Explicitly list all Makefiles here
>  AC_CONFIG_FILES([Makefile
> +spcontext01/Makefile
>  spfatal26/Makefile
>  spinternalerror02/Makefile
>  spinternalerror01/Makefile
> diff --git a/testsuites/sptests/spcontext01/Makefile.am b/testsuites/sptests/spcontext01/Makefile.am
> new file mode 100644
> index 0000000..b1c7de2
> --- /dev/null
> +++ b/testsuites/sptests/spcontext01/Makefile.am
> @@ -0,0 +1,19 @@
> +rtems_tests_PROGRAMS = spcontext01
> +spcontext01_SOURCES = init.c
> +
> +dist_rtems_tests_DATA = spcontext01.scn spcontext01.doc
> +
> +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
> +include $(top_srcdir)/../automake/compile.am
> +include $(top_srcdir)/../automake/leaf.am
> +
> +AM_CPPFLAGS += -I$(top_srcdir)/../support/include
> +
> +LINK_OBJS = $(spcontext01_OBJECTS)
> +LINK_LIBS = $(spcontext01_LDLIBS)
> +
> +spcontext01$(EXEEXT): $(spcontext01_OBJECTS) $(spcontext01_DEPENDENCIES)
> +       @rm -f spcontext01$(EXEEXT)
> +       $(make-exe)
> +
> +include $(top_srcdir)/../automake/local.am
> diff --git a/testsuites/sptests/spcontext01/init.c b/testsuites/sptests/spcontext01/init.c
> new file mode 100644
> index 0000000..f9c1803
> --- /dev/null
> +++ b/testsuites/sptests/spcontext01/init.c
> @@ -0,0 +1,188 @@
> +/*
> + * Copyright (c) 2013 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.com/license/LICENSE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include "tmacros.h"
> +
> +#define ITERATION_COUNT 2000
> +
> +#define PRIORITY_HIGH 2
> +
> +#define PRIORITY_LOW 3
> +
> +#define FINISH_EVENT RTEMS_EVENT_0
> +
> +typedef struct {
> +  rtems_id control_task;
> +  rtems_id validate_tasks[2];
> +  size_t task_index;
> +  int iteration_counter;
> +} test_context;
> +
> +static test_context test_instance;
> +
> +static void validate_task(rtems_task_argument arg)
> +{
> +  _CPU_Context_validate(arg);
> +  rtems_test_assert(0);
> +}
> +
> +static void start_validate_task(
> +  rtems_id *id,
> +  uintptr_t pattern,
> +  rtems_task_priority priority
> +)
> +{
> +  rtems_status_code sc;
> +
> +  sc = rtems_task_create(
> +    rtems_build_name('V', 'A', 'L', 'I'),
> +    priority,
> +    RTEMS_MINIMUM_STACK_SIZE,
> +    RTEMS_DEFAULT_MODES,
> +    RTEMS_DEFAULT_ATTRIBUTES,
> +    id
> +  );
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +
> +  sc = rtems_task_start(*id, validate_task, pattern);
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +}
> +
> +static void reset_timer_or_finish(test_context *self, rtems_id timer)
> +{
> +  rtems_status_code sc;
> +  int i = self->iteration_counter;
> +
> +  if (i < ITERATION_COUNT) {
> +    self->iteration_counter = i + 1;
> +
> +    sc = rtems_timer_reset(timer);
> +    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +  } else {
> +    sc = rtems_event_send(self->control_task, FINISH_EVENT);
> +    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +  }
> +}
> +
> +static void switch_priorities(test_context *self)
> +{
> +  rtems_status_code sc;
> +  size_t index = self->task_index;
> +  size_t next = (index + 1) & 0x1;
> +  size_t task_high = index;
> +  size_t task_low = next;
> +  rtems_task_priority priority;
> +
> +  self->task_index = next;
> +
> +  sc = rtems_task_set_priority(
> +    self->validate_tasks[task_high],
> +    PRIORITY_HIGH,
> +    &priority
> +  );
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +
> +  sc = rtems_task_set_priority(
> +    self->validate_tasks[task_low],
> +    PRIORITY_LOW,
> +    &priority
> +  );
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +}
> +
> +static void clobber_and_switch_timer(rtems_id timer, void *arg)
> +{
> +  uintptr_t pattern = (uintptr_t) 0xffffffffffffffffU;
> +  test_context *self = arg;
> +
> +  reset_timer_or_finish(self, timer);
> +  switch_priorities(self);
> +
> +  _CPU_Context_volatile_clobber(pattern);
> +}
> +
> +static void start_timer(test_context *self)
> +{
> +  rtems_status_code sc;
> +  rtems_id timer;
> +
> +  sc = rtems_timer_create(rtems_build_name('C', 'L', 'S', 'W'), &timer);
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +
> +  sc = rtems_timer_fire_after(timer, 2, clobber_and_switch_timer, self);
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +}
> +
> +static void wait_for_finish(void)
> +{
> +  rtems_status_code sc;
> +  rtems_event_set out;
> +
> +  sc = rtems_event_receive(
> +    FINISH_EVENT,
> +    RTEMS_WAIT | RTEMS_EVENT_ALL,
> +    RTEMS_NO_TIMEOUT,
> +    &out
> +  );
> +  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
> +  rtems_test_assert(out == FINISH_EVENT);
> +}
> +
> +static void test(test_context *self)
> +{
> +  uintptr_t pattern_0 = (uintptr_t) 0xaaaaaaaaaaaaaaaaU;
> +  uintptr_t pattern_1 = (uintptr_t) 0x5555555555555555U;
> +
> +  memset(self, 0, sizeof(*self));
> +
> +  self->control_task = rtems_task_self();
> +
> +  start_validate_task(&self->validate_tasks[0], pattern_0, PRIORITY_LOW);
> +  start_validate_task(&self->validate_tasks[1], pattern_1, PRIORITY_HIGH);
> +  start_timer(self);
> +  wait_for_finish();
> +}
> +
> +static void Init(rtems_task_argument arg)
> +{
> +  test_context *self = &test_instance;
> +
> +  puts("\n\n*** TEST SPCONTEXT 1 ***");
> +
> +  test(self);
> +
> +  puts("*** END OF TEST SPCONTEXT 1 ***");
> +
> +  rtems_test_exit(0);
> +}
> +
> +#define CONFIGURE_MICROSECONDS_PER_TICK 1000
> +
> +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
> +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
> +
> +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
> +
> +#define CONFIGURE_MAXIMUM_TASKS 3
> +#define CONFIGURE_MAXIMUM_TIMERS 1
> +
> +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
> +
> +#define CONFIGURE_INIT
> +
> +#include <rtems/confdefs.h>
> diff --git a/testsuites/sptests/spcontext01/spcontext01.doc b/testsuites/sptests/spcontext01/spcontext01.doc
> new file mode 100644
> index 0000000..2c2c4cf
> --- /dev/null
> +++ b/testsuites/sptests/spcontext01/spcontext01.doc
> @@ -0,0 +1,11 @@
> +This file describes the directives and concepts tested by this test set.
> +
> +test set name: spcontext01
> +
> +directives:
> +
> +  TBD
> +
> +concepts:
> +
> +  - Ensure the context switching and interrupt processing works
> diff --git a/testsuites/sptests/spcontext01/spcontext01.scn b/testsuites/sptests/spcontext01/spcontext01.scn
> new file mode 100644
> index 0000000..b7b823b
> --- /dev/null
> +++ b/testsuites/sptests/spcontext01/spcontext01.scn
> @@ -0,0 +1,2 @@
> +*** TEST SPCONTEXT 1 ***
> +*** END OF TEST SPCONTEXT 1 ***
> --
> 1.7.7
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel



More information about the devel mailing list