aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-02 13:01:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-02 13:01:04 -0500
commit03f51d4efa2287cc628bb20b0c032036d2a9e66a (patch)
treeec7fb3b6624d53092e2768578f3ef887c8d77f22 /tools
parent367b0df173b0ebea5d18b6971c244e260b5feb17 (diff)
parent015eb1b89e959c9349f0a01803fb8ed1ced36f09 (diff)
Merge tag 'powerpc-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman: "Highlights: - Enable support for memory protection keys aka "pkeys" on Power7/8/9 when using the hash table MMU. - Extend our interrupt soft masking to support masking PMU interrupts as well as "normal" interrupts, and then use that to implement local_t for a ~4x speedup vs the current atomics-based implementation. - A new driver "ocxl" for "Open Coherent Accelerator Processor Interface (OpenCAPI)" devices. - Support for new device tree properties on PowerVM to describe hotpluggable memory and devices. - Add support for CLOCK_{REALTIME/MONOTONIC}_COARSE to the 64-bit VDSO. - Freescale updates from Scott: fixes for CPM GPIO and an FSL PCI erratum workaround, plus a minor cleanup patch. As well as quite a lot of other changes all over the place, and small fixes and cleanups as always. Thanks to: Alan Modra, Alastair D'Silva, Alexey Kardashevskiy, Alistair Popple, Andreas Schwab, Andrew Donnellan, Aneesh Kumar K.V, Anju T Sudhakar, Anshuman Khandual, Anton Blanchard, Arnd Bergmann, Balbir Singh, Benjamin Herrenschmidt, Bhaktipriya Shridhar, Bryant G. Ly, Cédric Le Goater, Christophe Leroy, Christophe Lombard, Cyril Bur, David Gibson, Desnes A. Nunes do Rosario, Dmitry Torokhov, Frederic Barrat, Geert Uytterhoeven, Guilherme G. Piccoli, Gustavo A. R. Silva, Gustavo Romero, Ivan Mikhaylov, Joakim Tjernlund, Joe Perches, Josh Poimboeuf, Juan J. Alvarez, Julia Cartwright, Kamalesh Babulal, Madhavan Srinivasan, Mahesh Salgaonkar, Mathieu Malaterre, Michael Bringmann, Michael Hanselmann, Michael Neuling, Nathan Fontenot, Naveen N. Rao, Nicholas Piggin, Paul Mackerras, Philippe Bergheaud, Ram Pai, Russell Currey, Santosh Sivaraj, Scott Wood, Seth Forshee, Simon Guo, Stewart Smith, Sukadev Bhattiprolu, Thiago Jung Bauermann, Vaibhav Jain, Vasyl Gomonovych" * tag 'powerpc-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (199 commits) powerpc/mm/radix: Fix build error when RADIX_MMU=n macintosh/ams-input: Use true and false for boolean values macintosh: change some data types from int to bool powerpc/watchdog: Print the NIP in soft_nmi_interrupt() powerpc/watchdog: regs can't be null in soft_nmi_interrupt() powerpc/watchdog: Tweak watchdog printks powerpc/cell: Remove axonram driver rtc-opal: Fix handling of firmware error codes, prevent busy loops powerpc/mpc52xx_gpt: make use of raw_spinlock variants macintosh/adb: Properly mark continued kernel messages powerpc/pseries: Fix cpu hotplug crash with memoryless nodes powerpc/numa: Ensure nodes initialized for hotplug powerpc/numa: Use ibm,max-associativity-domains to discover possible nodes powerpc/kernel: Block interrupts when updating TIDR powerpc/powernv/idoa: Remove unnecessary pcidev from pci_dn powerpc/mm/nohash: do not flush the entire mm when range is a single page powerpc/pseries: Add Initialization of VF Bars powerpc/pseries/pci: Associate PEs to VFs in configure SR-IOV powerpc/eeh: Add EEH notify resume sysfs powerpc/eeh: Add EEH operations to notify resume ...
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/powerpc/alignment/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/alignment/alignment_handler.c491
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/mmap_bench.c53
-rw-r--r--tools/testing/selftests/powerpc/mm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/mm/segv_errors.c78
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c4
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c3
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-trap.c329
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-unavailable.c43
13 files changed, 994 insertions, 21 deletions
diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile
index 16b22004e75f..083a48a008b4 100644
--- a/tools/testing/selftests/powerpc/alignment/Makefile
+++ b/tools/testing/selftests/powerpc/alignment/Makefile
@@ -1,4 +1,5 @@
1TEST_GEN_PROGS := copy_unaligned copy_first_unaligned paste_unaligned paste_last_unaligned 1TEST_GEN_PROGS := copy_unaligned copy_first_unaligned paste_unaligned \
2 paste_last_unaligned alignment_handler
2 3
3include ../../lib.mk 4include ../../lib.mk
4 5
diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
new file mode 100644
index 000000000000..39fd362415cf
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
@@ -0,0 +1,491 @@
1/*
2 * Test the powerpc alignment handler on POWER8/POWER9
3 *
4 * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12/*
13 * This selftest exercises the powerpc alignment fault handler.
14 *
15 * We create two sets of source and destination buffers, one in regular memory,
16 * the other cache-inhibited (we use /dev/fb0 for this).
17 *
18 * We initialise the source buffers, then use whichever set of load/store
19 * instructions is under test to copy bytes from the source buffers to the
20 * destination buffers. For the regular buffers, these instructions will
21 * execute normally. For the cache-inhibited buffers, these instructions
22 * will trap and cause an alignment fault, and the alignment fault handler
23 * will emulate the particular instruction under test. We then compare the
24 * destination buffers to ensure that the native and emulated cases give the
25 * same result.
26 *
27 * TODO:
28 * - Any FIXMEs below
29 * - Test VSX regs < 32 and > 32
30 * - Test all loads and stores
31 * - Check update forms do update register
32 * - Test alignment faults over page boundary
33 *
34 * Some old binutils may not support all the instructions.
35 */
36
37
38#include <sys/mman.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <assert.h>
47#include <getopt.h>
48#include <setjmp.h>
49#include <signal.h>
50
51#include "utils.h"
52
53int bufsize;
54int debug;
55int testing;
56volatile int gotsig;
57
58void sighandler(int sig, siginfo_t *info, void *ctx)
59{
60 struct ucontext *ucp = ctx;
61
62 if (!testing) {
63 signal(sig, SIG_DFL);
64 kill(0, sig);
65 }
66 gotsig = sig;
67#ifdef __powerpc64__
68 ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
69#else
70 ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4;
71#endif
72}
73
74#define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
75#define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
76
77#define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
78 void test_##name(char *s, char *d) \
79 { \
80 asm volatile( \
81 #ld_op form(ld_reg, 0) \
82 #st_op form(st_reg, 1) \
83 :: "r"(s), "r"(d), "r"(0) \
84 : "memory", "vs0", "vs32", "r31"); \
85 } \
86 rc |= do_test(#name, test_##name)
87
88#define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
89#define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
90#define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
91#define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
92#define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
93#define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
94#define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
95#define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
96
97#define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
98#define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
99#define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
100#define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
101
102#define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
103#define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
104#define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
105#define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
106
107
108/* FIXME: Unimplemented tests: */
109// STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
110// STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
111
112// STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
113// STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
114
115
116/* preload byte by byte */
117void preload_data(void *dst, int offset, int width)
118{
119 char *c = dst;
120 int i;
121
122 c += offset;
123
124 for (i = 0 ; i < width ; i++)
125 c[i] = i;
126}
127
128int test_memcpy(void *dst, void *src, int size, int offset,
129 void (*test_func)(char *, char *))
130{
131 char *s, *d;
132
133 s = src;
134 s += offset;
135 d = dst;
136 d += offset;
137
138 assert(size == 16);
139 gotsig = 0;
140 testing = 1;
141
142 test_func(s, d); /* run the actual test */
143
144 testing = 0;
145 if (gotsig) {
146 if (debug)
147 printf(" Got signal %i\n", gotsig);
148 return 1;
149 }
150 return 0;
151}
152
153void dumpdata(char *s1, char *s2, int n, char *test_name)
154{
155 int i;
156
157 printf(" %s: unexpected result:\n", test_name);
158 printf(" mem:");
159 for (i = 0; i < n; i++)
160 printf(" %02x", s1[i]);
161 printf("\n");
162 printf(" ci: ");
163 for (i = 0; i < n; i++)
164 printf(" %02x", s2[i]);
165 printf("\n");
166}
167
168int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name)
169{
170 char *s1c, *s2c;
171
172 s1c = s1;
173 s1c += offset;
174 s2c = s2;
175 s2c += offset;
176
177 if (memcmp(s1c, s2c, n)) {
178 if (debug) {
179 printf("\n Compare failed. Offset:%i length:%i\n",
180 offset, n);
181 dumpdata(s1c, s2c, n, test_name);
182 }
183 return 1;
184 }
185 return 0;
186}
187
188/*
189 * Do two memcpy tests using the same instructions. One cachable
190 * memory and the other doesn't.
191 */
192int do_test(char *test_name, void (*test_func)(char *, char *))
193{
194 int offset, width, fd, rc = 0, r;
195 void *mem0, *mem1, *ci0, *ci1;
196
197 printf("\tDoing %s:\t", test_name);
198
199 fd = open("/dev/fb0", O_RDWR);
200 if (fd < 0) {
201 printf("\n");
202 perror("Can't open /dev/fb0");
203 SKIP_IF(1);
204 }
205
206 ci0 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED,
207 fd, 0x0);
208 ci1 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED,
209 fd, bufsize);
210 if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) {
211 printf("\n");
212 perror("mmap failed");
213 SKIP_IF(1);
214 }
215
216 rc = posix_memalign(&mem0, bufsize, bufsize);
217 if (rc) {
218 printf("\n");
219 return rc;
220 }
221
222 rc = posix_memalign(&mem1, bufsize, bufsize);
223 if (rc) {
224 printf("\n");
225 free(mem0);
226 return rc;
227 }
228
229 /* offset = 0 no alignment fault, so skip */
230 for (offset = 1; offset < 16; offset++) {
231 width = 16; /* vsx == 16 bytes */
232 r = 0;
233
234 /* load pattern into memory byte by byte */
235 preload_data(ci0, offset, width);
236 preload_data(mem0, offset, width); // FIXME: remove??
237 memcpy(ci0, mem0, bufsize);
238 memcpy(ci1, mem1, bufsize); /* initialise output to the same */
239
240 /* sanity check */
241 test_memcmp(mem0, ci0, width, offset, test_name);
242
243 r |= test_memcpy(ci1, ci0, width, offset, test_func);
244 r |= test_memcpy(mem1, mem0, width, offset, test_func);
245 if (r && !debug) {
246 printf("FAILED: Got signal");
247 break;
248 }
249
250 r |= test_memcmp(mem1, ci1, width, offset, test_name);
251 rc |= r;
252 if (r && !debug) {
253 printf("FAILED: Wrong Data");
254 break;
255 }
256 }
257 if (!r)
258 printf("PASSED");
259 printf("\n");
260
261 munmap(ci0, bufsize);
262 munmap(ci1, bufsize);
263 free(mem0);
264 free(mem1);
265
266 return rc;
267}
268
269int test_alignment_handler_vsx_206(void)
270{
271 int rc = 0;
272
273 printf("VSX: 2.06B\n");
274 LOAD_VSX_XFORM_TEST(lxvd2x);
275 LOAD_VSX_XFORM_TEST(lxvw4x);
276 LOAD_VSX_XFORM_TEST(lxsdx);
277 LOAD_VSX_XFORM_TEST(lxvdsx);
278 STORE_VSX_XFORM_TEST(stxvd2x);
279 STORE_VSX_XFORM_TEST(stxvw4x);
280 STORE_VSX_XFORM_TEST(stxsdx);
281 return rc;
282}
283
284int test_alignment_handler_vsx_207(void)
285{
286 int rc = 0;
287
288 printf("VSX: 2.07B\n");
289 LOAD_VSX_XFORM_TEST(lxsspx);
290 LOAD_VSX_XFORM_TEST(lxsiwax);
291 LOAD_VSX_XFORM_TEST(lxsiwzx);
292 STORE_VSX_XFORM_TEST(stxsspx);
293 STORE_VSX_XFORM_TEST(stxsiwx);
294 return rc;
295}
296
297int test_alignment_handler_vsx_300(void)
298{
299 int rc = 0;
300
301 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
302 printf("VSX: 3.00B\n");
303 LOAD_VMX_DFORM_TEST(lxsd);
304 LOAD_VSX_XFORM_TEST(lxsibzx);
305 LOAD_VSX_XFORM_TEST(lxsihzx);
306 LOAD_VMX_DFORM_TEST(lxssp);
307 LOAD_VSX_DFORM_TEST(lxv);
308 LOAD_VSX_XFORM_TEST(lxvb16x);
309 LOAD_VSX_XFORM_TEST(lxvh8x);
310 LOAD_VSX_XFORM_TEST(lxvx);
311 LOAD_VSX_XFORM_TEST(lxvwsx);
312 LOAD_VSX_XFORM_TEST(lxvl);
313 LOAD_VSX_XFORM_TEST(lxvll);
314 STORE_VMX_DFORM_TEST(stxsd);
315 STORE_VSX_XFORM_TEST(stxsibx);
316 STORE_VSX_XFORM_TEST(stxsihx);
317 STORE_VMX_DFORM_TEST(stxssp);
318 STORE_VSX_DFORM_TEST(stxv);
319 STORE_VSX_XFORM_TEST(stxvb16x);
320 STORE_VSX_XFORM_TEST(stxvh8x);
321 STORE_VSX_XFORM_TEST(stxvx);
322 STORE_VSX_XFORM_TEST(stxvl);
323 STORE_VSX_XFORM_TEST(stxvll);
324 return rc;
325}
326
327int test_alignment_handler_integer(void)
328{
329 int rc = 0;
330
331 printf("Integer\n");
332 LOAD_DFORM_TEST(lbz);
333 LOAD_DFORM_TEST(lbzu);
334 LOAD_XFORM_TEST(lbzx);
335 LOAD_XFORM_TEST(lbzux);
336 LOAD_DFORM_TEST(lhz);
337 LOAD_DFORM_TEST(lhzu);
338 LOAD_XFORM_TEST(lhzx);
339 LOAD_XFORM_TEST(lhzux);
340 LOAD_DFORM_TEST(lha);
341 LOAD_DFORM_TEST(lhau);
342 LOAD_XFORM_TEST(lhax);
343 LOAD_XFORM_TEST(lhaux);
344 LOAD_XFORM_TEST(lhbrx);
345 LOAD_DFORM_TEST(lwz);
346 LOAD_DFORM_TEST(lwzu);
347 LOAD_XFORM_TEST(lwzx);
348 LOAD_XFORM_TEST(lwzux);
349 LOAD_DFORM_TEST(lwa);
350 LOAD_XFORM_TEST(lwax);
351 LOAD_XFORM_TEST(lwaux);
352 LOAD_XFORM_TEST(lwbrx);
353 LOAD_DFORM_TEST(ld);
354 LOAD_DFORM_TEST(ldu);
355 LOAD_XFORM_TEST(ldx);
356 LOAD_XFORM_TEST(ldux);
357 LOAD_XFORM_TEST(ldbrx);
358 LOAD_DFORM_TEST(lmw);
359 STORE_DFORM_TEST(stb);
360 STORE_XFORM_TEST(stbx);
361 STORE_DFORM_TEST(stbu);
362 STORE_XFORM_TEST(stbux);
363 STORE_DFORM_TEST(sth);
364 STORE_XFORM_TEST(sthx);
365 STORE_DFORM_TEST(sthu);
366 STORE_XFORM_TEST(sthux);
367 STORE_XFORM_TEST(sthbrx);
368 STORE_DFORM_TEST(stw);
369 STORE_XFORM_TEST(stwx);
370 STORE_DFORM_TEST(stwu);
371 STORE_XFORM_TEST(stwux);
372 STORE_XFORM_TEST(stwbrx);
373 STORE_DFORM_TEST(std);
374 STORE_XFORM_TEST(stdx);
375 STORE_DFORM_TEST(stdu);
376 STORE_XFORM_TEST(stdux);
377 STORE_XFORM_TEST(stdbrx);
378 STORE_DFORM_TEST(stmw);
379 return rc;
380}
381
382int test_alignment_handler_vmx(void)
383{
384 int rc = 0;
385
386 printf("VMX\n");
387 LOAD_VMX_XFORM_TEST(lvx);
388
389 /*
390 * FIXME: These loads only load part of the register, so our
391 * testing method doesn't work. Also they don't take alignment
392 * faults, so it's kinda pointless anyway
393 *
394 LOAD_VMX_XFORM_TEST(lvebx)
395 LOAD_VMX_XFORM_TEST(lvehx)
396 LOAD_VMX_XFORM_TEST(lvewx)
397 LOAD_VMX_XFORM_TEST(lvxl)
398 */
399 STORE_VMX_XFORM_TEST(stvx);
400 STORE_VMX_XFORM_TEST(stvebx);
401 STORE_VMX_XFORM_TEST(stvehx);
402 STORE_VMX_XFORM_TEST(stvewx);
403 STORE_VMX_XFORM_TEST(stvxl);
404 return rc;
405}
406
407int test_alignment_handler_fp(void)
408{
409 int rc = 0;
410
411 printf("Floating point\n");
412 LOAD_FLOAT_DFORM_TEST(lfd);
413 LOAD_FLOAT_XFORM_TEST(lfdx);
414 LOAD_FLOAT_DFORM_TEST(lfdp);
415 LOAD_FLOAT_XFORM_TEST(lfdpx);
416 LOAD_FLOAT_DFORM_TEST(lfdu);
417 LOAD_FLOAT_XFORM_TEST(lfdux);
418 LOAD_FLOAT_DFORM_TEST(lfs);
419 LOAD_FLOAT_XFORM_TEST(lfsx);
420 LOAD_FLOAT_DFORM_TEST(lfsu);
421 LOAD_FLOAT_XFORM_TEST(lfsux);
422 LOAD_FLOAT_XFORM_TEST(lfiwzx);
423 LOAD_FLOAT_XFORM_TEST(lfiwax);
424 STORE_FLOAT_DFORM_TEST(stfd);
425 STORE_FLOAT_XFORM_TEST(stfdx);
426 STORE_FLOAT_DFORM_TEST(stfdp);
427 STORE_FLOAT_XFORM_TEST(stfdpx);
428 STORE_FLOAT_DFORM_TEST(stfdu);
429 STORE_FLOAT_XFORM_TEST(stfdux);
430 STORE_FLOAT_DFORM_TEST(stfs);
431 STORE_FLOAT_XFORM_TEST(stfsx);
432 STORE_FLOAT_DFORM_TEST(stfsu);
433 STORE_FLOAT_XFORM_TEST(stfsux);
434 STORE_FLOAT_XFORM_TEST(stfiwx);
435
436 return rc;
437}
438
439void usage(char *prog)
440{
441 printf("Usage: %s [options]\n", prog);
442 printf(" -d Enable debug error output\n");
443 printf("\n");
444 printf("This test requires a POWER8 or POWER9 CPU and a usable ");
445 printf("framebuffer at /dev/fb0.\n");
446}
447
448int main(int argc, char *argv[])
449{
450
451 struct sigaction sa;
452 int rc = 0;
453 int option = 0;
454
455 while ((option = getopt(argc, argv, "d")) != -1) {
456 switch (option) {
457 case 'd':
458 debug++;
459 break;
460 default:
461 usage(argv[0]);
462 exit(1);
463 }
464 }
465
466 bufsize = getpagesize();
467
468 sa.sa_sigaction = sighandler;
469 sigemptyset(&sa.sa_mask);
470 sa.sa_flags = SA_SIGINFO;
471 if (sigaction(SIGSEGV, &sa, NULL) == -1
472 || sigaction(SIGBUS, &sa, NULL) == -1
473 || sigaction(SIGILL, &sa, NULL) == -1) {
474 perror("sigaction");
475 exit(1);
476 }
477
478 rc |= test_harness(test_alignment_handler_vsx_206,
479 "test_alignment_handler_vsx_206");
480 rc |= test_harness(test_alignment_handler_vsx_207,
481 "test_alignment_handler_vsx_207");
482 rc |= test_harness(test_alignment_handler_vsx_300,
483 "test_alignment_handler_vsx_300");
484 rc |= test_harness(test_alignment_handler_integer,
485 "test_alignment_handler_integer");
486 rc |= test_harness(test_alignment_handler_vmx,
487 "test_alignment_handler_vmx");
488 rc |= test_harness(test_alignment_handler_fp,
489 "test_alignment_handler_fp");
490 return rc;
491}
diff --git a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c
index 8d084a2d6e74..7a0a462a2272 100644
--- a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c
+++ b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c
@@ -7,17 +7,34 @@
7#include <stdlib.h> 7#include <stdlib.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9#include <time.h> 9#include <time.h>
10#include <getopt.h>
10 11
11#include "utils.h" 12#include "utils.h"
12 13
13#define ITERATIONS 5000000 14#define ITERATIONS 5000000
14 15
15#define MEMSIZE (128 * 1024 * 1024) 16#define MEMSIZE (1UL << 27)
17#define PAGE_SIZE (1UL << 16)
18#define CHUNK_COUNT (MEMSIZE/PAGE_SIZE)
19
20static int pg_fault;
21static int iterations = ITERATIONS;
22
23static struct option options[] = {
24 { "pgfault", no_argument, &pg_fault, 1 },
25 { "iterations", required_argument, 0, 'i' },
26 { 0, },
27};
28
29static void usage(void)
30{
31 printf("mmap_bench <--pgfault> <--iterations count>\n");
32}
16 33
17int test_mmap(void) 34int test_mmap(void)
18{ 35{
19 struct timespec ts_start, ts_end; 36 struct timespec ts_start, ts_end;
20 unsigned long i = ITERATIONS; 37 unsigned long i = iterations;
21 38
22 clock_gettime(CLOCK_MONOTONIC, &ts_start); 39 clock_gettime(CLOCK_MONOTONIC, &ts_start);
23 40
@@ -25,6 +42,11 @@ int test_mmap(void)
25 char *c = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, 42 char *c = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE,
26 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 43 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
27 FAIL_IF(c == MAP_FAILED); 44 FAIL_IF(c == MAP_FAILED);
45 if (pg_fault) {
46 int count;
47 for (count = 0; count < CHUNK_COUNT; count++)
48 c[count << 16] = 'c';
49 }
28 munmap(c, MEMSIZE); 50 munmap(c, MEMSIZE);
29 } 51 }
30 52
@@ -35,7 +57,32 @@ int test_mmap(void)
35 return 0; 57 return 0;
36} 58}
37 59
38int main(void) 60int main(int argc, char *argv[])
39{ 61{
62 signed char c;
63 while (1) {
64 int option_index = 0;
65
66 c = getopt_long(argc, argv, "", options, &option_index);
67
68 if (c == -1)
69 break;
70
71 switch (c) {
72 case 0:
73 if (options[option_index].flag != 0)
74 break;
75
76 usage();
77 exit(1);
78 break;
79 case 'i':
80 iterations = atoi(optarg);
81 break;
82 default:
83 usage();
84 exit(1);
85 }
86 }
40 return test_harness(test_mmap, "mmap_bench"); 87 return test_harness(test_mmap, "mmap_bench");
41} 88}
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore
index e715a3f2fbf4..7d7c42ed6de9 100644
--- a/tools/testing/selftests/powerpc/mm/.gitignore
+++ b/tools/testing/selftests/powerpc/mm/.gitignore
@@ -1,4 +1,5 @@
1hugetlb_vs_thp_test 1hugetlb_vs_thp_test
2subpage_prot 2subpage_prot
3tempfile 3tempfile
4prot_sao \ No newline at end of file 4prot_sao
5segv_errors \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index bf315bcbe663..8ebbe96d80a8 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -2,7 +2,7 @@
2noarg: 2noarg:
3 $(MAKE) -C ../ 3 $(MAKE) -C ../
4 4
5TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao 5TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors
6TEST_GEN_FILES := tempfile 6TEST_GEN_FILES := tempfile
7 7
8include ../../lib.mk 8include ../../lib.mk
diff --git a/tools/testing/selftests/powerpc/mm/segv_errors.c b/tools/testing/selftests/powerpc/mm/segv_errors.c
new file mode 100644
index 000000000000..06ae76ee3ea1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/mm/segv_errors.c
@@ -0,0 +1,78 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright 2017 John Sperbeck
5 *
6 * Test that an access to a mapped but inaccessible area causes a SEGV and
7 * reports si_code == SEGV_ACCERR.
8 */
9
10#include <stdbool.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15#include <signal.h>
16#include <sys/mman.h>
17#include <assert.h>
18#include <ucontext.h>
19
20#include "utils.h"
21
22static bool faulted;
23static int si_code;
24
25static void segv_handler(int n, siginfo_t *info, void *ctxt_v)
26{
27 ucontext_t *ctxt = (ucontext_t *)ctxt_v;
28 struct pt_regs *regs = ctxt->uc_mcontext.regs;
29
30 faulted = true;
31 si_code = info->si_code;
32 regs->nip += 4;
33}
34
35int test_segv_errors(void)
36{
37 struct sigaction act = {
38 .sa_sigaction = segv_handler,
39 .sa_flags = SA_SIGINFO,
40 };
41 char c, *p = NULL;
42
43 p = mmap(NULL, getpagesize(), 0, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
44 FAIL_IF(p == MAP_FAILED);
45
46 FAIL_IF(sigaction(SIGSEGV, &act, NULL) != 0);
47
48 faulted = false;
49 si_code = 0;
50
51 /*
52 * We just need a compiler barrier, but mb() works and has the nice
53 * property of being easy to spot in the disassembly.
54 */
55 mb();
56 c = *p;
57 mb();
58
59 FAIL_IF(!faulted);
60 FAIL_IF(si_code != SEGV_ACCERR);
61
62 faulted = false;
63 si_code = 0;
64
65 mb();
66 *p = c;
67 mb();
68
69 FAIL_IF(!faulted);
70 FAIL_IF(si_code != SEGV_ACCERR);
71
72 return 0;
73}
74
75int main(void)
76{
77 return test_harness(test_segv_errors, "segv_errors");
78}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
index 0df3c23b7888..277dade1b382 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
@@ -79,8 +79,8 @@ trans:
79 : [res] "=r" (result), [texasr] "=r" (texasr) 79 : [res] "=r" (result), [texasr] "=r" (texasr)
80 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt), 80 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt),
81 [sprn_texasr] "i" (SPRN_TEXASR) 81 [sprn_texasr] "i" (SPRN_TEXASR)
82 : "memory", "r0", "r1", "r2", "r3", "r4", 82 : "memory", "r0", "r1", "r3", "r4",
83 "r8", "r9", "r10", "r11" 83 "r7", "r8", "r9", "r10", "r11"
84 ); 84 );
85 85
86 if (result) { 86 if (result) {
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
index 94e57cb89769..51427a2465f6 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
@@ -76,8 +76,7 @@ trans:
76 : [tfhar] "=r" (tfhar), [res] "=r" (result), 76 : [tfhar] "=r" (tfhar), [res] "=r" (result),
77 [texasr] "=r" (texasr), [cptr1] "=r" (cptr1) 77 [texasr] "=r" (texasr), [cptr1] "=r" (cptr1)
78 : [sprn_texasr] "i" (SPRN_TEXASR) 78 : [sprn_texasr] "i" (SPRN_TEXASR)
79 : "memory", "r0", "r1", "r2", "r3", "r4", 79 : "memory", "r0", "r8", "r31"
80 "r8", "r9", "r10", "r11", "r31"
81 ); 80 );
82 81
83 /* There are 2 32bit instructions before tbegin. */ 82 /* There are 2 32bit instructions before tbegin. */
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
index b4081e2b22d5..17c23cabac3e 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
@@ -67,7 +67,7 @@ trans:
67 : [res] "=r" (result), [texasr] "=r" (texasr) 67 : [res] "=r" (result), [texasr] "=r" (texasr)
68 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt), 68 : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt),
69 [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "r" (&cptr[1]) 69 [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "r" (&cptr[1])
70 : "memory", "r0", "r1", "r2", "r3", "r4", 70 : "memory", "r0", "r1", "r3", "r4",
71 "r7", "r8", "r9", "r10", "r11" 71 "r7", "r8", "r9", "r10", "r11"
72 ); 72 );
73 73
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 241a4a4ee0e4..bb90d4b79524 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -13,3 +13,4 @@ tm-signal-context-chk-vmx
13tm-signal-context-chk-vsx 13tm-signal-context-chk-vsx
14tm-vmx-unavail 14tm-vmx-unavail
15tm-unavailable 15tm-unavailable
16tm-trap
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 8ed6f8c57230..a23453943ad2 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -3,7 +3,7 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu
3 tm-signal-context-chk-vmx tm-signal-context-chk-vsx 3 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
4 4
5TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 5TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
6 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable \ 6 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail tm-unavailable tm-trap \
7 $(SIGNAL_CONTEXT_CHK_TESTS) 7 $(SIGNAL_CONTEXT_CHK_TESTS)
8 8
9include ../../lib.mk 9include ../../lib.mk
@@ -18,6 +18,7 @@ $(OUTPUT)/tm-tmspr: CFLAGS += -pthread
18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o 19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o
20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx 20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx
21$(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64
21 22
22SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 23SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
23$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S 24$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-trap.c b/tools/testing/selftests/powerpc/tm/tm-trap.c
new file mode 100644
index 000000000000..5d92c23ee6cb
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-trap.c
@@ -0,0 +1,329 @@
1/*
2 * Copyright 2017, Gustavo Romero, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Check if thread endianness is flipped inadvertently to BE on trap
6 * caught in TM whilst MSR.FP and MSR.VEC are zero (i.e. just after
7 * load_fp and load_vec overflowed).
8 *
9 * The issue can be checked on LE machines simply by zeroing load_fp
10 * and load_vec and then causing a trap in TM. Since the endianness
11 * changes to BE on return from the signal handler, 'nop' is
12 * thread as an illegal instruction in following sequence:
13 * tbegin.
14 * beq 1f
15 * trap
16 * tend.
17 * 1: nop
18 *
19 * However, although the issue is also present on BE machines, it's a
20 * bit trickier to check it on BE machines because MSR.LE bit is set
21 * to zero which determines a BE endianness that is the native
22 * endianness on BE machines, so nothing notably critical happens,
23 * i.e. no illegal instruction is observed immediately after returning
24 * from the signal handler (as it happens on LE machines). Thus to test
25 * it on BE machines LE endianness is forced after a first trap and then
26 * the endianness is verified on subsequent traps to determine if the
27 * endianness "flipped back" to the native endianness (BE).
28 */
29
30#define _GNU_SOURCE
31#include <error.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <htmintrin.h>
36#include <inttypes.h>
37#include <pthread.h>
38#include <sched.h>
39#include <signal.h>
40#include <stdbool.h>
41
42#include "tm.h"
43#include "utils.h"
44
45#define pr_error(error_code, format, ...) \
46 error_at_line(1, error_code, __FILE__, __LINE__, format, ##__VA_ARGS__)
47
48#define MSR_LE 1UL
49#define LE 1UL
50
51pthread_t t0_ping;
52pthread_t t1_pong;
53
54int exit_from_pong;
55
56int trap_event;
57int le;
58
59bool success;
60
61void trap_signal_handler(int signo, siginfo_t *si, void *uc)
62{
63 ucontext_t *ucp = uc;
64 uint64_t thread_endianness;
65
66 /* Get thread endianness: extract bit LE from MSR */
67 thread_endianness = MSR_LE & ucp->uc_mcontext.gp_regs[PT_MSR];
68
69 /***
70 * Little-Endian Machine
71 */
72
73 if (le) {
74 /* First trap event */
75 if (trap_event == 0) {
76 /* Do nothing. Since it is returning from this trap
77 * event that endianness is flipped by the bug, so just
78 * let the process return from the signal handler and
79 * check on the second trap event if endianness is
80 * flipped or not.
81 */
82 }
83 /* Second trap event */
84 else if (trap_event == 1) {
85 /*
86 * Since trap was caught in TM on first trap event, if
87 * endianness was still LE (not flipped inadvertently)
88 * after returning from the signal handler instruction
89 * (1) is executed (basically a 'nop'), as it's located
90 * at address of tbegin. +4 (rollback addr). As (1) on
91 * LE endianness does in effect nothing, instruction (2)
92 * is then executed again as 'trap', generating a second
93 * trap event (note that in that case 'trap' is caught
94 * not in transacional mode). On te other hand, if after
95 * the return from the signal handler the endianness in-
96 * advertently flipped, instruction (1) is tread as a
97 * branch instruction, i.e. b .+8, hence instruction (3)
98 * and (4) are executed (tbegin.; trap;) and we get sim-
99 * ilaly on the trap signal handler, but now in TM mode.
100 * Either way, it's now possible to check the MSR LE bit
101 * once in the trap handler to verify if endianness was
102 * flipped or not after the return from the second trap
103 * event. If endianness is flipped, the bug is present.
104 * Finally, getting a trap in TM mode or not is just
105 * worth noting because it affects the math to determine
106 * the offset added to the NIP on return: the NIP for a
107 * trap caught in TM is the rollback address, i.e. the
108 * next instruction after 'tbegin.', whilst the NIP for
109 * a trap caught in non-transactional mode is the very
110 * same address of the 'trap' instruction that generated
111 * the trap event.
112 */
113
114 if (thread_endianness == LE) {
115 /* Go to 'success', i.e. instruction (6) */
116 ucp->uc_mcontext.gp_regs[PT_NIP] += 16;
117 } else {
118 /*
119 * Thread endianness is BE, so it flipped
120 * inadvertently. Thus we flip back to LE and
121 * set NIP to go to 'failure', instruction (5).
122 */
123 ucp->uc_mcontext.gp_regs[PT_MSR] |= 1UL;
124 ucp->uc_mcontext.gp_regs[PT_NIP] += 4;
125 }
126 }
127 }
128
129 /***
130 * Big-Endian Machine
131 */
132
133 else {
134 /* First trap event */
135 if (trap_event == 0) {
136 /*
137 * Force thread endianness to be LE. Instructions (1),
138 * (3), and (4) will be executed, generating a second
139 * trap in TM mode.
140 */
141 ucp->uc_mcontext.gp_regs[PT_MSR] |= 1UL;
142 }
143 /* Second trap event */
144 else if (trap_event == 1) {
145 /*
146 * Do nothing. If bug is present on return from this
147 * second trap event endianness will flip back "automat-
148 * ically" to BE, otherwise thread endianness will
149 * continue to be LE, just as it was set above.
150 */
151 }
152 /* A third trap event */
153 else {
154 /*
155 * Once here it means that after returning from the sec-
156 * ond trap event instruction (4) (trap) was executed
157 * as LE, generating a third trap event. In that case
158 * endianness is still LE as set on return from the
159 * first trap event, hence no bug. Otherwise, bug
160 * flipped back to BE on return from the second trap
161 * event and instruction (4) was executed as 'tdi' (so
162 * basically a 'nop') and branch to 'failure' in
163 * instruction (5) was taken to indicate failure and we
164 * never get here.
165 */
166
167 /*
168 * Flip back to BE and go to instruction (6), i.e. go to
169 * 'success'.
170 */
171 ucp->uc_mcontext.gp_regs[PT_MSR] &= ~1UL;
172 ucp->uc_mcontext.gp_regs[PT_NIP] += 8;
173 }
174 }
175
176 trap_event++;
177}
178
179void usr1_signal_handler(int signo, siginfo_t *si, void *not_used)
180{
181 /* Got a USR1 signal from ping(), so just tell pong() to exit */
182 exit_from_pong = 1;
183}
184
185void *ping(void *not_used)
186{
187 uint64_t i;
188
189 trap_event = 0;
190
191 /*
192 * Wait an amount of context switches so load_fp and load_vec overflows
193 * and MSR_[FP|VEC|V] is 0.
194 */
195 for (i = 0; i < 1024*1024*512; i++)
196 ;
197
198 asm goto(
199 /*
200 * [NA] means "Native Endianness", i.e. it tells how a
201 * instruction is executed on machine's native endianness (in
202 * other words, native endianness matches kernel endianness).
203 * [OP] means "Opposite Endianness", i.e. on a BE machine, it
204 * tells how a instruction is executed as a LE instruction; con-
205 * versely, on a LE machine, it tells how a instruction is
206 * executed as a BE instruction. When [NA] is omitted, it means
207 * that the native interpretation of a given instruction is not
208 * relevant for the test. Likewise when [OP] is omitted.
209 */
210
211 " tbegin. ;" /* (0) tbegin. [NA] */
212 " tdi 0, 0, 0x48;" /* (1) nop [NA]; b (3) [OP] */
213 " trap ;" /* (2) trap [NA] */
214 ".long 0x1D05007C;" /* (3) tbegin. [OP] */
215 ".long 0x0800E07F;" /* (4) trap [OP]; nop [NA] */
216 " b %l[failure] ;" /* (5) b [NA]; MSR.LE flipped (bug) */
217 " b %l[success] ;" /* (6) b [NA]; MSR.LE did not flip (ok)*/
218
219 : : : : failure, success);
220
221failure:
222 success = false;
223 goto exit_from_ping;
224
225success:
226 success = true;
227
228exit_from_ping:
229 /* Tell pong() to exit before leaving */
230 pthread_kill(t1_pong, SIGUSR1);
231 return NULL;
232}
233
234void *pong(void *not_used)
235{
236 while (!exit_from_pong)
237 /*
238 * Induce context switches on ping() thread
239 * until ping() finishes its job and signs
240 * to exit from this loop.
241 */
242 sched_yield();
243
244 return NULL;
245}
246
247int tm_trap_test(void)
248{
249 uint16_t k = 1;
250
251 int rc;
252
253 pthread_attr_t attr;
254 cpu_set_t cpuset;
255
256 struct sigaction trap_sa;
257
258 trap_sa.sa_flags = SA_SIGINFO;
259 trap_sa.sa_sigaction = trap_signal_handler;
260 sigaction(SIGTRAP, &trap_sa, NULL);
261
262 struct sigaction usr1_sa;
263
264 usr1_sa.sa_flags = SA_SIGINFO;
265 usr1_sa.sa_sigaction = usr1_signal_handler;
266 sigaction(SIGUSR1, &usr1_sa, NULL);
267
268 /* Set only CPU 0 in the mask. Both threads will be bound to cpu 0. */
269 CPU_ZERO(&cpuset);
270 CPU_SET(0, &cpuset);
271
272 /* Init pthread attribute */
273 rc = pthread_attr_init(&attr);
274 if (rc)
275 pr_error(rc, "pthread_attr_init()");
276
277 /*
278 * Bind thread ping() and pong() both to CPU 0 so they ping-pong and
279 * speed up context switches on ping() thread, speeding up the load_fp
280 * and load_vec overflow.
281 */
282 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
283 if (rc)
284 pr_error(rc, "pthread_attr_setaffinity()");
285
286 /* Figure out the machine endianness */
287 le = (int) *(uint8_t *)&k;
288
289 printf("%s machine detected. Checking if endianness flips %s",
290 le ? "Little-Endian" : "Big-Endian",
291 "inadvertently on trap in TM... ");
292
293 rc = fflush(0);
294 if (rc)
295 pr_error(rc, "fflush()");
296
297 /* Launch ping() */
298 rc = pthread_create(&t0_ping, &attr, ping, NULL);
299 if (rc)
300 pr_error(rc, "pthread_create()");
301
302 exit_from_pong = 0;
303
304 /* Launch pong() */
305 rc = pthread_create(&t1_pong, &attr, pong, NULL);
306 if (rc)
307 pr_error(rc, "pthread_create()");
308
309 rc = pthread_join(t0_ping, NULL);
310 if (rc)
311 pr_error(rc, "pthread_join()");
312
313 rc = pthread_join(t1_pong, NULL);
314 if (rc)
315 pr_error(rc, "pthread_join()");
316
317 if (success) {
318 printf("no.\n"); /* no, endianness did not flip inadvertently */
319 return EXIT_SUCCESS;
320 }
321
322 printf("yes!\n"); /* yes, endianness did flip inadvertently */
323 return EXIT_FAILURE;
324}
325
326int main(int argc, char **argv)
327{
328 return test_harness(tm_trap_test, "tm_trap_test");
329}
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
index 96c37f84ce54..e6a0fad2bfd0 100644
--- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c
+++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#define _GNU_SOURCE 17#define _GNU_SOURCE
18#include <error.h>
18#include <stdio.h> 19#include <stdio.h>
19#include <stdlib.h> 20#include <stdlib.h>
20#include <unistd.h> 21#include <unistd.h>
@@ -33,6 +34,11 @@
33#define VSX_UNA_EXCEPTION 2 34#define VSX_UNA_EXCEPTION 2
34 35
35#define NUM_EXCEPTIONS 3 36#define NUM_EXCEPTIONS 3
37#define err_at_line(status, errnum, format, ...) \
38 error_at_line(status, errnum, __FILE__, __LINE__, format ##__VA_ARGS__)
39
40#define pr_warn(code, format, ...) err_at_line(0, code, format, ##__VA_ARGS__)
41#define pr_err(code, format, ...) err_at_line(1, code, format, ##__VA_ARGS__)
36 42
37struct Flags { 43struct Flags {
38 int touch_fp; 44 int touch_fp;
@@ -303,10 +309,19 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
303 * checking if the failure cause is the one we expect. 309 * checking if the failure cause is the one we expect.
304 */ 310 */
305 do { 311 do {
312 int rc;
313
306 /* Bind 'ping' to CPU 0, as specified in 'attr'. */ 314 /* Bind 'ping' to CPU 0, as specified in 'attr'. */
307 pthread_create(&t0, attr, ping, (void *) &flags); 315 rc = pthread_create(&t0, attr, ping, (void *) &flags);
308 pthread_setname_np(t0, "ping"); 316 if (rc)
309 pthread_join(t0, &ret_value); 317 pr_err(rc, "pthread_create()");
318 rc = pthread_setname_np(t0, "ping");
319 if (rc)
320 pr_warn(rc, "pthread_setname_np");
321 rc = pthread_join(t0, &ret_value);
322 if (rc)
323 pr_err(rc, "pthread_join");
324
310 retries--; 325 retries--;
311 } while (ret_value != NULL && retries); 326 } while (ret_value != NULL && retries);
312 327
@@ -320,7 +335,7 @@ void test_fp_vec(int fp, int vec, pthread_attr_t *attr)
320 335
321int main(int argc, char **argv) 336int main(int argc, char **argv)
322{ 337{
323 int exception; /* FP = 0, VEC = 1, VSX = 2 */ 338 int rc, exception; /* FP = 0, VEC = 1, VSX = 2 */
324 pthread_t t1; 339 pthread_t t1;
325 pthread_attr_t attr; 340 pthread_attr_t attr;
326 cpu_set_t cpuset; 341 cpu_set_t cpuset;
@@ -330,13 +345,23 @@ int main(int argc, char **argv)
330 CPU_SET(0, &cpuset); 345 CPU_SET(0, &cpuset);
331 346
332 /* Init pthread attribute. */ 347 /* Init pthread attribute. */
333 pthread_attr_init(&attr); 348 rc = pthread_attr_init(&attr);
349 if (rc)
350 pr_err(rc, "pthread_attr_init()");
334 351
335 /* Set CPU 0 mask into the pthread attribute. */ 352 /* Set CPU 0 mask into the pthread attribute. */
336 pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); 353 rc = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
337 354 if (rc)
338 pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL); 355 pr_err(rc, "pthread_attr_setaffinity_np()");
339 pthread_setname_np(t1, "pong"); /* Name it for systemtap convenience */ 356
357 rc = pthread_create(&t1, &attr /* Bind 'pong' to CPU 0 */, pong, NULL);
358 if (rc)
359 pr_err(rc, "pthread_create()");
360
361 /* Name it for systemtap convenience */
362 rc = pthread_setname_np(t1, "pong");
363 if (rc)
364 pr_warn(rc, "pthread_create()");
340 365
341 flags.result = 0; 366 flags.result = 0;
342 367