archsup.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. archsup.S
  9. Abstract:
  10. This module implements ARMv7 processor architecture features not
  11. implementable in C.
  12. Author:
  13. Evan Green 11-Aug-2012
  14. Environment:
  15. Kernel mode
  16. --*/
  17. //
  18. // ------------------------------------------------------------------ Includes
  19. //
  20. #include <minoca/kernel/arm.inc>
  21. //
  22. // --------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ---------------------------------------------------------------------- Code
  26. //
  27. ASSEMBLY_FILE_HEADER
  28. //
  29. // VOID
  30. // ArCleanEntireCache (
  31. // VOID
  32. // )
  33. //
  34. /*++
  35. Routine Description:
  36. This routine cleans the entire data cache.
  37. Arguments:
  38. None.
  39. Return Value:
  40. None.
  41. --*/
  42. FUNCTION ArCleanEntireCache
  43. stmdb %sp!, {%r4-%r11} @ Save non-volatile registers.
  44. mrc p15, 1, %r0, c0, c0, 1 @ Read CLIDR into R0.
  45. ands %r3, %r0, #0x7000000 @
  46. mov %r3, %r3, LSR #23 @ Cache level value (naturally aligned).
  47. beq ArCleanEntireCacheEnd @
  48. mov %r10, #0 @
  49. ArCleanEntireCacheLoop1:
  50. add %r2, %r10, %r10, LSR #1 @ Work out 3 x cache level.
  51. mov %r1, %r0, LSR %r2 @ Bottom 3 bits are the Cache Type for
  52. and %r1, %r1, #7 @ this level. Get those 3 bits.
  53. cmp %r1, #2 @ Check to see if there's no cache or
  54. blt ArCleanEntireCacheSkip @ only instruction cache at this level.
  55. mcr p15, 2, %r10, c0, c0, 0 @ Write CSSELR from R10.
  56. ISB @ ISB to sync the change to CCSIDR.
  57. mrc p15, 1, %r1, c0, c0, 0 @ Read current CCSIDR
  58. and %r2, %r1, #7 @ Extract the line length field.
  59. add %r2, %r2, #4 @ Add 4 for the line length offset
  60. ldr %r4, =0x3FF @ (log2 16 bytes).
  61. ands %r4, %r4, %r1, LSR #3 @ R4 is the max number on the way size
  62. @ (right aligned).
  63. clz %r5, %r4 @ R5 is the bit position of way size
  64. @ increment.
  65. mov %r9, %r4 @ R9 is the working copy of the max way
  66. @ size (right aligned).
  67. ArCleanEntireCacheLoop2:
  68. ldr %r7, =0x00007FFF @
  69. ands %r7, %r7, %r1, LSR #13 @ R7 is the max number of the index size
  70. @ (right aligned).
  71. ArCleanEntireCacheLoop3:
  72. lsl %r11, %r9, %r5 @ Factor in the way number and cache
  73. orr %r11, %r10, %r11 @ number into R11.
  74. lsl %r4, %r7, %r2 @ Factor in the
  75. orr %r11, %r11, %r4 @ index number.
  76. mcr p15, 0, %r11, c7, c10, 2 @ DCCSW, clean by set/way.
  77. subs %r7, %r7, #1 @ Decrement the index.
  78. bge ArCleanEntireCacheLoop3 @
  79. subs %r9, %r9, #1 @ Decrement the way number.
  80. bge ArCleanEntireCacheLoop2 @
  81. ArCleanEntireCacheSkip:
  82. add %r10, %r10, #2 @ Increment the cache number.
  83. cmp %r3, %r10
  84. bgt ArCleanEntireCacheLoop1
  85. ArCleanEntireCacheEnd:
  86. mcr p15, 0, %r0, c7, c5, 0 @ Write to ICIALLU
  87. ldmia %sp!, {%r4-%r11} @ Restore non-volatile registers.
  88. DSB @ Data Synchronization barrier.
  89. bx %lr
  90. END_FUNCTION ArCleanEntireCache
  91. //
  92. // VOID
  93. // ArCleanInvalidateEntireCache (
  94. // VOID
  95. // )
  96. //
  97. /*++
  98. Routine Description:
  99. This routine cleans and invalidates the entire data cache.
  100. Arguments:
  101. None.
  102. Return Value:
  103. None.
  104. --*/
  105. FUNCTION ArCleanInvalidateEntireCache
  106. stmdb %sp!, {%r4-%r11} @ Save non-volatile registers.
  107. mrc p15, 1, %r0, c0, c0, 1 @ Read CLIDR into R0.
  108. ands %r3, %r0, #0x7000000 @
  109. mov %r3, %r3, LSR #23 @ Cache level value (naturally aligned).
  110. beq ArCleanInvalidateEntireCacheEnd @
  111. mov %r10, #0 @
  112. ArCleanInvalidateEntireCacheLoop1:
  113. add %r2, %r10, %r10, LSR #1 @ Work out 3 x cache level.
  114. mov %r1, %r0, LSR %r2 @ Bottom 3 bits are the Cache Type for
  115. and %r1, %r1, #7 @ this level. Get those 3 bits.
  116. cmp %r1, #2 @ Check to see if there's no cache at
  117. blt ArCleanInvalidateEntireCacheSkip @ this level.
  118. mcr p15, 2, %r10, c0, c0, 0 @ Write CSSELR from R10.
  119. ISB @ ISB to sync the change to CCSIDR.
  120. mrc p15, 1, %r1, c0, c0, 0 @ Read current CCSIDR
  121. and %r2, %r1, #7 @ Extract the line length field.
  122. add %r2, %r2, #4 @ Add 4 for the line length offset
  123. ldr %r4, =0x3FF @ (log2 16 bytes).
  124. ands %r4, %r4, %r1, LSR #3 @ R4 is the max number on the way size
  125. @ (right aligned).
  126. clz %r5, %r4 @ R5 is the bit position of way size
  127. @ increment.
  128. mov %r9, %r4 @ R9 is the working copy of the max way
  129. @ size (right aligned).
  130. ArCleanInvalidateEntireCacheLoop2:
  131. ldr %r7, =0x00007FFF @
  132. ands %r7, %r7, %r1, LSR #13 @ R7 is the max number of the index size
  133. @ (right aligned).
  134. ArCleanInvalidateEntireCacheLoop3:
  135. lsl %r11, %r9, %r5 @ Factor in the way number and cache
  136. orr %r11, %r10, %r11 @ number into R11.
  137. lsl %r4, %r7, %r2 @ Factor in the
  138. orr %r11, %r11, %r4 @ index number.
  139. mcr p15, 0, %r11, c7, c14, 2 @ DCCISW, clean and invalidate set/way.
  140. subs %r7, %r7, #1 @ Decrement the index.
  141. bge ArCleanInvalidateEntireCacheLoop3
  142. subs %r9, %r9, #1 @ Decrement the way number.
  143. bge ArCleanInvalidateEntireCacheLoop2
  144. ArCleanInvalidateEntireCacheSkip:
  145. add %r10, %r10, #2 @ Increment the cache number.
  146. cmp %r3, %r10
  147. bgt ArCleanInvalidateEntireCacheLoop1
  148. ArCleanInvalidateEntireCacheEnd:
  149. mcr p15, 0, %r0, c7, c5, 0 @ Write to ICIALLU
  150. DSB
  151. ldmia %sp!, {%r4-%r11} @ Restore non-volatile registers.
  152. bx %lr
  153. END_FUNCTION ArCleanInvalidateEntireCache
  154. //
  155. // ULONG
  156. // ArGetMultiprocessorIdRegister (
  157. // VOID
  158. // )
  159. //
  160. /*++
  161. Routine Description:
  162. This routine gets the Multiprocessor ID register (MPIDR).
  163. Arguments:
  164. None.
  165. Return Value:
  166. Returns the value of the MPIDR.
  167. --*/
  168. FUNCTION ArGetMultiprocessorIdRegister
  169. mrc p15, 0, %r0, %c0, %c0, 5 @ Get the MPIDR
  170. bx %lr @
  171. END_FUNCTION ArGetMultiprocessorIdRegister
  172. //
  173. // ULONG
  174. // ArGetPerformanceControlRegister (
  175. // VOID
  176. // )
  177. //
  178. /*++
  179. Routine Description:
  180. This routine retrieves the PMCR (Performance Monitor Control Register).
  181. Arguments:
  182. None.
  183. Return Value:
  184. Returns the value of the PMCR.
  185. --*/
  186. FUNCTION ArGetPerformanceControlRegister
  187. mrc p15, 0, %r0, %c9, %c12, 0 @ Get the PMCR.
  188. bx %lr @
  189. END_FUNCTION ArGetPerformanceControlRegister
  190. //
  191. // VOID
  192. // ArSetPerformanceControlRegister (
  193. // ULONG Value
  194. // )
  195. //
  196. /*++
  197. Routine Description:
  198. This routine sets the PMCR (Performance Monitor Control Register).
  199. Arguments:
  200. Value - Supplies the value to set in the PMCR.
  201. Return Value:
  202. None.
  203. --*/
  204. FUNCTION ArSetPerformanceControlRegister
  205. mcr p15, 0, %r0, %c9, %c12, 0 @ Set the PMCR.
  206. bx %lr @
  207. END_FUNCTION ArSetPerformanceControlRegister
  208. //
  209. // VOID
  210. // ArClearPerformanceInterruptRegister (
  211. // ULONG Value
  212. // )
  213. //
  214. /*++
  215. Routine Description:
  216. This routine sets the PMINTENCLR (Performance Monitor Interrupt Clear)
  217. register.
  218. Arguments:
  219. Value - Supplies the value to set in the PMINTENCLR.
  220. Return Value:
  221. None.
  222. --*/
  223. FUNCTION ArClearPerformanceInterruptRegister
  224. mcr p15, 0, %r0, %c9, %c14, 2 @ Set the PMINTENCLR.
  225. bx %lr @
  226. END_FUNCTION ArClearPerformanceInterruptRegister
  227. //
  228. // VOID
  229. // ArSetPerformanceUserEnableRegister (
  230. // ULONG Value
  231. // )
  232. //
  233. /*++
  234. Routine Description:
  235. This routine sets the PMUSERENR (Performance Monitor User Enable Register).
  236. Arguments:
  237. Value - Supplies the value to set in the PMUSERENR.
  238. Return Value:
  239. None.
  240. --*/
  241. FUNCTION ArSetPerformanceUserEnableRegister
  242. mcr p15, 0, %r0, %c9, %c14, 0 @ Set the PMUSERENR.
  243. bx %lr @
  244. END_FUNCTION ArSetPerformanceUserEnableRegister
  245. //
  246. // ULONG
  247. // ArGetPerformanceCounterEnableRegister (
  248. // VOID
  249. // )
  250. //
  251. /*++
  252. Routine Description:
  253. This routine retrieves the PMCNTENSET (Performance Monitor Counter Enable
  254. Set) register.
  255. Arguments:
  256. None.
  257. Return Value:
  258. Returns the value of the PMCNTENSET.
  259. --*/
  260. FUNCTION ArGetPerformanceCounterEnableRegister
  261. mrc p15, 0, %r0, %c9, %c12, 1 @ Get the PMCNTENSET register.
  262. bx %lr @
  263. END_FUNCTION ArGetPerformanceCounterEnableRegister
  264. //
  265. // VOID
  266. // ArSetCycleCountEnableRegister (
  267. // ULONG Value
  268. // )
  269. //
  270. /*++
  271. Routine Description:
  272. This routine sets the PMCNTENSET (Performance Monitor Counter Enable
  273. Set) register.
  274. Arguments:
  275. Value - Supplies the value to set in the PMCNTENSET register.
  276. Return Value:
  277. None.
  278. --*/
  279. FUNCTION ArSetPerformanceCounterEnableRegister
  280. mcr p15, 0, %r0, %c9, %c12, 1 @ Set the PMCNTENSET register.
  281. bx %lr @
  282. END_FUNCTION ArSetPerformanceCounterEnableRegister
  283. //
  284. // ULONG
  285. // ArGetCycleCountRegister (
  286. // VOID
  287. // )
  288. //
  289. /*++
  290. Routine Description:
  291. This routine retrieves the PMCCNTR (Performance Monitor Cycle Counter)
  292. register.
  293. Arguments:
  294. None.
  295. Return Value:
  296. Returns the value of the PMCCNTR.
  297. --*/
  298. FUNCTION ArGetCycleCountRegister
  299. mrc p15, 0, %r0, %c9, %c13, 0 @ Get the PMCCNTR register.
  300. bx %lr @
  301. END_FUNCTION ArGetCycleCountRegister
  302. //
  303. // VOID
  304. // ArSetCycleCountRegister (
  305. // ULONG Value
  306. // )
  307. //
  308. /*++
  309. Routine Description:
  310. This routine sets the PMCCNTR (Performance Monitor Cycle Counter) register.
  311. Arguments:
  312. Value - Supplies the value to set in the PMCCNTR register.
  313. Return Value:
  314. None.
  315. --*/
  316. FUNCTION ArSetCycleCountRegister
  317. mcr p15, 0, %r0, %c9, %c13, 0 @ Set the PMCCNTR register.
  318. bx %lr @
  319. END_FUNCTION ArSetCycleCountRegister
  320. //
  321. // --------------------------------------------------------- Internal Functions
  322. //