Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
8.9 KiB

  1. //================ Copyright (c) Valve Corporation. All Rights Reserved. ===========================
  2. //
  3. // Raw SPU management
  4. //
  5. //==================================================================================================
  6. #ifndef INCLUDED_SPUMGR_PPU_H
  7. #define INCLUDED_SPUMGR_PPU_H
  8. //--------------------------------------------------------------------------------------------------
  9. // Headers
  10. //--------------------------------------------------------------------------------------------------
  11. #include <sys/spu_initialize.h>
  12. #include <sys/raw_spu.h>
  13. #include <sys/spu_utility.h>
  14. #include <sys/ppu_thread.h>
  15. #include <sys/interrupt.h>
  16. #include <sys/raw_spu.h>
  17. #include <sys/sys_time.h>
  18. #include <cell/spurs.h>
  19. //--------------------------------------------------------------------------------------------------
  20. //
  21. //--------------------------------------------------------------------------------------------------
  22. extern "C"
  23. {
  24. extern void (*g_snRawSPULockHandler) (void);
  25. extern void (*g_snRawSPUUnlockHandler) (void);
  26. extern void (*g_snRawSPUNotifyCreation) (unsigned int uID);
  27. extern void (*g_snRawSPUNotifyDestruction) (unsigned int uID);
  28. extern void (*g_snRawSPUNotifyElfLoad) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  29. extern void (*g_snRawSPUNotifyElfLoadNoWait) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  30. extern void (*g_snRawSPUNotifyElfLoadAbs) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  31. extern void (*g_snRawSPUNotifyElfLoadAbsNoWait) (unsigned int uID, unsigned int uEntry, const char *pFileName);
  32. extern void (*g_snRawSPUNotifySPUStopped) (unsigned int uID);
  33. extern void (*g_snRawSPUNotifySPUStarted) (unsigned int uID);
  34. };
  35. //--------------------------------------------------------------------------------------------------
  36. // Fwd refs
  37. //--------------------------------------------------------------------------------------------------
  38. class CellSpurs2;
  39. class SpuTaskHandle;
  40. //--------------------------------------------------------------------------------------------------
  41. // Defines
  42. //--------------------------------------------------------------------------------------------------
  43. #define MAX_RAW_SPUS 5
  44. // Class 2 Interrupt Status Register (INT_Stat_class2)
  45. // Described in CBE architecture v10 on page 259
  46. #define INTR_PPU_MB_SHIFT 0
  47. #define INTR_STOP_SHIFT 1
  48. #define INTR_HALT_SHIFT 2
  49. #define INTR_DMA_SHIFT 3
  50. #define INTR_SPU_MB_SHIFT 4
  51. #define INTR_PPU_MB_MASK (0x1 << INTR_PPU_MB_SHIFT)
  52. #define INTR_STOP_MASK (0x1 << INTR_STOP_SHIFT)
  53. #define INTR_HALT_MASK (0x1 << INTR_HALT_SHIFT)
  54. #define INTR_DMA_MASK (0x1 << INTR_DMA_SHIFT)
  55. #define INTR_SPU_MB_MASK (0x1 << INTR_SPU_MB_SHIFT)
  56. // thread priority for interrupt handler threads
  57. #define INTR_HANDLER_THREAD_PRIORITY 200
  58. #define INTR_HANDLER_THREAD_STACK_SIZE 0x4000
  59. #define SPUMGR_IS_ALIGNED(val, align) (((val) & ((align) - 1)) == 0)
  60. #define SPUMGR_ALIGN_UP(val, align) (((val) + ((align)-1)) & ~((align) - 1))
  61. #define SPUMGR_ALIGN_DOWN(val, align) ((val) & ~((align) - 1))
  62. //--------------------------------------------------------------------------------------------------
  63. // Overide sys_raw_spu_mmio_read / write, since they draw out another bug in SNC :(
  64. //--------------------------------------------------------------------------------------------------
  65. #define sys_raw_spu_mmio_read(spu, regoffset) spumgr_mmio_read(spu, regoffset)
  66. extern uint32_t spumgr_mmio_read(uint32_t spu, uint32_t regoffset);
  67. #define sys_raw_spu_mmio_write(spu, regoffset, value) spumgr_mmio_write(spu, regoffset, value)
  68. extern void spumgr_mmio_write(int id, int offset, uint32_t value);
  69. //--------------------------------------------------------------------------------------------------
  70. // Types
  71. //--------------------------------------------------------------------------------------------------
  72. typedef int CreateSPUTaskCallback(SpuTaskHandle *pTask);
  73. // SpuStatusRegister
  74. // Described in CBE architecture v10 on page 87
  75. typedef union SpuStatusRegister
  76. {
  77. struct
  78. {
  79. uint32_t m_sc : 16;
  80. uint32_t m_reserved2 : 5;
  81. uint32_t m_isolateExitStatus : 1;
  82. uint32_t m_isolateLoadStatus : 1;
  83. uint32_t m_reserved1 : 1;
  84. uint32_t m_isolationStatus : 1;
  85. uint32_t m_illegalChannelInstructionDetected : 1;
  86. uint32_t m_invalidInstructionDetected : 1;
  87. uint32_t m_singleStepStatus : 1;
  88. uint32_t m_waitStatus : 1;
  89. uint32_t m_haltStatus : 1;
  90. uint32_t m_programStopAndSignalStatus : 1;
  91. uint32_t m_runStatus : 1;
  92. };
  93. uint32_t m_val;
  94. } SpuStatusRegister;
  95. //--------------------------------------------------------------------------------------------------
  96. // Classes
  97. //--------------------------------------------------------------------------------------------------
  98. class SpuTaskHandle
  99. {
  100. public:
  101. sys_raw_spu_t m_spuId;
  102. sys_ppu_thread_t m_ppuThread;
  103. sys_interrupt_tag_t m_intrTag;
  104. sys_interrupt_thread_handle_t m_interruptThread;
  105. uint32_t m_lock;
  106. uint32_t m_memcpyLock;
  107. };
  108. //--------------------------------------------------------------------------------------------------
  109. // SpuMgr
  110. //
  111. // Provides functionality for running raw spu tasks. For this purpose it creates
  112. // and manages a raw spu pool
  113. //
  114. // Currently we assume a simple setup where app loads an elf on to a raw spu,
  115. // after which the spu starts running the elf and continues to do so thereafter.
  116. // The ppu->spu and spu->ppu communication is explicitly handled by the app
  117. // and the spu program using SpuMgr methods
  118. //
  119. // Currently all DMA transfer is supposed to be initiated by the SPUs which is
  120. // why SpuMgr does not provide any DMA functionality
  121. //--------------------------------------------------------------------------------------------------
  122. class SpuMgr
  123. {
  124. public:
  125. // Init/Term
  126. int Init(int numRawSpu);
  127. void Term();
  128. // Create/Destroy tasks
  129. int CreateSpuTask(const char *path, SpuTaskHandle *pTask, CreateSPUTaskCallback *pfnCallback = NULL);
  130. void DestroySpuTask(SpuTaskHandle *pTask);
  131. //
  132. // Helper functions to communicate with the SPU
  133. // As we build more functionality into the SPU mgr it is
  134. // possible that we will need to expose less of
  135. // these low-level functions
  136. //
  137. //
  138. // Mailbox functions
  139. //
  140. //
  141. // The SPU Inbound Mailbox is a 4-level FIFO structure for communication from the
  142. // PPU to SPU, and can hold up to four 32-bit messages.
  143. // If there are already four messages in the mailbox the last message will be
  144. // overwritten...but we can check for a full mailbox and prevent this
  145. int WriteMailbox(SpuTaskHandle *pTask, uint32_t val, bool bBlocking = true);
  146. // The SPU Outbound Mailbox can hold one 32-bit message for SPU-to-PPU communication.
  147. int ReadMailbox(SpuTaskHandle *pTask, uint32_t *pVal, bool bBlocking = true);
  148. // The SPU Outbound Interrupt Mailbox can hold one 32-bit message for SPU-to-PPU communication.
  149. int ReadIntrMailbox(SpuTaskHandle *pTask, uint32_t *pVal, bool bBlocking = true);
  150. //
  151. // Access to local store - note that this involves MMIO which will be slow
  152. // so need to use DMA instead for any significant data transfer. This
  153. // mechanism may be useful for writing some small amount of data such
  154. // as some constants etc into LS
  155. //
  156. int WriteLS(SpuTaskHandle *pTask, uint32_t lsOffset, void *pData, uint32_t size);
  157. int ReadLS(SpuTaskHandle *pTask, uint32_t lsOffset, void *pData, uint32_t size);
  158. bool Lock( SpuTaskHandle *pTask );
  159. void Unlock( SpuTaskHandle *pTask );
  160. bool MemcpyLock( SpuTaskHandle *pTask );
  161. void MemcpyUnlock( SpuTaskHandle *pTask );
  162. // CellSpurs2 m_exclusiveSpusSpurs; // SPURS instance running on SPUs used exclusively by the application
  163. // CellSpurs2 m_preemptedSpuSpurs; // SPURS instance running on an SPU shared with the OS (may be preempted by it occasionally)
  164. private:
  165. uint32_t m_numSpus;
  166. uint32_t m_spuInUse[MAX_RAW_SPUS];
  167. sys_raw_spu_t m_spuIds[MAX_RAW_SPUS];
  168. int ReadMailboxChannel(SpuTaskHandle *pTask, uint32_t *pVal,
  169. uint32_t countMask, uint32_t channel, bool bBlocking = true);
  170. };
  171. //--------------------------------------------------------------------------------------------------
  172. // Externs
  173. //--------------------------------------------------------------------------------------------------
  174. extern SpuMgr gSpuMgr;
  175. //--------------------------------------------------------------------------------------------------
  176. // DmaCheckAlignment
  177. // Checks restrictions specified in SpuMgr::DmaGet
  178. //--------------------------------------------------------------------------------------------------
  179. int DmaCheckAlignment(uint32_t src, uint32_t dest, uint32_t size);
  180. //--------------------------------------------------------------------------------------------------
  181. // GetStopSignal
  182. //--------------------------------------------------------------------------------------------------
  183. inline uint32_t GetStopSignal( sys_raw_spu_t idSpu )
  184. {
  185. SpuStatusRegister status;
  186. status.m_val = sys_raw_spu_mmio_read(idSpu, SPU_Status);
  187. uint32_t stopSignal = status.m_sc;
  188. return stopSignal;
  189. }
  190. #endif // INCLUDED_SPUMGR_PPU_H