aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 23:19:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 23:19:31 -0400
commit07021b43597f506cc525d139ed1a94e79cf184f2 (patch)
tree888ab33ec69b397ae6f8a2c82d14197047ee827e /tools
parentd1f5323370fceaed43a7ee38f4c7bfc7e70f28d0 (diff)
parentb7b7013cac55d794940bd9cb7b7c55c9dececac4 (diff)
Merge tag 'powerpc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman: "Highlights: - Major rework of Book3S 64-bit exception vectors (Nicholas Piggin) - Use gas sections for arranging exception vectors et. al. - Large set of TM cleanups and selftests (Cyril Bur) - Enable transactional memory (TM) lazily for userspace (Cyril Bur) - Support for XZ compression in the zImage wrapper (Oliver O'Halloran) - Add support for bpf constant blinding (Naveen N. Rao) - Beginnings of upstream support for PA Semi Nemo motherboards (Darren Stevens) Fixes: - Ensure .mem(init|exit).text are within _stext/_etext (Michael Ellerman) - xmon: Don't use ld on 32-bit (Michael Ellerman) - vdso64: Use double word compare on pointers (Anton Blanchard) - powerpc/nvram: Fix an incorrect partition merge (Pan Xinhui) - powerpc: Fix usage of _PAGE_RO in hugepage (Christophe Leroy) - powerpc/mm: Update FORCE_MAX_ZONEORDER range to allow hugetlb w/4K (Aneesh Kumar K.V) - Fix memory leak in queue_hotplug_event() error path (Andrew Donnellan) - Replay hypervisor maintenance interrupt first (Nicholas Piggin) Various performance optimisations (Anton Blanchard): - Align hot loops of memset() and backwards_memcpy() - During context switch, check before setting mm_cpumask - Remove static branch prediction in atomic{, 64}_add_unless - Only disable HAVE_EFFICIENT_UNALIGNED_ACCESS on POWER7 little endian - Set default CPU type to POWER8 for little endian builds Cleanups & features: - Sparse fixes/cleanups (Daniel Axtens) - Preserve CFAR value on SLB miss caused by access to bogus address (Paul Mackerras) - Radix MMU fixups for POWER9 (Aneesh Kumar K.V) - Support for setting used_(vsr|vr|spe) in sigreturn path (for CRIU) (Simon Guo) - Optimise syscall entry for virtual, relocatable case (Nicholas Piggin) - Optimise MSR handling in exception handling (Nicholas Piggin) - Support for kexec with Radix MMU (Benjamin Herrenschmidt) - powernv EEH fixes (Russell Currey) - Suprise PCI hotplug support for powernv (Gavin Shan) - Endian/sparse fixes for powernv PCI (Gavin Shan) - Defconfig updates (Anton Blanchard) - KVM: PPC: Book3S HV: Migrate pinned pages out of CMA (Balbir Singh) - cxl: Flush PSL cache before resetting the adapter (Frederic Barrat) - cxl: replace loop with for_each_child_of_node(), remove unneeded of_node_put() (Andrew Donnellan) - Fix HV facility unavailable to use correct handler (Nicholas Piggin) - Remove unnecessary syscall trampoline (Nicholas Piggin) - fadump: Fix build break when CONFIG_PROC_VMCORE=n (Michael Ellerman) - Quieten EEH message when no adapters are found (Anton Blanchard) - powernv: Add PHB register dump debugfs handle (Russell Currey) - Use kprobe blacklist for exception handlers & asm functions (Nicholas Piggin) - Document the syscall ABI (Nicholas Piggin) - MAINTAINERS: Update cxl maintainers (Michael Neuling) - powerpc: Remove all usages of NO_IRQ (Michael Ellerman) Minor cleanups: - Andrew Donnellan, Christophe Leroy, Colin Ian King, Cyril Bur, Frederic Barrat, Pan Xinhui, PrasannaKumar Muralidharan, Rui Teng, Simon Guo" * tag 'powerpc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (156 commits) powerpc/bpf: Add support for bpf constant blinding powerpc/bpf: Implement support for tail calls powerpc/bpf: Introduce accessors for using the tmp local stack space powerpc/fadump: Fix build break when CONFIG_PROC_VMCORE=n powerpc: tm: Enable transactional memory (TM) lazily for userspace powerpc/tm: Add TM Unavailable Exception powerpc: Remove do_load_up_transact_{fpu,altivec} powerpc: tm: Rename transct_(*) to ck(\1)_state powerpc: tm: Always use fp_state and vr_state to store live registers selftests/powerpc: Add checks for transactional VSXs in signal contexts selftests/powerpc: Add checks for transactional VMXs in signal contexts selftests/powerpc: Add checks for transactional FPUs in signal contexts selftests/powerpc: Add checks for transactional GPRs in signal contexts selftests/powerpc: Check that signals always get delivered selftests/powerpc: Add TM tcheck helpers in C selftests/powerpc: Allow tests to extend their kill timeout selftests/powerpc: Introduce GPR asm helper header file selftests/powerpc: Move VMX stack frame macros to header file selftests/powerpc: Rework FPU stack placement macros and move to header file selftests/powerpc: Check for VSX preservation across userspace preemption ...
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/fpu_asm.h80
-rw-r--r--tools/testing/selftests/powerpc/gpr_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/harness.c9
-rw-r--r--tools/testing/selftests/powerpc/math/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/math/fpu_asm.S73
-rw-r--r--tools/testing/selftests/powerpc/math/vmx_asm.S85
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_asm.S61
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_preempt.c147
-rw-r--r--tools/testing/selftests/powerpc/signal/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.S50
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.c111
-rw-r--r--tools/testing/selftests/powerpc/signal/signal_tm.c110
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile8
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c92
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c110
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c125
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal.S114
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h27
-rw-r--r--tools/testing/selftests/powerpc/utils.h9
-rw-r--r--tools/testing/selftests/powerpc/vmx_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/vsx_asm.h71
23 files changed, 1426 insertions, 157 deletions
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 1cc6d64c39b7..db54a33f850f 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -19,6 +19,7 @@ SUB_DIRS = alignment \
19 dscr \ 19 dscr \
20 mm \ 20 mm \
21 pmu \ 21 pmu \
22 signal \
22 primitives \ 23 primitives \
23 stringloops \ 24 stringloops \
24 switch_endian \ 25 switch_endian \
diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/fpu_asm.h
new file mode 100644
index 000000000000..6a387d255e27
--- /dev/null
+++ b/tools/testing/selftests/powerpc/fpu_asm.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _SELFTESTS_POWERPC_FPU_ASM_H
11#define _SELFTESTS_POWERPC_FPU_ASM_H
12#include "basic_asm.h"
13
14#define PUSH_FPU(stack_size) \
15 stfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
16 stfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
17 stfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
18 stfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
19 stfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
20 stfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
21 stfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
22 stfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
23 stfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
24 stfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
25 stfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
26 stfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
27 stfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
28 stfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
29 stfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
30 stfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
31 stfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
32 stfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
33
34#define POP_FPU(stack_size) \
35 lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
36 lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
37 lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
38 lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
39 lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
40 lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
41 lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
42 lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
43 lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
44 lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
45 lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
46 lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
47 lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
48 lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
49 lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
50 lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
51 lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
52 lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
53
54/*
55 * Careful calling this, it will 'clobber' fpu (by design)
56 * Don't call this from C
57 */
58FUNC_START(load_fpu)
59 lfd f14,0(r3)
60 lfd f15,8(r3)
61 lfd f16,16(r3)
62 lfd f17,24(r3)
63 lfd f18,32(r3)
64 lfd f19,40(r3)
65 lfd f20,48(r3)
66 lfd f21,56(r3)
67 lfd f22,64(r3)
68 lfd f23,72(r3)
69 lfd f24,80(r3)
70 lfd f25,88(r3)
71 lfd f26,96(r3)
72 lfd f27,104(r3)
73 lfd f28,112(r3)
74 lfd f29,120(r3)
75 lfd f30,128(r3)
76 lfd f31,136(r3)
77 blr
78FUNC_END(load_fpu)
79
80#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */
diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/gpr_asm.h
new file mode 100644
index 000000000000..f6f38852d3a0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/gpr_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _SELFTESTS_POWERPC_GPR_ASM_H
11#define _SELFTESTS_POWERPC_GPR_ASM_H
12
13#include "basic_asm.h"
14
15#define __PUSH_NVREGS(top_pos); \
16 std r31,(top_pos)(%r1); \
17 std r30,(top_pos - 8)(%r1); \
18 std r29,(top_pos - 16)(%r1); \
19 std r28,(top_pos - 24)(%r1); \
20 std r27,(top_pos - 32)(%r1); \
21 std r26,(top_pos - 40)(%r1); \
22 std r25,(top_pos - 48)(%r1); \
23 std r24,(top_pos - 56)(%r1); \
24 std r23,(top_pos - 64)(%r1); \
25 std r22,(top_pos - 72)(%r1); \
26 std r21,(top_pos - 80)(%r1); \
27 std r20,(top_pos - 88)(%r1); \
28 std r19,(top_pos - 96)(%r1); \
29 std r18,(top_pos - 104)(%r1); \
30 std r17,(top_pos - 112)(%r1); \
31 std r16,(top_pos - 120)(%r1); \
32 std r15,(top_pos - 128)(%r1); \
33 std r14,(top_pos - 136)(%r1)
34
35#define __POP_NVREGS(top_pos); \
36 ld r31,(top_pos)(%r1); \
37 ld r30,(top_pos - 8)(%r1); \
38 ld r29,(top_pos - 16)(%r1); \
39 ld r28,(top_pos - 24)(%r1); \
40 ld r27,(top_pos - 32)(%r1); \
41 ld r26,(top_pos - 40)(%r1); \
42 ld r25,(top_pos - 48)(%r1); \
43 ld r24,(top_pos - 56)(%r1); \
44 ld r23,(top_pos - 64)(%r1); \
45 ld r22,(top_pos - 72)(%r1); \
46 ld r21,(top_pos - 80)(%r1); \
47 ld r20,(top_pos - 88)(%r1); \
48 ld r19,(top_pos - 96)(%r1); \
49 ld r18,(top_pos - 104)(%r1); \
50 ld r17,(top_pos - 112)(%r1); \
51 ld r16,(top_pos - 120)(%r1); \
52 ld r15,(top_pos - 128)(%r1); \
53 ld r14,(top_pos - 136)(%r1)
54
55#define PUSH_NVREGS(stack_size) \
56 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
57
58/* 18 NV FPU REGS */
59#define PUSH_NVREGS_BELOW_FPU(stack_size) \
60 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
61
62#define POP_NVREGS(stack_size) \
63 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
64
65/* 18 NV FPU REGS */
66#define POP_NVREGS_BELOW_FPU(stack_size) \
67 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
68
69/*
70 * Careful calling this, it will 'clobber' NVGPRs (by design)
71 * Don't call this from C
72 */
73FUNC_START(load_gpr)
74 ld r14,0(r3)
75 ld r15,8(r3)
76 ld r16,16(r3)
77 ld r17,24(r3)
78 ld r18,32(r3)
79 ld r19,40(r3)
80 ld r20,48(r3)
81 ld r21,56(r3)
82 ld r22,64(r3)
83 ld r23,72(r3)
84 ld r24,80(r3)
85 ld r25,88(r3)
86 ld r26,96(r3)
87 ld r27,104(r3)
88 ld r28,112(r3)
89 ld r29,120(r3)
90 ld r30,128(r3)
91 ld r31,136(r3)
92 blr
93FUNC_END(load_gpr)
94
95
96#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index 52f9be7f61f0..248a820048df 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -19,9 +19,9 @@
19#include "subunit.h" 19#include "subunit.h"
20#include "utils.h" 20#include "utils.h"
21 21
22#define TIMEOUT 120
23#define KILL_TIMEOUT 5 22#define KILL_TIMEOUT 5
24 23
24static uint64_t timeout = 120;
25 25
26int run_test(int (test_function)(void), char *name) 26int run_test(int (test_function)(void), char *name)
27{ 27{
@@ -44,7 +44,7 @@ int run_test(int (test_function)(void), char *name)
44 setpgid(pid, pid); 44 setpgid(pid, pid);
45 45
46 /* Wake us up in timeout seconds */ 46 /* Wake us up in timeout seconds */
47 alarm(TIMEOUT); 47 alarm(timeout);
48 terminated = false; 48 terminated = false;
49 49
50wait: 50wait:
@@ -94,6 +94,11 @@ static struct sigaction alarm_action = {
94 .sa_handler = alarm_handler, 94 .sa_handler = alarm_handler,
95}; 95};
96 96
97void test_harness_set_timeout(uint64_t time)
98{
99 timeout = time;
100}
101
97int test_harness(int (test_function)(void), char *name) 102int test_harness(int (test_function)(void), char *name)
98{ 103{
99 int rc; 104 int rc;
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
index 5b88875d5955..a505b66d408a 100644
--- a/tools/testing/selftests/powerpc/math/Makefile
+++ b/tools/testing/selftests/powerpc/math/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal 1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -13,6 +13,9 @@ vmx_syscall: vmx_asm.S
13vmx_preempt: vmx_asm.S 13vmx_preempt: vmx_asm.S
14vmx_signal: vmx_asm.S 14vmx_signal: vmx_asm.S
15 15
16vsx_preempt: CFLAGS += -mvsx
17vsx_preempt: vsx_asm.S
18
16include ../../lib.mk 19include ../../lib.mk
17 20
18clean: 21clean:
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
index f3711d80e709..241f067a510f 100644
--- a/tools/testing/selftests/powerpc/math/fpu_asm.S
+++ b/tools/testing/selftests/powerpc/math/fpu_asm.S
@@ -8,70 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../fpu_asm.h"
12#define PUSH_FPU(pos) \
13 stfd f14,pos(sp); \
14 stfd f15,pos+8(sp); \
15 stfd f16,pos+16(sp); \
16 stfd f17,pos+24(sp); \
17 stfd f18,pos+32(sp); \
18 stfd f19,pos+40(sp); \
19 stfd f20,pos+48(sp); \
20 stfd f21,pos+56(sp); \
21 stfd f22,pos+64(sp); \
22 stfd f23,pos+72(sp); \
23 stfd f24,pos+80(sp); \
24 stfd f25,pos+88(sp); \
25 stfd f26,pos+96(sp); \
26 stfd f27,pos+104(sp); \
27 stfd f28,pos+112(sp); \
28 stfd f29,pos+120(sp); \
29 stfd f30,pos+128(sp); \
30 stfd f31,pos+136(sp);
31
32#define POP_FPU(pos) \
33 lfd f14,pos(sp); \
34 lfd f15,pos+8(sp); \
35 lfd f16,pos+16(sp); \
36 lfd f17,pos+24(sp); \
37 lfd f18,pos+32(sp); \
38 lfd f19,pos+40(sp); \
39 lfd f20,pos+48(sp); \
40 lfd f21,pos+56(sp); \
41 lfd f22,pos+64(sp); \
42 lfd f23,pos+72(sp); \
43 lfd f24,pos+80(sp); \
44 lfd f25,pos+88(sp); \
45 lfd f26,pos+96(sp); \
46 lfd f27,pos+104(sp); \
47 lfd f28,pos+112(sp); \
48 lfd f29,pos+120(sp); \
49 lfd f30,pos+128(sp); \
50 lfd f31,pos+136(sp);
51
52# Careful calling this, it will 'clobber' fpu (by design)
53# Don't call this from C
54FUNC_START(load_fpu)
55 lfd f14,0(r3)
56 lfd f15,8(r3)
57 lfd f16,16(r3)
58 lfd f17,24(r3)
59 lfd f18,32(r3)
60 lfd f19,40(r3)
61 lfd f20,48(r3)
62 lfd f21,56(r3)
63 lfd f22,64(r3)
64 lfd f23,72(r3)
65 lfd f24,80(r3)
66 lfd f25,88(r3)
67 lfd f26,96(r3)
68 lfd f27,104(r3)
69 lfd f28,112(r3)
70 lfd f29,120(r3)
71 lfd f30,128(r3)
72 lfd f31,136(r3)
73 blr
74FUNC_END(load_fpu)
75 12
76FUNC_START(check_fpu) 13FUNC_START(check_fpu)
77 mr r4,r3 14 mr r4,r3
@@ -138,9 +75,9 @@ FUNC_START(test_fpu)
138 # r4 holds pointer to the pid 75 # r4 holds pointer to the pid
139 # f14-f31 are non volatiles 76 # f14-f31 are non volatiles
140 PUSH_BASIC_STACK(256) 77 PUSH_BASIC_STACK(256)
78 PUSH_FPU(256)
141 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray 79 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
142 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid 80 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
143 PUSH_FPU(STACK_FRAME_LOCAL(2,0))
144 81
145 bl load_fpu 82 bl load_fpu
146 nop 83 nop
@@ -155,7 +92,7 @@ FUNC_START(test_fpu)
155 bl check_fpu 92 bl check_fpu
156 nop 93 nop
157 94
158 POP_FPU(STACK_FRAME_LOCAL(2,0)) 95 POP_FPU(256)
159 POP_BASIC_STACK(256) 96 POP_BASIC_STACK(256)
160 blr 97 blr
161FUNC_END(test_fpu) 98FUNC_END(test_fpu)
@@ -166,10 +103,10 @@ FUNC_END(test_fpu)
166# registers while running is not zero. 103# registers while running is not zero.
167FUNC_START(preempt_fpu) 104FUNC_START(preempt_fpu)
168 PUSH_BASIC_STACK(256) 105 PUSH_BASIC_STACK(256)
106 PUSH_FPU(256)
169 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray 107 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
170 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting 108 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
171 std r5,STACK_FRAME_PARAM(2)(sp) # int *running 109 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
172 PUSH_FPU(STACK_FRAME_LOCAL(3,0))
173 110
174 bl load_fpu 111 bl load_fpu
175 nop 112 nop
@@ -192,7 +129,7 @@ FUNC_START(preempt_fpu)
192 cmpwi r5,0 129 cmpwi r5,0
193 bne 2b 130 bne 2b
194 131
1953: POP_FPU(STACK_FRAME_LOCAL(3,0)) 1323: POP_FPU(256)
196 POP_BASIC_STACK(256) 133 POP_BASIC_STACK(256)
197 blr 134 blr
198FUNC_END(preempt_fpu) 135FUNC_END(preempt_fpu)
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
index 1b8c248b3ac1..fd74da488625 100644
--- a/tools/testing/selftests/powerpc/math/vmx_asm.S
+++ b/tools/testing/selftests/powerpc/math/vmx_asm.S
@@ -8,90 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../vmx_asm.h"
12# POS MUST BE 16 ALIGNED!
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,sp; \
16 addi reg,reg,16; \
17 stvx v21,reg,sp; \
18 addi reg,reg,16; \
19 stvx v22,reg,sp; \
20 addi reg,reg,16; \
21 stvx v23,reg,sp; \
22 addi reg,reg,16; \
23 stvx v24,reg,sp; \
24 addi reg,reg,16; \
25 stvx v25,reg,sp; \
26 addi reg,reg,16; \
27 stvx v26,reg,sp; \
28 addi reg,reg,16; \
29 stvx v27,reg,sp; \
30 addi reg,reg,16; \
31 stvx v28,reg,sp; \
32 addi reg,reg,16; \
33 stvx v29,reg,sp; \
34 addi reg,reg,16; \
35 stvx v30,reg,sp; \
36 addi reg,reg,16; \
37 stvx v31,reg,sp;
38
39# POS MUST BE 16 ALIGNED!
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,sp; \
43 addi reg,reg,16; \
44 lvx v21,reg,sp; \
45 addi reg,reg,16; \
46 lvx v22,reg,sp; \
47 addi reg,reg,16; \
48 lvx v23,reg,sp; \
49 addi reg,reg,16; \
50 lvx v24,reg,sp; \
51 addi reg,reg,16; \
52 lvx v25,reg,sp; \
53 addi reg,reg,16; \
54 lvx v26,reg,sp; \
55 addi reg,reg,16; \
56 lvx v27,reg,sp; \
57 addi reg,reg,16; \
58 lvx v28,reg,sp; \
59 addi reg,reg,16; \
60 lvx v29,reg,sp; \
61 addi reg,reg,16; \
62 lvx v30,reg,sp; \
63 addi reg,reg,16; \
64 lvx v31,reg,sp;
65
66# Carefull this will 'clobber' vmx (by design)
67# Don't call this from C
68FUNC_START(load_vmx)
69 li r5,0
70 lvx v20,r5,r3
71 addi r5,r5,16
72 lvx v21,r5,r3
73 addi r5,r5,16
74 lvx v22,r5,r3
75 addi r5,r5,16
76 lvx v23,r5,r3
77 addi r5,r5,16
78 lvx v24,r5,r3
79 addi r5,r5,16
80 lvx v25,r5,r3
81 addi r5,r5,16
82 lvx v26,r5,r3
83 addi r5,r5,16
84 lvx v27,r5,r3
85 addi r5,r5,16
86 lvx v28,r5,r3
87 addi r5,r5,16
88 lvx v29,r5,r3
89 addi r5,r5,16
90 lvx v30,r5,r3
91 addi r5,r5,16
92 lvx v31,r5,r3
93 blr
94FUNC_END(load_vmx)
95 12
96# Should be safe from C, only touches r4, r5 and v0,v1,v2 13# Should be safe from C, only touches r4, r5 and v0,v1,v2
97FUNC_START(check_vmx) 14FUNC_START(check_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S
new file mode 100644
index 000000000000..a110dd882d5e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_asm.S
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11#include "../vsx_asm.h"
12
13#long check_vsx(vector int *r3);
14#This function wraps storeing VSX regs to the end of an array and a
15#call to a comparison function in C which boils down to a memcmp()
16FUNC_START(check_vsx)
17 PUSH_BASIC_STACK(32)
18 std r3,STACK_FRAME_PARAM(0)(sp)
19 addi r3, r3, 16 * 12 #Second half of array
20 bl store_vsx
21 ld r3,STACK_FRAME_PARAM(0)(sp)
22 bl vsx_memcmp
23 POP_BASIC_STACK(32)
24 blr
25FUNC_END(check_vsx)
26
27# int preempt_vmx(vector int *varray, int *threads_starting,
28# int *running);
29# On starting will (atomically) decrement threads_starting as a signal
30# that the VMX have been loaded with varray. Will proceed to check the
31# validity of the VMX registers while running is not zero.
32FUNC_START(preempt_vsx)
33 PUSH_BASIC_STACK(512)
34 std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
35 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
36 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
37
38 bl load_vsx
39 nop
40
41 sync
42 # Atomic DEC
43 ld r3,STACK_FRAME_PARAM(1)(sp)
441: lwarx r4,0,r3
45 addi r4,r4,-1
46 stwcx. r4,0,r3
47 bne- 1b
48
492: ld r3,STACK_FRAME_PARAM(0)(sp)
50 bl check_vsx
51 nop
52 cmpdi r3,0
53 bne 3f
54 ld r4,STACK_FRAME_PARAM(2)(sp)
55 ld r5,0(r4)
56 cmpwi r5,0
57 bne 2b
58
593: POP_BASIC_STACK(512)
60 blr
61FUNC_END(preempt_vsx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_preempt.c b/tools/testing/selftests/powerpc/math/vsx_preempt.c
new file mode 100644
index 000000000000..6387f03a0a6a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_preempt.c
@@ -0,0 +1,147 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * This test attempts to see if the VSX registers change across preemption.
10 * There is no way to be sure preemption happened so this test just
11 * uses many threads and a long wait. As such, a successful test
12 * doesn't mean much but a failure is bad.
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <unistd.h>
18#include <sys/syscall.h>
19#include <sys/time.h>
20#include <sys/types.h>
21#include <sys/wait.h>
22#include <stdlib.h>
23#include <pthread.h>
24
25#include "utils.h"
26
27/* Time to wait for workers to get preempted (seconds) */
28#define PREEMPT_TIME 20
29/*
30 * Factor by which to multiply number of online CPUs for total number of
31 * worker threads
32 */
33#define THREAD_FACTOR 8
34
35/*
36 * Ensure there is twice the number of non-volatile VMX regs!
37 * check_vmx() is going to use the other half as space to put the live
38 * registers before calling vsx_memcmp()
39 */
40__thread vector int varray[24] = {
41 {1, 2, 3, 4 }, {5, 6, 7, 8 }, {9, 10,11,12},
42 {13,14,15,16}, {17,18,19,20}, {21,22,23,24},
43 {25,26,27,28}, {29,30,31,32}, {33,34,35,36},
44 {37,38,39,40}, {41,42,43,44}, {45,46,47,48}
45};
46
47int threads_starting;
48int running;
49
50extern long preempt_vsx(vector int *varray, int *threads_starting, int *running);
51
52long vsx_memcmp(vector int *a) {
53 vector int zero = {0, 0, 0, 0};
54 int i;
55
56 FAIL_IF(a != varray);
57
58 for(i = 0; i < 12; i++) {
59 if (memcmp(&a[i + 12], &zero, sizeof(vector int)) == 0) {
60 fprintf(stderr, "Detected zero from the VSX reg %d\n", i + 12);
61 return 2;
62 }
63 }
64
65 if (memcmp(a, &a[12], 12 * sizeof(vector int))) {
66 long *p = (long *)a;
67 fprintf(stderr, "VSX mismatch\n");
68 for (i = 0; i < 24; i=i+2)
69 fprintf(stderr, "%d: 0x%08lx%08lx | 0x%08lx%08lx\n",
70 i/2 + i%2 + 20, p[i], p[i + 1], p[i + 24], p[i + 25]);
71 return 1;
72 }
73 return 0;
74}
75
76void *preempt_vsx_c(void *p)
77{
78 int i, j;
79 long rc;
80 srand(pthread_self());
81 for (i = 0; i < 12; i++)
82 for (j = 0; j < 4; j++) {
83 varray[i][j] = rand();
84 /* Don't want zero because it hides kernel problems */
85 if (varray[i][j] == 0)
86 j--;
87 }
88 rc = preempt_vsx(varray, &threads_starting, &running);
89 if (rc == 2)
90 fprintf(stderr, "Caught zeros in VSX compares\n");
91 return (void *)rc;
92}
93
94int test_preempt_vsx(void)
95{
96 int i, rc, threads;
97 pthread_t *tids;
98
99 threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
100 tids = malloc(threads * sizeof(pthread_t));
101 FAIL_IF(!tids);
102
103 running = true;
104 threads_starting = threads;
105 for (i = 0; i < threads; i++) {
106 rc = pthread_create(&tids[i], NULL, preempt_vsx_c, NULL);
107 FAIL_IF(rc);
108 }
109
110 setbuf(stdout, NULL);
111 /* Not really nessesary but nice to wait for every thread to start */
112 printf("\tWaiting for %d workers to start...", threads_starting);
113 while(threads_starting)
114 asm volatile("": : :"memory");
115 printf("done\n");
116
117 printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
118 sleep(PREEMPT_TIME);
119 printf("done\n");
120
121 printf("\tStopping workers...");
122 /*
123 * Working are checking this value every loop. In preempt_vsx 'cmpwi r5,0; bne 2b'.
124 * r5 will have loaded the value of running.
125 */
126 running = 0;
127 for (i = 0; i < threads; i++) {
128 void *rc_p;
129 pthread_join(tids[i], &rc_p);
130
131 /*
132 * Harness will say the fail was here, look at why preempt_vsx
133 * returned
134 */
135 if ((long) rc_p)
136 printf("oops\n");
137 FAIL_IF((long) rc_p);
138 }
139 printf("done\n");
140
141 return 0;
142}
143
144int main(int argc, char *argv[])
145{
146 return test_harness(test_preempt_vsx, "vsx_preempt");
147}
diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile
new file mode 100644
index 000000000000..f0eef27458e2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/Makefile
@@ -0,0 +1,13 @@
1TEST_PROGS := signal signal_tm
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c signal.S
6
7CFLAGS += -maltivec
8signal_tm: CFLAGS += -mhtm
9
10include ../../lib.mk
11
12clean:
13 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S
new file mode 100644
index 000000000000..7043d521df0a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.S
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11
12/* long signal_self(pid_t pid, int sig); */
13FUNC_START(signal_self)
14 li r0,37 /* sys_kill */
15 /* r3 already has our pid in it */
16 /* r4 already has signal type in it */
17 sc
18 bc 4,3,1f
19 subfze r3,r3
201: blr
21FUNC_END(signal_self)
22
23/* long tm_signal_self(pid_t pid, int sig, int *ret); */
24FUNC_START(tm_signal_self)
25 PUSH_BASIC_STACK(8)
26 std r5,STACK_FRAME_PARAM(0)(sp) /* ret */
27 tbegin.
28 beq 1f
29 tsuspend.
30 li r0,37 /* sys_kill */
31 /* r3 already has our pid in it */
32 /* r4 already has signal type in it */
33 sc
34 ld r5,STACK_FRAME_PARAM(0)(sp) /* ret */
35 bc 4,3,2f
36 subfze r3,r3
372: std r3,0(r5)
38 tabort. 0
39 tresume. /* Be nice to some cleanup, jumps back to tbegin then to 1: */
40 /*
41 * Transaction should be proper doomed and we should never get
42 * here
43 */
44 li r3,1
45 POP_BASIC_STACK(8)
46 blr
471: li r3,0
48 POP_BASIC_STACK(8)
49 blr
50FUNC_END(tm_signal_self)
diff --git a/tools/testing/selftests/powerpc/signal/signal.c b/tools/testing/selftests/powerpc/signal/signal.c
new file mode 100644
index 000000000000..e7dedd28b3c2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Sending one self a signal should always get delivered.
10 */
11
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <unistd.h>
19
20#include <altivec.h>
21
22#include "utils.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 5
26
27extern long signal_self(pid_t pid, int sig);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (sig == SIGUSR1)
35 signaled = 1;
36 else
37 fail = 1;
38}
39
40static int test_signal()
41{
42 int i;
43 struct sigaction act;
44 pid_t ppid = getpid();
45 pid_t pid;
46
47 act.sa_handler = signal_handler;
48 act.sa_flags = 0;
49 sigemptyset(&act.sa_mask);
50 if (sigaction(SIGUSR1, &act, NULL) < 0) {
51 perror("sigaction SIGUSR1");
52 exit(1);
53 }
54 if (sigaction(SIGALRM, &act, NULL) < 0) {
55 perror("sigaction SIGALRM");
56 exit(1);
57 }
58
59 /* Don't do this for MAX_ATTEMPT, its simply too long */
60 for(i = 0; i < 1000; i++) {
61 pid = fork();
62 if (pid == -1) {
63 perror("fork");
64 exit(1);
65 }
66 if (pid == 0) {
67 signal_self(ppid, SIGUSR1);
68 exit(1);
69 } else {
70 alarm(0); /* Disable any pending */
71 alarm(2);
72 while (!signaled && !fail)
73 asm volatile("": : :"memory");
74 if (!signaled) {
75 fprintf(stderr, "Didn't get signal from child\n");
76 FAIL_IF(1); /* For the line number */
77 }
78 /* Otherwise we'll loop too fast and fork() will eventually fail */
79 waitpid(pid, NULL, 0);
80 }
81 }
82
83 for (i = 0; i < MAX_ATTEMPT; i++) {
84 long rc;
85
86 alarm(0); /* Disable any pending */
87 signaled = 0;
88 alarm(TIMEOUT);
89 rc = signal_self(ppid, SIGUSR1);
90 if (rc) {
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
92 i, fail, rc);
93 FAIL_IF(1); /* For the line number */
94 }
95 while (!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
99 i, fail, rc);
100 FAIL_IF(1); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 test_harness_set_timeout(300);
110 return test_harness(test_signal, "signal");
111}
diff --git a/tools/testing/selftests/powerpc/signal/signal_tm.c b/tools/testing/selftests/powerpc/signal/signal_tm.c
new file mode 100644
index 000000000000..2e7451a37cc6
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal_tm.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Sending one self a signal should always get delivered.
10 */
11
12#include <errno.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <signal.h>
17#include <unistd.h>
18
19#include <altivec.h>
20
21#include "utils.h"
22#include "../tm/tm.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 10
26
27extern long tm_signal_self(pid_t pid, int sig, long *ret);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (tcheck_active()) {
35 fail = 2;
36 return;
37 }
38
39 if (sig == SIGUSR1)
40 signaled = 1;
41 else
42 fail = 1;
43}
44
45static int test_signal_tm()
46{
47 int i;
48 struct sigaction act;
49
50 act.sa_handler = signal_handler;
51 act.sa_flags = 0;
52 sigemptyset(&act.sa_mask);
53 if (sigaction(SIGUSR1, &act, NULL) < 0) {
54 perror("sigaction SIGUSR1");
55 exit(1);
56 }
57 if (sigaction(SIGALRM, &act, NULL) < 0) {
58 perror("sigaction SIGALRM");
59 exit(1);
60 }
61
62 SKIP_IF(!have_htm());
63
64 for (i = 0; i < MAX_ATTEMPT; i++) {
65 /*
66 * If anything bad happens in ASM and we fail to set ret
67 * because *handwave* TM this will cause failure
68 */
69 long ret = 0xdead;
70 long rc = 0xbeef;
71
72 alarm(0); /* Disable any pending */
73 signaled = 0;
74 alarm(TIMEOUT);
75 FAIL_IF(tcheck_transactional());
76 rc = tm_signal_self(getpid(), SIGUSR1, &ret);
77 if (ret == 0xdead)
78 /*
79 * This basically means the transaction aborted before we
80 * even got to the suspend... this is crazy but it
81 * happens.
82 * Yes this also means we might never make forward
83 * progress... the alarm() will trip eventually...
84 */
85 continue;
86
87 if (rc || ret) {
88 /* Ret is actually an errno */
89 printf("TEXASR 0x%016lx, TFIAR 0x%016lx\n",
90 __builtin_get_texasr(), __builtin_get_tfiar());
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
92 i, fail, rc, ret);
93 FAIL_IF(ret);
94 }
95 while(!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
99 i, fail, rc, ret);
100 FAIL_IF(fail); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 return test_harness(test_signal_tm, "signal_tm");
110}
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 9d301d785d9e..c6c53c82fdd6 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,5 +1,8 @@
1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \
2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
3
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 4TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
2 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-exec tm-execed 5 tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
3 6
4all: $(TEST_PROGS) 7all: $(TEST_PROGS)
5 8
@@ -11,6 +14,9 @@ tm-syscall: tm-syscall-asm.S
11tm-syscall: CFLAGS += -I../../../../../usr/include 14tm-syscall: CFLAGS += -I../../../../../usr/include
12tm-tmspr: CFLAGS += -pthread 15tm-tmspr: CFLAGS += -pthread
13 16
17$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
18$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx
19
14include ../../lib.mk 20include ../../lib.mk
15 21
16clean: 22clean:
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
new file mode 100644
index 000000000000..c760debbd5ad
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
@@ -0,0 +1,92 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_FPU_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40/* Be sure there are 2x as many as there are NV FPU regs (2x18) */
41static double fps[] = {
42 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
44};
45
46static sig_atomic_t fail;
47
48static void signal_usr1(int signum, siginfo_t *info, void *uc)
49{
50 int i;
51 ucontext_t *ucp = uc;
52 ucontext_t *tm_ucp = ucp->uc_link;
53
54 for (i = 0; i < NV_FPU_REGS && !fail; i++) {
55 fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]);
56 fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]);
57 if (fail)
58 printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]);
59 }
60}
61
62static int tm_signal_context_chk_fpu()
63{
64 struct sigaction act;
65 int i;
66 long rc;
67 pid_t pid = getpid();
68
69 SKIP_IF(!have_htm());
70
71 act.sa_sigaction = signal_usr1;
72 sigemptyset(&act.sa_mask);
73 act.sa_flags = SA_SIGINFO;
74 if (sigaction(SIGUSR1, &act, NULL) < 0) {
75 perror("sigaction sigusr1");
76 exit(1);
77 }
78
79 i = 0;
80 while (i < MAX_ATTEMPT && !fail) {
81 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
82 FAIL_IF(rc != pid);
83 i++;
84 }
85
86 return fail;
87}
88
89int main(void)
90{
91 return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu");
92}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
new file mode 100644
index 000000000000..df91330a08ef
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_GPR_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40static sig_atomic_t fail;
41
42static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18};
44
45static void signal_usr1(int signum, siginfo_t *info, void *uc)
46{
47 int i;
48 ucontext_t *ucp = uc;
49 ucontext_t *tm_ucp = ucp->uc_link;
50
51 for (i = 0; i < NV_GPR_REGS && !fail; i++) {
52 fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]);
53 fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]);
54 if (fail)
55 printf("Failed on %d GPR %lu or %lu\n", i,
56 ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]);
57 }
58}
59
60static int tm_signal_context_chk_gpr()
61{
62 struct sigaction act;
63 int i;
64 long rc;
65 pid_t pid = getpid();
66
67 SKIP_IF(!have_htm());
68
69 act.sa_sigaction = signal_usr1;
70 sigemptyset(&act.sa_mask);
71 act.sa_flags = SA_SIGINFO;
72 if (sigaction(SIGUSR1, &act, NULL) < 0) {
73 perror("sigaction sigusr1");
74 exit(1);
75 }
76
77 i = 0;
78 while (i < MAX_ATTEMPT && !fail) {
79 rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL);
80 FAIL_IF(rc != pid);
81 i++;
82 }
83
84 return fail;
85}
86
87int main(void)
88{
89 return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
new file mode 100644
index 000000000000..f0ee55fd5185
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VMX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vms[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 ucontext_t *ucp = uc;
58 ucontext_t *tm_ucp = ucp->uc_link;
59
60 for (i = 0; i < NV_VMX_REGS && !fail; i++) {
61 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20],
62 &vms[i], sizeof(vector int));
63 fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20],
64 &vms[i + NV_VMX_REGS], sizeof (vector int));
65
66 if (fail) {
67 int j;
68
69 fprintf(stderr, "Failed on %d vmx 0x", i);
70 for (j = 0; j < 4; j++)
71 fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
72 fprintf(stderr, " vs 0x");
73 for (j = 0 ; j < 4; j++)
74 fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
75 fprintf(stderr, "\n");
76 }
77 }
78}
79
80static int tm_signal_context_chk()
81{
82 struct sigaction act;
83 int i;
84 long rc;
85 pid_t pid = getpid();
86
87 SKIP_IF(!have_htm());
88
89 act.sa_sigaction = signal_usr1;
90 sigemptyset(&act.sa_mask);
91 act.sa_flags = SA_SIGINFO;
92 if (sigaction(SIGUSR1, &act, NULL) < 0) {
93 perror("sigaction sigusr1");
94 exit(1);
95 }
96
97 i = 0;
98 while (i < MAX_ATTEMPT && !fail) {
99 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
100 FAIL_IF(rc != pid);
101 i++;
102 }
103
104 return fail;
105}
106
107int main(void)
108{
109 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx");
110}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
new file mode 100644
index 000000000000..b99c3d835957
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
@@ -0,0 +1,125 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VSX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vss[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 uint8_t vsc[sizeof(vector int)];
58 uint8_t vst[sizeof(vector int)];
59 ucontext_t *ucp = uc;
60 ucontext_t *tm_ucp = ucp->uc_link;
61
62 /*
63 * The other half of the VSX regs will be after v_regs.
64 *
65 * In short, vmx_reserve array holds everything. v_regs is a 16
66 * byte aligned pointer at the start of vmx_reserve (vmx_reserve
67 * may or may not be 16 aligned) where the v_regs structure exists.
68 * (half of) The VSX regsters are directly after v_regs so the
69 * easiest way to find them below.
70 */
71 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1);
72 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1);
73 for (i = 0; i < NV_VSX_REGS && !fail; i++) {
74 memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8);
75 memcpy(vsc + 8, &vsx_ptr[20 + i], 8);
76 fail = memcmp(vsc, &vss[i], sizeof(vector int));
77 memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8);
78 memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8);
79 fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int));
80
81 if (fail) {
82 int j;
83
84 fprintf(stderr, "Failed on %d vsx 0x", i);
85 for (j = 0; j < 16; j++)
86 fprintf(stderr, "%02x", vsc[j]);
87 fprintf(stderr, " vs 0x");
88 for (j = 0; j < 16; j++)
89 fprintf(stderr, "%02x", vst[j]);
90 fprintf(stderr, "\n");
91 }
92 }
93}
94
95static int tm_signal_context_chk()
96{
97 struct sigaction act;
98 int i;
99 long rc;
100 pid_t pid = getpid();
101
102 SKIP_IF(!have_htm());
103
104 act.sa_sigaction = signal_usr1;
105 sigemptyset(&act.sa_mask);
106 act.sa_flags = SA_SIGINFO;
107 if (sigaction(SIGUSR1, &act, NULL) < 0) {
108 perror("sigaction sigusr1");
109 exit(1);
110 }
111
112 i = 0;
113 while (i < MAX_ATTEMPT && !fail) {
114 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss);
115 FAIL_IF(rc != pid);
116 i++;
117 }
118
119 return fail;
120}
121
122int main(void)
123{
124 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vsx");
125}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S
new file mode 100644
index 000000000000..4e13e8b3a96f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal.S
@@ -0,0 +1,114 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11#include "../gpr_asm.h"
12#include "../fpu_asm.h"
13#include "../vmx_asm.h"
14#include "../vsx_asm.h"
15
16/*
17 * Large caveat here being that the caller cannot expect the
18 * signal to always be sent! The hardware can (AND WILL!) abort
19 * the transaction between the tbegin and the tsuspend (however
20 * unlikely it seems or infrequently it actually happens).
21 * You have been warned.
22 */
23/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
24FUNC_START(tm_signal_self_context_load)
25 PUSH_BASIC_STACK(512)
26 /*
27 * Don't strictly need to save and restore as it depends on if
28 * we're going to use them, however this reduces messy logic
29 */
30 PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
31 PUSH_FPU(512)
32 PUSH_NVREGS_BELOW_FPU(512)
33 std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
34 std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
35 std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
36 std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
37 std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
38
39 ld r3, STACK_FRAME_PARAM(1)(sp)
40 cmpdi r3, 0
41 beq skip_gpr_lc
42 bl load_gpr
43skip_gpr_lc:
44 ld r3, STACK_FRAME_PARAM(2)(sp)
45 cmpdi r3, 0
46 beq skip_fpu_lc
47 bl load_fpu
48skip_fpu_lc:
49 ld r3, STACK_FRAME_PARAM(3)(sp)
50 cmpdi r3, 0
51 beq skip_vmx_lc
52 bl load_vmx
53skip_vmx_lc:
54 ld r3, STACK_FRAME_PARAM(4)(sp)
55 cmpdi r3, 0
56 beq skip_vsx_lc
57 bl load_vsx
58skip_vsx_lc:
59 /*
60 * Set r3 (return value) before tbegin. Use the pid as a known
61 * 'all good' return value, zero is used to indicate a non-doomed
62 * transaction.
63 */
64 ld r3, STACK_FRAME_PARAM(0)(sp)
65 tbegin.
66 beq 1f
67 tsuspend. /* Can't enter a syscall transactionally */
68 ld r3, STACK_FRAME_PARAM(1)(sp)
69 cmpdi r3, 0
70 beq skip_gpr_lt
71 /* Get the second half of the array */
72 addi r3, r3, 8 * 18
73 bl load_gpr
74skip_gpr_lt:
75 ld r3, STACK_FRAME_PARAM(2)(sp)
76 cmpdi r3, 0
77 beq skip_fpu_lt
78 /* Get the second half of the array */
79 addi r3, r3, 8 * 18
80 bl load_fpu
81skip_fpu_lt:
82 ld r3, STACK_FRAME_PARAM(3)(sp)
83 cmpdi r3, 0
84 beq skip_vmx_lt
85 /* Get the second half of the array */
86 addi r3, r3, 16 * 12
87 bl load_vmx
88skip_vmx_lt:
89 ld r3, STACK_FRAME_PARAM(4)(sp)
90 cmpdi r3, 0
91 beq skip_vsx_lt
92 /* Get the second half of the array */
93 addi r3, r3, 16 * 12
94 bl load_vsx
95skip_vsx_lt:
96 li r0, 37 /* sys_kill */
97 ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
98 li r4, 10 /* SIGUSR1 */
99 sc /* Taking the signal will doom the transaction */
100 tabort. 0
101 tresume. /* Be super sure we abort */
102 /*
103 * This will cause us to resume doomed transaction and cause
104 * hardware to cleanup, we'll end up at 1: anything between
105 * tresume. and 1: shouldn't ever run.
106 */
107 li r3, 0
108 1:
109 POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
110 POP_FPU(512)
111 POP_NVREGS_BELOW_FPU(512)
112 POP_BASIC_STACK(512)
113 blr
114FUNC_END(tm_signal_self_context_load)
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index 60318bad7d7a..2c8da74304e7 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -52,4 +52,31 @@ static inline bool failure_is_nesting(void)
52 return (__builtin_get_texasru() & 0x400000); 52 return (__builtin_get_texasru() & 0x400000);
53} 53}
54 54
55static inline int tcheck(void)
56{
57 long cr;
58 asm volatile ("tcheck 0" : "=r"(cr) : : "cr0");
59 return (cr >> 28) & 4;
60}
61
62static inline bool tcheck_doomed(void)
63{
64 return tcheck() & 8;
65}
66
67static inline bool tcheck_active(void)
68{
69 return tcheck() & 4;
70}
71
72static inline bool tcheck_suspended(void)
73{
74 return tcheck() & 2;
75}
76
77static inline bool tcheck_transactional(void)
78{
79 return tcheck() & 6;
80}
81
55#endif /* _SELFTESTS_POWERPC_TM_TM_H */ 82#endif /* _SELFTESTS_POWERPC_TM_TM_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index fbd33e52ef8f..53405e8a52ab 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -22,7 +22,7 @@ typedef uint32_t u32;
22typedef uint16_t u16; 22typedef uint16_t u16;
23typedef uint8_t u8; 23typedef uint8_t u8;
24 24
25 25void test_harness_set_timeout(uint64_t time);
26int test_harness(int (test_function)(void), char *name); 26int test_harness(int (test_function)(void), char *name);
27extern void *get_auxv_entry(int type); 27extern void *get_auxv_entry(int type);
28int pick_online_cpu(void); 28int pick_online_cpu(void);
@@ -32,10 +32,17 @@ static inline bool have_hwcap(unsigned long ftr)
32 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; 32 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr;
33} 33}
34 34
35#ifdef AT_HWCAP2
35static inline bool have_hwcap2(unsigned long ftr2) 36static inline bool have_hwcap2(unsigned long ftr2)
36{ 37{
37 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; 38 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2;
38} 39}
40#else
41static inline bool have_hwcap2(unsigned long ftr2)
42{
43 return false;
44}
45#endif
39 46
40/* Yes, this is evil */ 47/* Yes, this is evil */
41#define FAIL_IF(x) \ 48#define FAIL_IF(x) \
diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/vmx_asm.h
new file mode 100644
index 000000000000..2eaaeca9cf1d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vmx_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "basic_asm.h"
11
12/* POS MUST BE 16 ALIGNED! */
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,%r1; \
16 addi reg,reg,16; \
17 stvx v21,reg,%r1; \
18 addi reg,reg,16; \
19 stvx v22,reg,%r1; \
20 addi reg,reg,16; \
21 stvx v23,reg,%r1; \
22 addi reg,reg,16; \
23 stvx v24,reg,%r1; \
24 addi reg,reg,16; \
25 stvx v25,reg,%r1; \
26 addi reg,reg,16; \
27 stvx v26,reg,%r1; \
28 addi reg,reg,16; \
29 stvx v27,reg,%r1; \
30 addi reg,reg,16; \
31 stvx v28,reg,%r1; \
32 addi reg,reg,16; \
33 stvx v29,reg,%r1; \
34 addi reg,reg,16; \
35 stvx v30,reg,%r1; \
36 addi reg,reg,16; \
37 stvx v31,reg,%r1;
38
39/* POS MUST BE 16 ALIGNED! */
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,%r1; \
43 addi reg,reg,16; \
44 lvx v21,reg,%r1; \
45 addi reg,reg,16; \
46 lvx v22,reg,%r1; \
47 addi reg,reg,16; \
48 lvx v23,reg,%r1; \
49 addi reg,reg,16; \
50 lvx v24,reg,%r1; \
51 addi reg,reg,16; \
52 lvx v25,reg,%r1; \
53 addi reg,reg,16; \
54 lvx v26,reg,%r1; \
55 addi reg,reg,16; \
56 lvx v27,reg,%r1; \
57 addi reg,reg,16; \
58 lvx v28,reg,%r1; \
59 addi reg,reg,16; \
60 lvx v29,reg,%r1; \
61 addi reg,reg,16; \
62 lvx v30,reg,%r1; \
63 addi reg,reg,16; \
64 lvx v31,reg,%r1;
65
66/*
67 * Careful this will 'clobber' vmx (by design)
68 * Don't call this from C
69 */
70FUNC_START(load_vmx)
71 li r5,0
72 lvx v20,r5,r3
73 addi r5,r5,16
74 lvx v21,r5,r3
75 addi r5,r5,16
76 lvx v22,r5,r3
77 addi r5,r5,16
78 lvx v23,r5,r3
79 addi r5,r5,16
80 lvx v24,r5,r3
81 addi r5,r5,16
82 lvx v25,r5,r3
83 addi r5,r5,16
84 lvx v26,r5,r3
85 addi r5,r5,16
86 lvx v27,r5,r3
87 addi r5,r5,16
88 lvx v28,r5,r3
89 addi r5,r5,16
90 lvx v29,r5,r3
91 addi r5,r5,16
92 lvx v30,r5,r3
93 addi r5,r5,16
94 lvx v31,r5,r3
95 blr
96FUNC_END(load_vmx)
diff --git a/tools/testing/selftests/powerpc/vsx_asm.h b/tools/testing/selftests/powerpc/vsx_asm.h
new file mode 100644
index 000000000000..d828bfb6ef2d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vsx_asm.h
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "basic_asm.h"
11
12/*
13 * Careful this will 'clobber' vsx (by design), VSX are always
14 * volatile though so unlike vmx this isn't so much of an issue
15 * Still should avoid calling from C
16 */
17FUNC_START(load_vsx)
18 li r5,0
19 lxvx vs20,r5,r3
20 addi r5,r5,16
21 lxvx vs21,r5,r3
22 addi r5,r5,16
23 lxvx vs22,r5,r3
24 addi r5,r5,16
25 lxvx vs23,r5,r3
26 addi r5,r5,16
27 lxvx vs24,r5,r3
28 addi r5,r5,16
29 lxvx vs25,r5,r3
30 addi r5,r5,16
31 lxvx vs26,r5,r3
32 addi r5,r5,16
33 lxvx vs27,r5,r3
34 addi r5,r5,16
35 lxvx vs28,r5,r3
36 addi r5,r5,16
37 lxvx vs29,r5,r3
38 addi r5,r5,16
39 lxvx vs30,r5,r3
40 addi r5,r5,16
41 lxvx vs31,r5,r3
42 blr
43FUNC_END(load_vsx)
44
45FUNC_START(store_vsx)
46 li r5,0
47 stxvx vs20,r5,r3
48 addi r5,r5,16
49 stxvx vs21,r5,r3
50 addi r5,r5,16
51 stxvx vs22,r5,r3
52 addi r5,r5,16
53 stxvx vs23,r5,r3
54 addi r5,r5,16
55 stxvx vs24,r5,r3
56 addi r5,r5,16
57 stxvx vs25,r5,r3
58 addi r5,r5,16
59 stxvx vs26,r5,r3
60 addi r5,r5,16
61 stxvx vs27,r5,r3
62 addi r5,r5,16
63 stxvx vs28,r5,r3
64 addi r5,r5,16
65 stxvx vs29,r5,r3
66 addi r5,r5,16
67 stxvx vs30,r5,r3
68 addi r5,r5,16
69 stxvx vs31,r5,r3
70 blr
71FUNC_END(store_vsx)