test_emulate_step.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Simple sanity test for emulate_step load/store instructions.
  3. *
  4. * Copyright IBM Corp. 2016
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #define pr_fmt(fmt) "emulate_step_test: " fmt
  12. #include <linux/ptrace.h>
  13. #include <asm/sstep.h>
  14. #include <asm/ppc-opcode.h>
  15. #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
  16. /*
  17. * Defined with TEST_ prefix so it does not conflict with other
  18. * definitions.
  19. */
  20. #define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
  21. ___PPC_RA(base) | IMM_L(i))
  22. #define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
  23. ___PPC_RA(base) | IMM_L(i))
  24. #define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
  25. ___PPC_RA(a) | ___PPC_RB(b))
  26. #define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
  27. ___PPC_RA(base) | ((i) & 0xfffc))
  28. #define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
  29. ___PPC_RA(a) | ___PPC_RB(b) | \
  30. __PPC_EH(eh))
  31. #define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
  32. ___PPC_RA(a) | ___PPC_RB(b))
  33. #define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
  34. ___PPC_RA(a) | ___PPC_RB(b))
  35. #define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
  36. ___PPC_RA(a) | ___PPC_RB(b))
  37. #define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
  38. ___PPC_RA(a) | ___PPC_RB(b))
  39. #define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
  40. ___PPC_RA(a) | ___PPC_RB(b))
  41. #define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
  42. ___PPC_RA(a) | ___PPC_RB(b))
  43. #define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
  44. ___PPC_RA(a) | ___PPC_RB(b))
  45. #define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
  46. #define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
  47. static void __init init_pt_regs(struct pt_regs *regs)
  48. {
  49. static unsigned long msr;
  50. static bool msr_cached;
  51. memset(regs, 0, sizeof(struct pt_regs));
  52. if (likely(msr_cached)) {
  53. regs->msr = msr;
  54. return;
  55. }
  56. asm volatile("mfmsr %0" : "=r"(regs->msr));
  57. regs->msr |= MSR_FP;
  58. regs->msr |= MSR_VEC;
  59. regs->msr |= MSR_VSX;
  60. msr = regs->msr;
  61. msr_cached = true;
  62. }
  63. static void __init show_result(char *ins, char *result)
  64. {
  65. pr_info("%-14s : %s\n", ins, result);
  66. }
  67. static void __init test_ld(void)
  68. {
  69. struct pt_regs regs;
  70. unsigned long a = 0x23;
  71. int stepped = -1;
  72. init_pt_regs(&regs);
  73. regs.gpr[3] = (unsigned long) &a;
  74. /* ld r5, 0(r3) */
  75. stepped = emulate_step(&regs, TEST_LD(5, 3, 0));
  76. if (stepped == 1 && regs.gpr[5] == a)
  77. show_result("ld", "PASS");
  78. else
  79. show_result("ld", "FAIL");
  80. }
  81. static void __init test_lwz(void)
  82. {
  83. struct pt_regs regs;
  84. unsigned int a = 0x4545;
  85. int stepped = -1;
  86. init_pt_regs(&regs);
  87. regs.gpr[3] = (unsigned long) &a;
  88. /* lwz r5, 0(r3) */
  89. stepped = emulate_step(&regs, TEST_LWZ(5, 3, 0));
  90. if (stepped == 1 && regs.gpr[5] == a)
  91. show_result("lwz", "PASS");
  92. else
  93. show_result("lwz", "FAIL");
  94. }
  95. static void __init test_lwzx(void)
  96. {
  97. struct pt_regs regs;
  98. unsigned int a[3] = {0x0, 0x0, 0x1234};
  99. int stepped = -1;
  100. init_pt_regs(&regs);
  101. regs.gpr[3] = (unsigned long) a;
  102. regs.gpr[4] = 8;
  103. regs.gpr[5] = 0x8765;
  104. /* lwzx r5, r3, r4 */
  105. stepped = emulate_step(&regs, TEST_LWZX(5, 3, 4));
  106. if (stepped == 1 && regs.gpr[5] == a[2])
  107. show_result("lwzx", "PASS");
  108. else
  109. show_result("lwzx", "FAIL");
  110. }
  111. static void __init test_std(void)
  112. {
  113. struct pt_regs regs;
  114. unsigned long a = 0x1234;
  115. int stepped = -1;
  116. init_pt_regs(&regs);
  117. regs.gpr[3] = (unsigned long) &a;
  118. regs.gpr[5] = 0x5678;
  119. /* std r5, 0(r3) */
  120. stepped = emulate_step(&regs, TEST_STD(5, 3, 0));
  121. if (stepped == 1 || regs.gpr[5] == a)
  122. show_result("std", "PASS");
  123. else
  124. show_result("std", "FAIL");
  125. }
  126. static void __init test_ldarx_stdcx(void)
  127. {
  128. struct pt_regs regs;
  129. unsigned long a = 0x1234;
  130. int stepped = -1;
  131. unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
  132. init_pt_regs(&regs);
  133. asm volatile("mfcr %0" : "=r"(regs.ccr));
  134. /*** ldarx ***/
  135. regs.gpr[3] = (unsigned long) &a;
  136. regs.gpr[4] = 0;
  137. regs.gpr[5] = 0x5678;
  138. /* ldarx r5, r3, r4, 0 */
  139. stepped = emulate_step(&regs, TEST_LDARX(5, 3, 4, 0));
  140. /*
  141. * Don't touch 'a' here. Touching 'a' can do Load/store
  142. * of 'a' which result in failure of subsequent stdcx.
  143. * Instead, use hardcoded value for comparison.
  144. */
  145. if (stepped <= 0 || regs.gpr[5] != 0x1234) {
  146. show_result("ldarx / stdcx.", "FAIL (ldarx)");
  147. return;
  148. }
  149. /*** stdcx. ***/
  150. regs.gpr[5] = 0x9ABC;
  151. /* stdcx. r5, r3, r4 */
  152. stepped = emulate_step(&regs, TEST_STDCX(5, 3, 4));
  153. /*
  154. * Two possible scenarios that indicates successful emulation
  155. * of stdcx. :
  156. * 1. Reservation is active and store is performed. In this
  157. * case cr0.eq bit will be set to 1.
  158. * 2. Reservation is not active and store is not performed.
  159. * In this case cr0.eq bit will be set to 0.
  160. */
  161. if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
  162. || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
  163. show_result("ldarx / stdcx.", "PASS");
  164. else
  165. show_result("ldarx / stdcx.", "FAIL (stdcx.)");
  166. }
  167. #ifdef CONFIG_PPC_FPU
  168. static void __init test_lfsx_stfsx(void)
  169. {
  170. struct pt_regs regs;
  171. union {
  172. float a;
  173. int b;
  174. } c;
  175. int cached_b;
  176. int stepped = -1;
  177. init_pt_regs(&regs);
  178. /*** lfsx ***/
  179. c.a = 123.45;
  180. cached_b = c.b;
  181. regs.gpr[3] = (unsigned long) &c.a;
  182. regs.gpr[4] = 0;
  183. /* lfsx frt10, r3, r4 */
  184. stepped = emulate_step(&regs, TEST_LFSX(10, 3, 4));
  185. if (stepped == 1)
  186. show_result("lfsx", "PASS");
  187. else
  188. show_result("lfsx", "FAIL");
  189. /*** stfsx ***/
  190. c.a = 678.91;
  191. /* stfsx frs10, r3, r4 */
  192. stepped = emulate_step(&regs, TEST_STFSX(10, 3, 4));
  193. if (stepped == 1 && c.b == cached_b)
  194. show_result("stfsx", "PASS");
  195. else
  196. show_result("stfsx", "FAIL");
  197. }
  198. static void __init test_lfdx_stfdx(void)
  199. {
  200. struct pt_regs regs;
  201. union {
  202. double a;
  203. long b;
  204. } c;
  205. long cached_b;
  206. int stepped = -1;
  207. init_pt_regs(&regs);
  208. /*** lfdx ***/
  209. c.a = 123456.78;
  210. cached_b = c.b;
  211. regs.gpr[3] = (unsigned long) &c.a;
  212. regs.gpr[4] = 0;
  213. /* lfdx frt10, r3, r4 */
  214. stepped = emulate_step(&regs, TEST_LFDX(10, 3, 4));
  215. if (stepped == 1)
  216. show_result("lfdx", "PASS");
  217. else
  218. show_result("lfdx", "FAIL");
  219. /*** stfdx ***/
  220. c.a = 987654.32;
  221. /* stfdx frs10, r3, r4 */
  222. stepped = emulate_step(&regs, TEST_STFDX(10, 3, 4));
  223. if (stepped == 1 && c.b == cached_b)
  224. show_result("stfdx", "PASS");
  225. else
  226. show_result("stfdx", "FAIL");
  227. }
  228. #else
  229. static void __init test_lfsx_stfsx(void)
  230. {
  231. show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
  232. show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
  233. }
  234. static void __init test_lfdx_stfdx(void)
  235. {
  236. show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
  237. show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
  238. }
  239. #endif /* CONFIG_PPC_FPU */
  240. #ifdef CONFIG_ALTIVEC
  241. static void __init test_lvx_stvx(void)
  242. {
  243. struct pt_regs regs;
  244. union {
  245. vector128 a;
  246. u32 b[4];
  247. } c;
  248. u32 cached_b[4];
  249. int stepped = -1;
  250. init_pt_regs(&regs);
  251. /*** lvx ***/
  252. cached_b[0] = c.b[0] = 923745;
  253. cached_b[1] = c.b[1] = 2139478;
  254. cached_b[2] = c.b[2] = 9012;
  255. cached_b[3] = c.b[3] = 982134;
  256. regs.gpr[3] = (unsigned long) &c.a;
  257. regs.gpr[4] = 0;
  258. /* lvx vrt10, r3, r4 */
  259. stepped = emulate_step(&regs, TEST_LVX(10, 3, 4));
  260. if (stepped == 1)
  261. show_result("lvx", "PASS");
  262. else
  263. show_result("lvx", "FAIL");
  264. /*** stvx ***/
  265. c.b[0] = 4987513;
  266. c.b[1] = 84313948;
  267. c.b[2] = 71;
  268. c.b[3] = 498532;
  269. /* stvx vrs10, r3, r4 */
  270. stepped = emulate_step(&regs, TEST_STVX(10, 3, 4));
  271. if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
  272. cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
  273. show_result("stvx", "PASS");
  274. else
  275. show_result("stvx", "FAIL");
  276. }
  277. #else
  278. static void __init test_lvx_stvx(void)
  279. {
  280. show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
  281. show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
  282. }
  283. #endif /* CONFIG_ALTIVEC */
  284. #ifdef CONFIG_VSX
  285. static void __init test_lxvd2x_stxvd2x(void)
  286. {
  287. struct pt_regs regs;
  288. union {
  289. vector128 a;
  290. u32 b[4];
  291. } c;
  292. u32 cached_b[4];
  293. int stepped = -1;
  294. init_pt_regs(&regs);
  295. /*** lxvd2x ***/
  296. cached_b[0] = c.b[0] = 18233;
  297. cached_b[1] = c.b[1] = 34863571;
  298. cached_b[2] = c.b[2] = 834;
  299. cached_b[3] = c.b[3] = 6138911;
  300. regs.gpr[3] = (unsigned long) &c.a;
  301. regs.gpr[4] = 0;
  302. /* lxvd2x vsr39, r3, r4 */
  303. stepped = emulate_step(&regs, TEST_LXVD2X(39, 3, 4));
  304. if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
  305. show_result("lxvd2x", "PASS");
  306. } else {
  307. if (!cpu_has_feature(CPU_FTR_VSX))
  308. show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
  309. else
  310. show_result("lxvd2x", "FAIL");
  311. }
  312. /*** stxvd2x ***/
  313. c.b[0] = 21379463;
  314. c.b[1] = 87;
  315. c.b[2] = 374234;
  316. c.b[3] = 4;
  317. /* stxvd2x vsr39, r3, r4 */
  318. stepped = emulate_step(&regs, TEST_STXVD2X(39, 3, 4));
  319. if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
  320. cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
  321. cpu_has_feature(CPU_FTR_VSX)) {
  322. show_result("stxvd2x", "PASS");
  323. } else {
  324. if (!cpu_has_feature(CPU_FTR_VSX))
  325. show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
  326. else
  327. show_result("stxvd2x", "FAIL");
  328. }
  329. }
  330. #else
  331. static void __init test_lxvd2x_stxvd2x(void)
  332. {
  333. show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
  334. show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
  335. }
  336. #endif /* CONFIG_VSX */
  337. static int __init test_emulate_step(void)
  338. {
  339. test_ld();
  340. test_lwz();
  341. test_lwzx();
  342. test_std();
  343. test_ldarx_stdcx();
  344. test_lfsx_stfsx();
  345. test_lfdx_stfdx();
  346. test_lvx_stvx();
  347. test_lxvd2x_stxvd2x();
  348. return 0;
  349. }
  350. late_initcall(test_emulate_step);