Ignore:
Timestamp:
May 18, 2012, 1:47:23 PM (9 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
105ccdd5
Parents:
721fe34
git-author:
Sebastian Huber <sebastian.huber@…> (05/18/12 13:47:23)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/04/12 07:54:31)
Message:

powerpc: Simplify context switch

PowerPC cores with the SPE (Signal Processing Extension) have 64-bit
general-purpose registers. The SPE context switch code has been merged
with the standard context switch code. The context switch may use cache
operations to increase the performance. It will be ensured that the
context is 32-byte aligned (PPC_DEFAULT_CACHE_LINE_SIZE). This
increases the overall memory size of the context area in the thread
control block slightly. The general-purpose registers GPR2 and GPR13
are no longer part of the context. The BSP must initialize these
registers during startup (usually initialized by the eabi() function).

The new BSP option BSP_USE_DATA_CACHE_BLOCK_TOUCH can be used to enable
the dcbt instruction in the context switch.

The new BSP option BSP_USE_SYNC_IN_CONTEXT_SWITCH can be used to enable
sync and isync instructions in the context switch. This should be not
necessary in most cases.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/cpu/powerpc/rtems/score/cpu.h

    r721fe34 r1869bb7  
    2424 *  Copyright (c) 2001 Surrey Satellite Technology Limited (SSTL).
    2525 *
    26  *  Copyright (c) 2010-2011 embedded brains GmbH.
     26 *  Copyright (c) 2010-2012 embedded brains GmbH.
    2727 *
    2828 *  The license and distribution terms for this file may be
     
    250250 */
    251251
     252#ifndef __SPE__
     253  #define PPC_GPR_TYPE uint32_t
     254  #define PPC_GPR_SIZE 4
     255  #define PPC_GPR_LOAD lwz
     256  #define PPC_GPR_STORE stw
     257#else
     258  #define PPC_GPR_TYPE uint64_t
     259  #define PPC_GPR_SIZE 8
     260  #define PPC_GPR_LOAD evldd
     261  #define PPC_GPR_STORE evstdd
     262#endif
     263
     264#define PPC_DEFAULT_CACHE_LINE_SIZE 32
     265
    252266#ifndef ASM
    253267
     268/* Non-volatile context according to E500ABIUG and EABI */
    254269typedef struct {
    255   #ifndef __SPE__
    256     uint32_t   gpr1;    /* Stack pointer for all */
    257     uint32_t   gpr2;    /* Reserved SVR4, section ptr EABI + */
    258     uint32_t   gpr13;   /* Section ptr SVR4/EABI */
    259     uint32_t   gpr14;   /* Non volatile for all */
    260     uint32_t   gpr15;   /* Non volatile for all */
    261     uint32_t   gpr16;   /* Non volatile for all */
    262     uint32_t   gpr17;   /* Non volatile for all */
    263     uint32_t   gpr18;   /* Non volatile for all */
    264     uint32_t   gpr19;   /* Non volatile for all */
    265     uint32_t   gpr20;   /* Non volatile for all */
    266     uint32_t   gpr21;   /* Non volatile for all */
    267     uint32_t   gpr22;   /* Non volatile for all */
    268     uint32_t   gpr23;   /* Non volatile for all */
    269     uint32_t   gpr24;   /* Non volatile for all */
    270     uint32_t   gpr25;   /* Non volatile for all */
    271     uint32_t   gpr26;   /* Non volatile for all */
    272     uint32_t   gpr27;   /* Non volatile for all */
    273     uint32_t   gpr28;   /* Non volatile for all */
    274     uint32_t   gpr29;   /* Non volatile for all */
    275     uint32_t   gpr30;   /* Non volatile for all */
    276     uint32_t   gpr31;   /* Non volatile for all */
    277     uint32_t   cr;      /* PART of the CR is non volatile for all */
    278     uint32_t   pc;      /* Program counter/Link register */
    279     uint32_t   msr;     /* Initial interrupt level */
    280     #ifdef __ALTIVEC__
    281       /*
    282        * 12 non-volatile vector registers, cache-aligned area for vscr/vrsave
    283        * and padding to ensure cache-alignment.  Unfortunately, we can't verify
    284        * the cache line size here in the cpukit but altivec support code will
    285        * produce an error if this is ever different from 32 bytes.
    286        *
    287        * Note: it is the BSP/CPU-support's responsibility to save/restore
    288        *       volatile vregs across interrupts and exceptions.
    289        */
    290       uint8_t altivec[16*12 + 32 + 32];
    291     #endif
    292   #else
    293     /* Non-volatile context according to E500ABIUG and EABI */
    294     uint32_t context [
    295       8 /* Cache line padding */
    296       + 1 /* Stack pointer */
    297       + 1 /* MSR */
    298       + 1 /* LR */
    299       + 1 /* CR */
    300       + 18 * 2 /* GPR 14 to GPR 31 */
    301     ];
     270  uint32_t gpr1;
     271  uint32_t msr;
     272  uint32_t lr;
     273  uint32_t cr;
     274  PPC_GPR_TYPE gpr14;
     275  PPC_GPR_TYPE gpr15;
     276  PPC_GPR_TYPE gpr16;
     277  PPC_GPR_TYPE gpr17;
     278  PPC_GPR_TYPE gpr18;
     279  PPC_GPR_TYPE gpr19;
     280  PPC_GPR_TYPE gpr20;
     281  PPC_GPR_TYPE gpr21;
     282  PPC_GPR_TYPE gpr22;
     283  PPC_GPR_TYPE gpr23;
     284  PPC_GPR_TYPE gpr24;
     285  PPC_GPR_TYPE gpr25;
     286  PPC_GPR_TYPE gpr26;
     287  PPC_GPR_TYPE gpr27;
     288  PPC_GPR_TYPE gpr28;
     289  PPC_GPR_TYPE gpr29;
     290  PPC_GPR_TYPE gpr30;
     291  PPC_GPR_TYPE gpr31;
     292  #ifdef __ALTIVEC__
     293    /*
     294     * 12 non-volatile vector registers, cache-aligned area for vscr/vrsave
     295     * and padding to ensure cache-alignment.  Unfortunately, we can't verify
     296     * the cache line size here in the cpukit but altivec support code will
     297     * produce an error if this is ever different from 32 bytes.
     298     *
     299     * Note: it is the BSP/CPU-support's responsibility to save/restore
     300     *       volatile vregs across interrupts and exceptions.
     301     */
     302    uint8_t altivec[16*12 + 32 + PPC_DEFAULT_CACHE_LINE_SIZE];
    302303  #endif
     304} ppc_context;
     305
     306typedef struct {
     307  uint8_t context [
     308    PPC_DEFAULT_CACHE_LINE_SIZE
     309      + sizeof(ppc_context)
     310      + (sizeof(ppc_context) % PPC_DEFAULT_CACHE_LINE_SIZE == 0
     311        ? 0
     312          : PPC_DEFAULT_CACHE_LINE_SIZE
     313            - sizeof(ppc_context) % PPC_DEFAULT_CACHE_LINE_SIZE)
     314  ];
    303315} Context_Control;
     316
     317static inline ppc_context *ppc_get_context( Context_Control *context )
     318{
     319  uintptr_t clsz = PPC_DEFAULT_CACHE_LINE_SIZE;
     320  uintptr_t mask = clsz - 1;
     321  uintptr_t addr = (uintptr_t) context;
     322
     323  return (ppc_context *) ((addr & ~mask) + clsz);
     324}
     325
     326#define _CPU_Context_Get_SP( _context ) \
     327  ppc_get_context(_context)->gpr1
    304328#endif /* ASM */
    305329
    306 #ifndef __SPE__
    307   #define PPC_CONTEXT_SET_SP( _context, _sp ) \
    308     do { \
    309       (_context)->gpr1 = _sp; \
    310     } while (0)
    311 
    312   #define PPC_CONTEXT_GET_CR( _context ) \
    313     (_context)->cr
    314 
    315   #define PPC_CONTEXT_GET_MSR( _context ) \
    316     (_context)->msr
    317 
    318   #define PPC_CONTEXT_SET_MSR( _context, _msr ) \
    319     do { \
    320       (_context)->msr = _msr; \
    321     } while (0)
    322 
    323   #define PPC_CONTEXT_FIRST_SAVED_GPR 13
    324 
    325   #define PPC_CONTEXT_GET_FIRST_SAVED( _context ) \
    326     (_context)->gpr13
    327 
    328   #define PPC_CONTEXT_GET_PC( _context ) \
    329     (_context)->pc
    330 
    331   #define PPC_CONTEXT_SET_PC( _context, _pc ) \
    332     do { \
    333       (_context)->pc = _pc; \
    334     } while (0)
    335 
    336   #define _CPU_Context_Get_SP( _context ) \
    337     (_context)->gpr1
    338 #else
    339   #define PPC_CONTEXT_CACHE_LINE_0 32
    340   #define PPC_CONTEXT_OFFSET_SP 32
    341   #define PPC_CONTEXT_OFFSET_MSR 36
    342   #define PPC_CONTEXT_OFFSET_LR 40
    343   #define PPC_CONTEXT_OFFSET_CR 44
    344   #define PPC_CONTEXT_OFFSET_GPR14 48
    345   #define PPC_CONTEXT_OFFSET_GPR15 56
    346   #define PPC_CONTEXT_CACHE_LINE_1 64
    347   #define PPC_CONTEXT_OFFSET_GPR16 64
    348   #define PPC_CONTEXT_OFFSET_GPR17 72
    349   #define PPC_CONTEXT_OFFSET_GPR18 80
    350   #define PPC_CONTEXT_OFFSET_GPR19 88
    351   #define PPC_CONTEXT_CACHE_LINE_2 96
    352   #define PPC_CONTEXT_OFFSET_GPR20 96
    353   #define PPC_CONTEXT_OFFSET_GPR21 104
    354   #define PPC_CONTEXT_OFFSET_GPR22 112
    355   #define PPC_CONTEXT_OFFSET_GPR23 120
    356   #define PPC_CONTEXT_CACHE_LINE_3 128
    357   #define PPC_CONTEXT_OFFSET_GPR24 128
    358   #define PPC_CONTEXT_OFFSET_GPR25 136
    359   #define PPC_CONTEXT_OFFSET_GPR26 144
    360   #define PPC_CONTEXT_OFFSET_GPR27 152
    361   #define PPC_CONTEXT_CACHE_LINE_4 160
    362   #define PPC_CONTEXT_OFFSET_GPR28 160
    363   #define PPC_CONTEXT_OFFSET_GPR29 168
    364   #define PPC_CONTEXT_OFFSET_GPR30 176
    365   #define PPC_CONTEXT_OFFSET_GPR31 184
    366 
    367   #define PPC_CONTEXT_AREA( _context ) \
    368     ((uint32_t *) (((uintptr_t) (_context)) & ~0x1fU))
    369 
    370   #define PPC_CONTEXT_FIELD( _context, _offset ) \
    371     PPC_CONTEXT_AREA( _context ) [(_offset) / 4]
    372 
    373   #define PPC_CONTEXT_SET_SP( _context, _sp ) \
    374     do { \
    375       PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_SP ) = _sp; \
    376     } while (0)
    377 
    378   #define PPC_CONTEXT_GET_CR( _context ) \
    379     PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_CR )
    380 
    381   #define PPC_CONTEXT_GET_MSR( _context ) \
    382     PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_MSR )
    383 
    384   #define PPC_CONTEXT_SET_MSR( _context, _msr ) \
    385     do { \
    386       PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_MSR ) = _msr; \
    387     } while (0)
    388 
    389   #define PPC_CONTEXT_FIRST_SAVED_GPR 14
    390 
    391   #define PPC_CONTEXT_GET_FIRST_SAVED( _context ) \
    392     PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_GPR14 )
    393 
    394   #define PPC_CONTEXT_GET_PC( _context ) \
    395     PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_LR )
    396 
    397   #define PPC_CONTEXT_SET_PC( _context, _pc ) \
    398     do { \
    399       PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_LR ) = _pc; \
    400     } while (0)
    401 
    402   #define _CPU_Context_Get_SP( _context ) \
    403     PPC_CONTEXT_FIELD( _context, PPC_CONTEXT_OFFSET_SP )
    404 #endif
     330#define PPC_CONTEXT_OFFSET_GPR1 32
     331#define PPC_CONTEXT_OFFSET_MSR 36
     332#define PPC_CONTEXT_OFFSET_LR 40
     333#define PPC_CONTEXT_OFFSET_CR 44
     334
     335#define PPC_CONTEXT_GPR_OFFSET( gpr ) \
     336  (((gpr) - 14) * PPC_GPR_SIZE + 48)
     337
     338#define PPC_CONTEXT_OFFSET_GPR14 PPC_CONTEXT_GPR_OFFSET( 14 )
     339#define PPC_CONTEXT_OFFSET_GPR15 PPC_CONTEXT_GPR_OFFSET( 15 )
     340#define PPC_CONTEXT_OFFSET_GPR16 PPC_CONTEXT_GPR_OFFSET( 16 )
     341#define PPC_CONTEXT_OFFSET_GPR17 PPC_CONTEXT_GPR_OFFSET( 17 )
     342#define PPC_CONTEXT_OFFSET_GPR18 PPC_CONTEXT_GPR_OFFSET( 18 )
     343#define PPC_CONTEXT_OFFSET_GPR19 PPC_CONTEXT_GPR_OFFSET( 19 )
     344#define PPC_CONTEXT_OFFSET_GPR20 PPC_CONTEXT_GPR_OFFSET( 20 )
     345#define PPC_CONTEXT_OFFSET_GPR21 PPC_CONTEXT_GPR_OFFSET( 21 )
     346#define PPC_CONTEXT_OFFSET_GPR22 PPC_CONTEXT_GPR_OFFSET( 22 )
     347#define PPC_CONTEXT_OFFSET_GPR23 PPC_CONTEXT_GPR_OFFSET( 23 )
     348#define PPC_CONTEXT_OFFSET_GPR24 PPC_CONTEXT_GPR_OFFSET( 24 )
     349#define PPC_CONTEXT_OFFSET_GPR25 PPC_CONTEXT_GPR_OFFSET( 25 )
     350#define PPC_CONTEXT_OFFSET_GPR26 PPC_CONTEXT_GPR_OFFSET( 26 )
     351#define PPC_CONTEXT_OFFSET_GPR27 PPC_CONTEXT_GPR_OFFSET( 27 )
     352#define PPC_CONTEXT_OFFSET_GPR28 PPC_CONTEXT_GPR_OFFSET( 28 )
     353#define PPC_CONTEXT_OFFSET_GPR29 PPC_CONTEXT_GPR_OFFSET( 29 )
     354#define PPC_CONTEXT_OFFSET_GPR30 PPC_CONTEXT_GPR_OFFSET( 30 )
     355#define PPC_CONTEXT_OFFSET_GPR31 PPC_CONTEXT_GPR_OFFSET( 31 )
    405356
    406357#ifndef ASM
Note: See TracChangeset for help on using the changeset viewer.