Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * utils.h: Utilities for SPU-side of the context switch operation.
0004  *
0005  * (C) Copyright IBM 2005
0006  */
0007 
0008 #ifndef _SPU_CONTEXT_UTILS_H_
0009 #define _SPU_CONTEXT_UTILS_H_
0010 
0011 /*
0012  * 64-bit safe EA.
0013  */
0014 typedef union {
0015     unsigned long long ull;
0016     unsigned int ui[2];
0017 } addr64;
0018 
0019 /*
0020  * 128-bit register template.
0021  */
0022 typedef union {
0023     unsigned int slot[4];
0024     vector unsigned int v;
0025 } spu_reg128v;
0026 
0027 /*
0028  * DMA list structure.
0029  */
0030 struct dma_list_elem {
0031     unsigned int size;
0032     unsigned int ea_low;
0033 };
0034 
0035 /*
0036  * Declare storage for 8-byte aligned DMA list.
0037  */
0038 struct dma_list_elem dma_list[15] __attribute__ ((aligned(8)));
0039 
0040 /*
0041  * External definition for storage
0042  * declared in crt0.
0043  */
0044 extern spu_reg128v regs_spill[NR_SPU_SPILL_REGS];
0045 
0046 /*
0047  * Compute LSCSA byte offset for a given field.
0048  */
0049 static struct spu_lscsa *dummy = (struct spu_lscsa *)0;
0050 #define LSCSA_BYTE_OFFSET(_field)  \
0051     ((char *)(&(dummy->_field)) - (char *)(&(dummy->gprs[0].slot[0])))
0052 #define LSCSA_QW_OFFSET(_field)  (LSCSA_BYTE_OFFSET(_field) >> 4)
0053 
0054 static inline void set_event_mask(void)
0055 {
0056     unsigned int event_mask = 0;
0057 
0058     /* Save, Step 4:
0059      * Restore, Step 1:
0060      *    Set the SPU_RdEventMsk channel to zero to mask
0061      *    all events.
0062      */
0063     spu_writech(SPU_WrEventMask, event_mask);
0064 }
0065 
0066 static inline void set_tag_mask(void)
0067 {
0068     unsigned int tag_mask = 1;
0069 
0070     /* Save, Step 5:
0071      * Restore, Step 2:
0072      *    Set the SPU_WrTagMsk channel to '01' to unmask
0073      *    only tag group 0.
0074      */
0075     spu_writech(MFC_WrTagMask, tag_mask);
0076 }
0077 
0078 static inline void build_dma_list(addr64 lscsa_ea)
0079 {
0080     unsigned int ea_low;
0081     int i;
0082 
0083     /* Save, Step 6:
0084      * Restore, Step 3:
0085      *    Update the effective address for the CSA in the
0086      *    pre-canned DMA-list in local storage.
0087      */
0088     ea_low = lscsa_ea.ui[1];
0089     ea_low += LSCSA_BYTE_OFFSET(ls[16384]);
0090 
0091     for (i = 0; i < 15; i++, ea_low += 16384) {
0092         dma_list[i].size = 16384;
0093         dma_list[i].ea_low = ea_low;
0094     }
0095 }
0096 
0097 static inline void enqueue_putllc(addr64 lscsa_ea)
0098 {
0099     unsigned int ls = 0;
0100     unsigned int size = 128;
0101     unsigned int tag_id = 0;
0102     unsigned int cmd = 0xB4;    /* PUTLLC */
0103 
0104     /* Save, Step 12:
0105      * Restore, Step 7:
0106      *    Send a PUTLLC (tag 0) command to the MFC using
0107      *    an effective address in the CSA in order to
0108      *    remove any possible lock-line reservation.
0109      */
0110     spu_writech(MFC_LSA, ls);
0111     spu_writech(MFC_EAH, lscsa_ea.ui[0]);
0112     spu_writech(MFC_EAL, lscsa_ea.ui[1]);
0113     spu_writech(MFC_Size, size);
0114     spu_writech(MFC_TagID, tag_id);
0115     spu_writech(MFC_Cmd, cmd);
0116 }
0117 
0118 static inline void set_tag_update(void)
0119 {
0120     unsigned int update_any = 1;
0121 
0122     /* Save, Step 15:
0123      * Restore, Step 8:
0124      *    Write the MFC_TagUpdate channel with '01'.
0125      */
0126     spu_writech(MFC_WrTagUpdate, update_any);
0127 }
0128 
0129 static inline void read_tag_status(void)
0130 {
0131     /* Save, Step 16:
0132      * Restore, Step 9:
0133      *    Read the MFC_TagStat channel data.
0134      */
0135     spu_readch(MFC_RdTagStat);
0136 }
0137 
0138 static inline void read_llar_status(void)
0139 {
0140     /* Save, Step 17:
0141      * Restore, Step 10:
0142      *    Read the MFC_AtomicStat channel data.
0143      */
0144     spu_readch(MFC_RdAtomicStat);
0145 }
0146 
0147 #endif              /* _SPU_CONTEXT_UTILS_H_ */