alignment_handler.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Test the powerpc alignment handler on POWER8/POWER9
  4. *
  5. * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
  6. */
  7. /*
  8. * This selftest exercises the powerpc alignment fault handler.
  9. *
  10. * We create two sets of source and destination buffers, one in regular memory,
  11. * the other cache-inhibited (by default we use /dev/fb0 for this, but an
  12. * alterative path for cache-inhibited memory may be provided, e.g. memtrace).
  13. *
  14. * We initialise the source buffers, then use whichever set of load/store
  15. * instructions is under test to copy bytes from the source buffers to the
  16. * destination buffers. For the regular buffers, these instructions will
  17. * execute normally. For the cache-inhibited buffers, these instructions
  18. * will trap and cause an alignment fault, and the alignment fault handler
  19. * will emulate the particular instruction under test. We then compare the
  20. * destination buffers to ensure that the native and emulated cases give the
  21. * same result.
  22. *
  23. * TODO:
  24. * - Any FIXMEs below
  25. * - Test VSX regs < 32 and > 32
  26. * - Test all loads and stores
  27. * - Check update forms do update register
  28. * - Test alignment faults over page boundary
  29. *
  30. * Some old binutils may not support all the instructions.
  31. */
  32. #include <sys/mman.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <unistd.h>
  37. #include <stdbool.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <assert.h>
  42. #include <getopt.h>
  43. #include <setjmp.h>
  44. #include <signal.h>
  45. #include "utils.h"
  46. #include "instructions.h"
  47. int bufsize;
  48. int debug;
  49. int testing;
  50. volatile int gotsig;
  51. bool prefixes_enabled;
  52. char *cipath = "/dev/fb0";
  53. long cioffset;
  54. void sighandler(int sig, siginfo_t *info, void *ctx)
  55. {
  56. ucontext_t *ucp = ctx;
  57. if (!testing) {
  58. signal(sig, SIG_DFL);
  59. kill(0, sig);
  60. }
  61. gotsig = sig;
  62. #ifdef __powerpc64__
  63. if (prefixes_enabled) {
  64. u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP];
  65. ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4);
  66. } else {
  67. ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
  68. }
  69. #else
  70. ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
  71. #endif
  72. }
  73. #define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
  74. #define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
  75. #define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
  76. void test_##name(char *s, char *d) \
  77. { \
  78. asm volatile( \
  79. #ld_op form(ld_reg, 0) \
  80. #st_op form(st_reg, 1) \
  81. :: "r"(s), "r"(d), "r"(0) \
  82. : "memory", "vs0", "vs32", "r31"); \
  83. } \
  84. rc |= do_test(#name, test_##name)
  85. #define TESTP(name, ld_op, st_op, ld_reg, st_reg) \
  86. void test_##name(char *s, char *d) \
  87. { \
  88. asm volatile( \
  89. ld_op(ld_reg, %0, 0, 0) \
  90. st_op(st_reg, %1, 0, 0) \
  91. :: "r"(s), "r"(d), "r"(0) \
  92. : "memory", "vs0", "vs32", "r31"); \
  93. } \
  94. rc |= do_test(#name, test_##name)
  95. #define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
  96. #define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
  97. #define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
  98. #define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
  99. #define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
  100. #define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
  101. #define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
  102. #define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
  103. #define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
  104. #define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
  105. #define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
  106. #define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
  107. #define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
  108. #define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
  109. #define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
  110. #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
  111. #define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
  112. #define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
  113. #define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
  114. #define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
  115. #define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0)
  116. #define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0)
  117. #define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32)
  118. #define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0)
  119. /* FIXME: Unimplemented tests: */
  120. // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
  121. // STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
  122. // STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
  123. // STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
  124. /* preload byte by byte */
  125. void preload_data(void *dst, int offset, int width)
  126. {
  127. char *c = dst;
  128. int i;
  129. c += offset;
  130. for (i = 0 ; i < width ; i++)
  131. c[i] = i;
  132. }
  133. int test_memcpy(void *dst, void *src, int size, int offset,
  134. void (*test_func)(char *, char *))
  135. {
  136. char *s, *d;
  137. s = src;
  138. s += offset;
  139. d = dst;
  140. d += offset;
  141. assert(size == 16);
  142. gotsig = 0;
  143. testing = 1;
  144. test_func(s, d); /* run the actual test */
  145. testing = 0;
  146. if (gotsig) {
  147. if (debug)
  148. printf(" Got signal %i\n", gotsig);
  149. return 1;
  150. }
  151. return 0;
  152. }
  153. void dumpdata(char *s1, char *s2, int n, char *test_name)
  154. {
  155. int i;
  156. printf(" %s: unexpected result:\n", test_name);
  157. printf(" mem:");
  158. for (i = 0; i < n; i++)
  159. printf(" %02x", s1[i]);
  160. printf("\n");
  161. printf(" ci: ");
  162. for (i = 0; i < n; i++)
  163. printf(" %02x", s2[i]);
  164. printf("\n");
  165. }
  166. int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name)
  167. {
  168. char *s1c, *s2c;
  169. s1c = s1;
  170. s1c += offset;
  171. s2c = s2;
  172. s2c += offset;
  173. if (memcmp(s1c, s2c, n)) {
  174. if (debug) {
  175. printf("\n Compare failed. Offset:%i length:%i\n",
  176. offset, n);
  177. dumpdata(s1c, s2c, n, test_name);
  178. }
  179. return 1;
  180. }
  181. return 0;
  182. }
  183. /*
  184. * Do two memcpy tests using the same instructions. One cachable
  185. * memory and the other doesn't.
  186. */
  187. int do_test(char *test_name, void (*test_func)(char *, char *))
  188. {
  189. int offset, width, fd, rc, r;
  190. void *mem0, *mem1, *ci0, *ci1;
  191. printf("\tDoing %s:\t", test_name);
  192. fd = open(cipath, O_RDWR);
  193. if (fd < 0) {
  194. printf("\n");
  195. perror("Can't open ci file now?");
  196. return 1;
  197. }
  198. ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
  199. fd, cioffset);
  200. ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED,
  201. fd, cioffset + bufsize);
  202. if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
  203. printf("\n");
  204. perror("mmap failed");
  205. SKIP_IF(1);
  206. }
  207. rc = posix_memalign(&mem0, bufsize, bufsize);
  208. if (rc) {
  209. printf("\n");
  210. return rc;
  211. }
  212. rc = posix_memalign(&mem1, bufsize, bufsize);
  213. if (rc) {
  214. printf("\n");
  215. free(mem0);
  216. return rc;
  217. }
  218. rc = 0;
  219. /*
  220. * offset = 0 is aligned but tests the workaround for the P9N
  221. * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s:
  222. * Add workaround for P9 vector CI load issue")
  223. */
  224. for (offset = 0; offset < 16; offset++) {
  225. width = 16; /* vsx == 16 bytes */
  226. r = 0;
  227. /* load pattern into memory byte by byte */
  228. preload_data(ci0, offset, width);
  229. preload_data(mem0, offset, width); // FIXME: remove??
  230. memcpy(ci0, mem0, bufsize);
  231. memcpy(ci1, mem1, bufsize); /* initialise output to the same */
  232. /* sanity check */
  233. test_memcmp(mem0, ci0, width, offset, test_name);
  234. r |= test_memcpy(ci1, ci0, width, offset, test_func);
  235. r |= test_memcpy(mem1, mem0, width, offset, test_func);
  236. if (r && !debug) {
  237. printf("FAILED: Got signal");
  238. rc = 1;
  239. break;
  240. }
  241. r |= test_memcmp(mem1, ci1, width, offset, test_name);
  242. if (r && !debug) {
  243. printf("FAILED: Wrong Data");
  244. rc = 1;
  245. break;
  246. }
  247. }
  248. if (rc == 0)
  249. printf("PASSED");
  250. printf("\n");
  251. munmap(ci0, bufsize);
  252. munmap(ci1, bufsize);
  253. free(mem0);
  254. free(mem1);
  255. close(fd);
  256. return rc;
  257. }
  258. static bool can_open_cifile(void)
  259. {
  260. int fd;
  261. fd = open(cipath, O_RDWR);
  262. if (fd < 0)
  263. return false;
  264. close(fd);
  265. return true;
  266. }
  267. int test_alignment_handler_vsx_206(void)
  268. {
  269. int rc = 0;
  270. SKIP_IF(!can_open_cifile());
  271. SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
  272. printf("VSX: 2.06B\n");
  273. LOAD_VSX_XFORM_TEST(lxvd2x);
  274. LOAD_VSX_XFORM_TEST(lxvw4x);
  275. LOAD_VSX_XFORM_TEST(lxsdx);
  276. LOAD_VSX_XFORM_TEST(lxvdsx);
  277. STORE_VSX_XFORM_TEST(stxvd2x);
  278. STORE_VSX_XFORM_TEST(stxvw4x);
  279. STORE_VSX_XFORM_TEST(stxsdx);
  280. return rc;
  281. }
  282. int test_alignment_handler_vsx_207(void)
  283. {
  284. int rc = 0;
  285. SKIP_IF(!can_open_cifile());
  286. SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
  287. printf("VSX: 2.07B\n");
  288. LOAD_VSX_XFORM_TEST(lxsspx);
  289. LOAD_VSX_XFORM_TEST(lxsiwax);
  290. LOAD_VSX_XFORM_TEST(lxsiwzx);
  291. STORE_VSX_XFORM_TEST(stxsspx);
  292. STORE_VSX_XFORM_TEST(stxsiwx);
  293. return rc;
  294. }
  295. int test_alignment_handler_vsx_300(void)
  296. {
  297. int rc = 0;
  298. SKIP_IF(!can_open_cifile());
  299. SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
  300. printf("VSX: 3.00B\n");
  301. LOAD_VMX_DFORM_TEST(lxsd);
  302. LOAD_VSX_XFORM_TEST(lxsibzx);
  303. LOAD_VSX_XFORM_TEST(lxsihzx);
  304. LOAD_VMX_DFORM_TEST(lxssp);
  305. LOAD_VSX_DFORM_TEST(lxv);
  306. LOAD_VSX_XFORM_TEST(lxvb16x);
  307. LOAD_VSX_XFORM_TEST(lxvh8x);
  308. LOAD_VSX_XFORM_TEST(lxvx);
  309. LOAD_VSX_XFORM_TEST(lxvwsx);
  310. LOAD_VSX_XFORM_TEST(lxvl);
  311. LOAD_VSX_XFORM_TEST(lxvll);
  312. STORE_VMX_DFORM_TEST(stxsd);
  313. STORE_VSX_XFORM_TEST(stxsibx);
  314. STORE_VSX_XFORM_TEST(stxsihx);
  315. STORE_VMX_DFORM_TEST(stxssp);
  316. STORE_VSX_DFORM_TEST(stxv);
  317. STORE_VSX_XFORM_TEST(stxvb16x);
  318. STORE_VSX_XFORM_TEST(stxvh8x);
  319. STORE_VSX_XFORM_TEST(stxvx);
  320. STORE_VSX_XFORM_TEST(stxvl);
  321. STORE_VSX_XFORM_TEST(stxvll);
  322. return rc;
  323. }
  324. int test_alignment_handler_vsx_prefix(void)
  325. {
  326. int rc = 0;
  327. SKIP_IF(!can_open_cifile());
  328. SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
  329. printf("VSX: PREFIX\n");
  330. LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0);
  331. LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0);
  332. LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0);
  333. LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1);
  334. STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0);
  335. STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0);
  336. STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0);
  337. STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1);
  338. return rc;
  339. }
  340. int test_alignment_handler_integer(void)
  341. {
  342. int rc = 0;
  343. SKIP_IF(!can_open_cifile());
  344. printf("Integer\n");
  345. LOAD_DFORM_TEST(lbz);
  346. LOAD_DFORM_TEST(lbzu);
  347. LOAD_XFORM_TEST(lbzx);
  348. LOAD_XFORM_TEST(lbzux);
  349. LOAD_DFORM_TEST(lhz);
  350. LOAD_DFORM_TEST(lhzu);
  351. LOAD_XFORM_TEST(lhzx);
  352. LOAD_XFORM_TEST(lhzux);
  353. LOAD_DFORM_TEST(lha);
  354. LOAD_DFORM_TEST(lhau);
  355. LOAD_XFORM_TEST(lhax);
  356. LOAD_XFORM_TEST(lhaux);
  357. LOAD_XFORM_TEST(lhbrx);
  358. LOAD_DFORM_TEST(lwz);
  359. LOAD_DFORM_TEST(lwzu);
  360. LOAD_XFORM_TEST(lwzx);
  361. LOAD_XFORM_TEST(lwzux);
  362. LOAD_DFORM_TEST(lwa);
  363. LOAD_XFORM_TEST(lwax);
  364. LOAD_XFORM_TEST(lwaux);
  365. LOAD_XFORM_TEST(lwbrx);
  366. LOAD_DFORM_TEST(ld);
  367. LOAD_DFORM_TEST(ldu);
  368. LOAD_XFORM_TEST(ldx);
  369. LOAD_XFORM_TEST(ldux);
  370. STORE_DFORM_TEST(stb);
  371. STORE_XFORM_TEST(stbx);
  372. STORE_DFORM_TEST(stbu);
  373. STORE_XFORM_TEST(stbux);
  374. STORE_DFORM_TEST(sth);
  375. STORE_XFORM_TEST(sthx);
  376. STORE_DFORM_TEST(sthu);
  377. STORE_XFORM_TEST(sthux);
  378. STORE_XFORM_TEST(sthbrx);
  379. STORE_DFORM_TEST(stw);
  380. STORE_XFORM_TEST(stwx);
  381. STORE_DFORM_TEST(stwu);
  382. STORE_XFORM_TEST(stwux);
  383. STORE_XFORM_TEST(stwbrx);
  384. STORE_DFORM_TEST(std);
  385. STORE_XFORM_TEST(stdx);
  386. STORE_DFORM_TEST(stdu);
  387. STORE_XFORM_TEST(stdux);
  388. #ifdef __BIG_ENDIAN__
  389. LOAD_DFORM_TEST(lmw);
  390. STORE_DFORM_TEST(stmw);
  391. #endif
  392. return rc;
  393. }
  394. int test_alignment_handler_integer_206(void)
  395. {
  396. int rc = 0;
  397. SKIP_IF(!can_open_cifile());
  398. SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
  399. printf("Integer: 2.06\n");
  400. LOAD_XFORM_TEST(ldbrx);
  401. STORE_XFORM_TEST(stdbrx);
  402. return rc;
  403. }
  404. int test_alignment_handler_integer_prefix(void)
  405. {
  406. int rc = 0;
  407. SKIP_IF(!can_open_cifile());
  408. SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
  409. printf("Integer: PREFIX\n");
  410. LOAD_MLS_PREFIX_TEST(PLBZ);
  411. LOAD_MLS_PREFIX_TEST(PLHZ);
  412. LOAD_MLS_PREFIX_TEST(PLHA);
  413. LOAD_MLS_PREFIX_TEST(PLWZ);
  414. LOAD_8LS_PREFIX_TEST(PLWA);
  415. LOAD_8LS_PREFIX_TEST(PLD);
  416. STORE_MLS_PREFIX_TEST(PSTB);
  417. STORE_MLS_PREFIX_TEST(PSTH);
  418. STORE_MLS_PREFIX_TEST(PSTW);
  419. STORE_8LS_PREFIX_TEST(PSTD);
  420. return rc;
  421. }
  422. int test_alignment_handler_vmx(void)
  423. {
  424. int rc = 0;
  425. SKIP_IF(!can_open_cifile());
  426. SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC));
  427. printf("VMX\n");
  428. LOAD_VMX_XFORM_TEST(lvx);
  429. /*
  430. * FIXME: These loads only load part of the register, so our
  431. * testing method doesn't work. Also they don't take alignment
  432. * faults, so it's kinda pointless anyway
  433. *
  434. LOAD_VMX_XFORM_TEST(lvebx)
  435. LOAD_VMX_XFORM_TEST(lvehx)
  436. LOAD_VMX_XFORM_TEST(lvewx)
  437. LOAD_VMX_XFORM_TEST(lvxl)
  438. */
  439. STORE_VMX_XFORM_TEST(stvx);
  440. STORE_VMX_XFORM_TEST(stvebx);
  441. STORE_VMX_XFORM_TEST(stvehx);
  442. STORE_VMX_XFORM_TEST(stvewx);
  443. STORE_VMX_XFORM_TEST(stvxl);
  444. return rc;
  445. }
  446. int test_alignment_handler_fp(void)
  447. {
  448. int rc = 0;
  449. SKIP_IF(!can_open_cifile());
  450. printf("Floating point\n");
  451. LOAD_FLOAT_DFORM_TEST(lfd);
  452. LOAD_FLOAT_XFORM_TEST(lfdx);
  453. LOAD_FLOAT_DFORM_TEST(lfdu);
  454. LOAD_FLOAT_XFORM_TEST(lfdux);
  455. LOAD_FLOAT_DFORM_TEST(lfs);
  456. LOAD_FLOAT_XFORM_TEST(lfsx);
  457. LOAD_FLOAT_DFORM_TEST(lfsu);
  458. LOAD_FLOAT_XFORM_TEST(lfsux);
  459. STORE_FLOAT_DFORM_TEST(stfd);
  460. STORE_FLOAT_XFORM_TEST(stfdx);
  461. STORE_FLOAT_DFORM_TEST(stfdu);
  462. STORE_FLOAT_XFORM_TEST(stfdux);
  463. STORE_FLOAT_DFORM_TEST(stfs);
  464. STORE_FLOAT_XFORM_TEST(stfsx);
  465. STORE_FLOAT_DFORM_TEST(stfsu);
  466. STORE_FLOAT_XFORM_TEST(stfsux);
  467. STORE_FLOAT_XFORM_TEST(stfiwx);
  468. return rc;
  469. }
  470. int test_alignment_handler_fp_205(void)
  471. {
  472. int rc = 0;
  473. SKIP_IF(!can_open_cifile());
  474. SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05));
  475. printf("Floating point: 2.05\n");
  476. LOAD_FLOAT_DFORM_TEST(lfdp);
  477. LOAD_FLOAT_XFORM_TEST(lfdpx);
  478. LOAD_FLOAT_XFORM_TEST(lfiwax);
  479. STORE_FLOAT_DFORM_TEST(stfdp);
  480. STORE_FLOAT_XFORM_TEST(stfdpx);
  481. return rc;
  482. }
  483. int test_alignment_handler_fp_206(void)
  484. {
  485. int rc = 0;
  486. SKIP_IF(!can_open_cifile());
  487. SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
  488. printf("Floating point: 2.06\n");
  489. LOAD_FLOAT_XFORM_TEST(lfiwzx);
  490. return rc;
  491. }
  492. int test_alignment_handler_fp_prefix(void)
  493. {
  494. int rc = 0;
  495. SKIP_IF(!can_open_cifile());
  496. SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
  497. printf("Floating point: PREFIX\n");
  498. LOAD_FLOAT_DFORM_TEST(lfs);
  499. LOAD_FLOAT_MLS_PREFIX_TEST(PLFS);
  500. LOAD_FLOAT_MLS_PREFIX_TEST(PLFD);
  501. STORE_FLOAT_MLS_PREFIX_TEST(PSTFS);
  502. STORE_FLOAT_MLS_PREFIX_TEST(PSTFD);
  503. return rc;
  504. }
  505. void usage(char *prog)
  506. {
  507. printf("Usage: %s [options] [path [offset]]\n", prog);
  508. printf(" -d Enable debug error output\n");
  509. printf("\n");
  510. printf("This test requires a POWER8, POWER9 or POWER10 CPU ");
  511. printf("and either a usable framebuffer at /dev/fb0 or ");
  512. printf("the path to usable cache inhibited memory and optional ");
  513. printf("offset to be provided\n");
  514. }
  515. int main(int argc, char *argv[])
  516. {
  517. struct sigaction sa;
  518. int rc = 0;
  519. int option = 0;
  520. while ((option = getopt(argc, argv, "d")) != -1) {
  521. switch (option) {
  522. case 'd':
  523. debug++;
  524. break;
  525. default:
  526. usage(argv[0]);
  527. exit(1);
  528. }
  529. }
  530. argc -= optind;
  531. argv += optind;
  532. if (argc > 0)
  533. cipath = argv[0];
  534. if (argc > 1)
  535. cioffset = strtol(argv[1], 0, 0x10);
  536. bufsize = getpagesize();
  537. sa.sa_sigaction = sighandler;
  538. sigemptyset(&sa.sa_mask);
  539. sa.sa_flags = SA_SIGINFO;
  540. if (sigaction(SIGSEGV, &sa, NULL) == -1
  541. || sigaction(SIGBUS, &sa, NULL) == -1
  542. || sigaction(SIGILL, &sa, NULL) == -1) {
  543. perror("sigaction");
  544. exit(1);
  545. }
  546. prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1);
  547. rc |= test_harness(test_alignment_handler_vsx_206,
  548. "test_alignment_handler_vsx_206");
  549. rc |= test_harness(test_alignment_handler_vsx_207,
  550. "test_alignment_handler_vsx_207");
  551. rc |= test_harness(test_alignment_handler_vsx_300,
  552. "test_alignment_handler_vsx_300");
  553. rc |= test_harness(test_alignment_handler_vsx_prefix,
  554. "test_alignment_handler_vsx_prefix");
  555. rc |= test_harness(test_alignment_handler_integer,
  556. "test_alignment_handler_integer");
  557. rc |= test_harness(test_alignment_handler_integer_206,
  558. "test_alignment_handler_integer_206");
  559. rc |= test_harness(test_alignment_handler_integer_prefix,
  560. "test_alignment_handler_integer_prefix");
  561. rc |= test_harness(test_alignment_handler_vmx,
  562. "test_alignment_handler_vmx");
  563. rc |= test_harness(test_alignment_handler_fp,
  564. "test_alignment_handler_fp");
  565. rc |= test_harness(test_alignment_handler_fp_205,
  566. "test_alignment_handler_fp_205");
  567. rc |= test_harness(test_alignment_handler_fp_206,
  568. "test_alignment_handler_fp_206");
  569. rc |= test_harness(test_alignment_handler_fp_prefix,
  570. "test_alignment_handler_fp_prefix");
  571. return rc;
  572. }