zt-test.S 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (C) 2021-2 ARM Limited.
  3. // Original author: Mark Brown <broonie@kernel.org>
  4. //
  5. // Scalable Matrix Extension ZT context switch test
  6. // Repeatedly writes unique test patterns into ZT0
  7. // and reads them back to verify integrity.
  8. #include <asm/unistd.h>
  9. #include "assembler.h"
  10. #include "asm-offsets.h"
  11. #include "sme-inst.h"
  12. .arch_extension sve
  13. #define ZT_SZ 512
  14. #define ZT_B (ZT_SZ / 8)
  15. // Declare some storage space to shadow ZT register contents and a
  16. // scratch buffer.
  17. .pushsection .text
  18. .data
  19. .align 4
  20. ztref:
  21. .space ZT_B
  22. scratch:
  23. .space ZT_B
  24. .popsection
  25. // Generate a test pattern for storage in ZT
  26. // x0: pid
  27. // x1: generation
  28. // These values are used to construct a 32-bit pattern that is repeated in the
  29. // scratch buffer as many times as will fit:
  30. // bits 31:24 generation number (increments once per test_loop)
  31. // bits 23: 8 pid
  32. // bits 7: 0 32-bit lane index
  33. function pattern
  34. mov w3, wzr
  35. bfi w3, w0, #8, #16 // PID
  36. bfi w3, w1, #24, #8 // Generation
  37. ldr x0, =scratch
  38. mov w1, #ZT_B / 4
  39. 0: str w3, [x0], #4
  40. add w3, w3, #1 // Lane
  41. subs w1, w1, #1
  42. b.ne 0b
  43. ret
  44. endfunction
  45. // Set up test pattern in a ZT horizontal vector
  46. // x0: pid
  47. // x1: generation
  48. function setup_zt
  49. mov x4, x30
  50. bl pattern // Get pattern in scratch buffer
  51. ldr x0, =ztref
  52. ldr x1, =scratch
  53. mov x2, #ZT_B
  54. bl memcpy
  55. ldr x0, =ztref
  56. _ldr_zt 0 // load zt0 from pointer x0
  57. ret x4
  58. endfunction
  59. // Trivial memory compare: compare x2 bytes starting at address x0 with
  60. // bytes starting at address x1.
  61. // Returns only if all bytes match; otherwise, the program is aborted.
  62. // Clobbers x0-x5.
  63. function memcmp
  64. cbz x2, 2f
  65. stp x0, x1, [sp, #-0x20]!
  66. str x2, [sp, #0x10]
  67. mov x5, #0
  68. 0: ldrb w3, [x0, x5]
  69. ldrb w4, [x1, x5]
  70. add x5, x5, #1
  71. cmp w3, w4
  72. b.ne 1f
  73. subs x2, x2, #1
  74. b.ne 0b
  75. 1: ldr x2, [sp, #0x10]
  76. ldp x0, x1, [sp], #0x20
  77. b.ne barf
  78. 2: ret
  79. endfunction
  80. // Verify that a ZT vector matches its shadow in memory, else abort
  81. // Clobbers x0-x3
  82. function check_zt
  83. mov x3, x30
  84. ldr x0, =scratch // Poison scratch
  85. mov x1, #ZT_B
  86. bl memfill_ae
  87. ldr x0, =scratch
  88. _str_zt 0
  89. ldr x0, =ztref
  90. ldr x1, =scratch
  91. mov x2, #ZT_B
  92. mov x30, x3
  93. b memcmp
  94. endfunction
  95. // Any SME register modified here can cause corruption in the main
  96. // thread -- but *only* the locations modified here.
  97. function irritator_handler
  98. // Increment the irritation signal count (x23):
  99. ldr x0, [x2, #ucontext_regs + 8 * 23]
  100. add x0, x0, #1
  101. str x0, [x2, #ucontext_regs + 8 * 23]
  102. // Corrupt some random ZT data
  103. #if 0
  104. adr x0, .text + (irritator_handler - .text) / 16 * 16
  105. movi v0.8b, #1
  106. movi v9.16b, #2
  107. movi v31.8b, #3
  108. #endif
  109. ret
  110. endfunction
  111. function tickle_handler
  112. // Increment the signal count (x23):
  113. ldr x0, [x2, #ucontext_regs + 8 * 23]
  114. add x0, x0, #1
  115. str x0, [x2, #ucontext_regs + 8 * 23]
  116. ret
  117. endfunction
  118. function terminate_handler
  119. mov w21, w0
  120. mov x20, x2
  121. puts "Terminated by signal "
  122. mov w0, w21
  123. bl putdec
  124. puts ", no error, iterations="
  125. ldr x0, [x20, #ucontext_regs + 8 * 22]
  126. bl putdec
  127. puts ", signals="
  128. ldr x0, [x20, #ucontext_regs + 8 * 23]
  129. bl putdecn
  130. mov x0, #0
  131. mov x8, #__NR_exit
  132. svc #0
  133. endfunction
  134. // w0: signal number
  135. // x1: sa_action
  136. // w2: sa_flags
  137. // Clobbers x0-x6,x8
  138. function setsignal
  139. str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
  140. mov w4, w0
  141. mov x5, x1
  142. mov w6, w2
  143. add x0, sp, #16
  144. mov x1, #sa_sz
  145. bl memclr
  146. mov w0, w4
  147. add x1, sp, #16
  148. str w6, [x1, #sa_flags]
  149. str x5, [x1, #sa_handler]
  150. mov x2, #0
  151. mov x3, #sa_mask_sz
  152. mov x8, #__NR_rt_sigaction
  153. svc #0
  154. cbz w0, 1f
  155. puts "sigaction failure\n"
  156. b .Labort
  157. 1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
  158. ret
  159. endfunction
  160. // Main program entry point
  161. .globl _start
  162. function _start
  163. mov x23, #0 // signal count
  164. mov w0, #SIGINT
  165. adr x1, terminate_handler
  166. mov w2, #SA_SIGINFO
  167. bl setsignal
  168. mov w0, #SIGTERM
  169. adr x1, terminate_handler
  170. mov w2, #SA_SIGINFO
  171. bl setsignal
  172. mov w0, #SIGUSR1
  173. adr x1, irritator_handler
  174. mov w2, #SA_SIGINFO
  175. orr w2, w2, #SA_NODEFER
  176. bl setsignal
  177. mov w0, #SIGUSR2
  178. adr x1, tickle_handler
  179. mov w2, #SA_SIGINFO
  180. orr w2, w2, #SA_NODEFER
  181. bl setsignal
  182. smstart_za
  183. // Obtain our PID, to ensure test pattern uniqueness between processes
  184. mov x8, #__NR_getpid
  185. svc #0
  186. mov x20, x0
  187. puts "PID:\t"
  188. mov x0, x20
  189. bl putdecn
  190. mov x22, #0 // generation number, increments per iteration
  191. .Ltest_loop:
  192. mov x0, x20
  193. mov x1, x22
  194. bl setup_zt
  195. mov x8, #__NR_sched_yield // Encourage preemption
  196. svc #0
  197. mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=1,SM=0
  198. and x1, x0, #3
  199. cmp x1, #2
  200. b.ne svcr_barf
  201. bl check_zt
  202. add x22, x22, #1 // Everything still working
  203. b .Ltest_loop
  204. .Labort:
  205. mov x0, #0
  206. mov x1, #SIGABRT
  207. mov x8, #__NR_kill
  208. svc #0
  209. endfunction
  210. function barf
  211. // fpsimd.c acitivty log dump hack
  212. // ldr w0, =0xdeadc0de
  213. // mov w8, #__NR_exit
  214. // svc #0
  215. // end hack
  216. mrs x13, S3_3_C4_C2_2
  217. smstop
  218. mov x10, x0 // expected data
  219. mov x11, x1 // actual data
  220. mov x12, x2 // data size
  221. puts "Mismatch: PID="
  222. mov x0, x20
  223. bl putdec
  224. puts ", iteration="
  225. mov x0, x22
  226. bl putdec
  227. puts "\tExpected ["
  228. mov x0, x10
  229. mov x1, x12
  230. bl dumphex
  231. puts "]\n\tGot ["
  232. mov x0, x11
  233. mov x1, x12
  234. bl dumphex
  235. puts "]\n"
  236. puts "\tSVCR: "
  237. mov x0, x13
  238. bl putdecn
  239. mov x8, #__NR_getpid
  240. svc #0
  241. // fpsimd.c acitivty log dump hack
  242. // ldr w0, =0xdeadc0de
  243. // mov w8, #__NR_exit
  244. // svc #0
  245. // ^ end of hack
  246. mov x1, #SIGABRT
  247. mov x8, #__NR_kill
  248. svc #0
  249. // mov x8, #__NR_exit
  250. // mov x1, #1
  251. // svc #0
  252. endfunction
  253. function svcr_barf
  254. mov x10, x0
  255. puts "Bad SVCR: "
  256. mov x0, x10
  257. bl putdecn
  258. mov x8, #__NR_exit
  259. mov x1, #1
  260. svc #0
  261. endfunction