diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 23:19:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 23:19:31 -0400 |
commit | 07021b43597f506cc525d139ed1a94e79cf184f2 (patch) | |
tree | 888ab33ec69b397ae6f8a2c82d14197047ee827e /tools | |
parent | d1f5323370fceaed43a7ee38f4c7bfc7e70f28d0 (diff) | |
parent | b7b7013cac55d794940bd9cb7b7c55c9dececac4 (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')
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 | */ | ||
58 | FUNC_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 | ||
78 | FUNC_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 | */ | ||
73 | FUNC_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 | ||
93 | FUNC_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 | ||
24 | static uint64_t timeout = 120; | ||
25 | 25 | ||
26 | int run_test(int (test_function)(void), char *name) | 26 | int 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 | ||
50 | wait: | 50 | wait: |
@@ -94,6 +94,11 @@ static struct sigaction alarm_action = { | |||
94 | .sa_handler = alarm_handler, | 94 | .sa_handler = alarm_handler, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | void test_harness_set_timeout(uint64_t time) | ||
98 | { | ||
99 | timeout = time; | ||
100 | } | ||
101 | |||
97 | int test_harness(int (test_function)(void), char *name) | 102 | int 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 @@ | |||
1 | TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal | 1 | TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt |
2 | 2 | ||
3 | all: $(TEST_PROGS) | 3 | all: $(TEST_PROGS) |
4 | 4 | ||
@@ -13,6 +13,9 @@ vmx_syscall: vmx_asm.S | |||
13 | vmx_preempt: vmx_asm.S | 13 | vmx_preempt: vmx_asm.S |
14 | vmx_signal: vmx_asm.S | 14 | vmx_signal: vmx_asm.S |
15 | 15 | ||
16 | vsx_preempt: CFLAGS += -mvsx | ||
17 | vsx_preempt: vsx_asm.S | ||
18 | |||
16 | include ../../lib.mk | 19 | include ../../lib.mk |
17 | 20 | ||
18 | clean: | 21 | clean: |
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 | ||
54 | FUNC_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 | ||
74 | FUNC_END(load_fpu) | ||
75 | 12 | ||
76 | FUNC_START(check_fpu) | 13 | FUNC_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 |
161 | FUNC_END(test_fpu) | 98 | FUNC_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. |
167 | FUNC_START(preempt_fpu) | 104 | FUNC_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 | ||
195 | 3: POP_FPU(STACK_FRAME_LOCAL(3,0)) | 132 | 3: POP_FPU(256) |
196 | POP_BASIC_STACK(256) | 133 | POP_BASIC_STACK(256) |
197 | blr | 134 | blr |
198 | FUNC_END(preempt_fpu) | 135 | FUNC_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 | ||
68 | FUNC_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 | ||
94 | FUNC_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 |
97 | FUNC_START(check_vmx) | 14 | FUNC_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() | ||
16 | FUNC_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 | ||
25 | FUNC_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. | ||
32 | FUNC_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) | ||
44 | 1: lwarx r4,0,r3 | ||
45 | addi r4,r4,-1 | ||
46 | stwcx. r4,0,r3 | ||
47 | bne- 1b | ||
48 | |||
49 | 2: 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 | |||
59 | 3: POP_BASIC_STACK(512) | ||
60 | blr | ||
61 | FUNC_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 | |||
47 | int threads_starting; | ||
48 | int running; | ||
49 | |||
50 | extern long preempt_vsx(vector int *varray, int *threads_starting, int *running); | ||
51 | |||
52 | long 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 | |||
76 | void *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 | |||
94 | int 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 | |||
144 | int 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 @@ | |||
1 | TEST_PROGS := signal signal_tm | ||
2 | |||
3 | all: $(TEST_PROGS) | ||
4 | |||
5 | $(TEST_PROGS): ../harness.c ../utils.c signal.S | ||
6 | |||
7 | CFLAGS += -maltivec | ||
8 | signal_tm: CFLAGS += -mhtm | ||
9 | |||
10 | include ../../lib.mk | ||
11 | |||
12 | clean: | ||
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); */ | ||
13 | FUNC_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 | ||
20 | 1: blr | ||
21 | FUNC_END(signal_self) | ||
22 | |||
23 | /* long tm_signal_self(pid_t pid, int sig, int *ret); */ | ||
24 | FUNC_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 | ||
37 | 2: 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 | ||
47 | 1: li r3,0 | ||
48 | POP_BASIC_STACK(8) | ||
49 | blr | ||
50 | FUNC_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 | |||
27 | extern long signal_self(pid_t pid, int sig); | ||
28 | |||
29 | static sig_atomic_t signaled; | ||
30 | static sig_atomic_t fail; | ||
31 | |||
32 | static void signal_handler(int sig) | ||
33 | { | ||
34 | if (sig == SIGUSR1) | ||
35 | signaled = 1; | ||
36 | else | ||
37 | fail = 1; | ||
38 | } | ||
39 | |||
40 | static 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 | |||
107 | int 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 | |||
27 | extern long tm_signal_self(pid_t pid, int sig, long *ret); | ||
28 | |||
29 | static sig_atomic_t signaled; | ||
30 | static sig_atomic_t fail; | ||
31 | |||
32 | static 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 | |||
45 | static 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 | |||
107 | int 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 @@ | |||
1 | SIGNAL_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 | |||
1 | TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ | 4 | TEST_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 | ||
4 | all: $(TEST_PROGS) | 7 | all: $(TEST_PROGS) |
5 | 8 | ||
@@ -11,6 +14,9 @@ tm-syscall: tm-syscall-asm.S | |||
11 | tm-syscall: CFLAGS += -I../../../../../usr/include | 14 | tm-syscall: CFLAGS += -I../../../../../usr/include |
12 | tm-tmspr: CFLAGS += -pthread | 15 | tm-tmspr: CFLAGS += -pthread |
13 | 16 | ||
17 | $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S | ||
18 | $(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx | ||
19 | |||
14 | include ../../lib.mk | 20 | include ../../lib.mk |
15 | 21 | ||
16 | clean: | 22 | clean: |
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 | |||
38 | long 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) */ | ||
41 | static 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 | |||
46 | static sig_atomic_t fail; | ||
47 | |||
48 | static 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 | |||
62 | static 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 | |||
89 | int 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 | |||
38 | long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); | ||
39 | |||
40 | static sig_atomic_t fail; | ||
41 | |||
42 | static 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 | |||
45 | static 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 | |||
60 | static 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 | |||
87 | int 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 | |||
39 | long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); | ||
40 | |||
41 | static sig_atomic_t fail; | ||
42 | |||
43 | vector 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 | |||
54 | static 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 | |||
80 | static 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 | |||
107 | int 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 | |||
39 | long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); | ||
40 | |||
41 | static sig_atomic_t fail; | ||
42 | |||
43 | vector 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 | |||
54 | static 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 | |||
95 | static 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 | |||
122 | int 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); */ | ||
24 | FUNC_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 | ||
43 | skip_gpr_lc: | ||
44 | ld r3, STACK_FRAME_PARAM(2)(sp) | ||
45 | cmpdi r3, 0 | ||
46 | beq skip_fpu_lc | ||
47 | bl load_fpu | ||
48 | skip_fpu_lc: | ||
49 | ld r3, STACK_FRAME_PARAM(3)(sp) | ||
50 | cmpdi r3, 0 | ||
51 | beq skip_vmx_lc | ||
52 | bl load_vmx | ||
53 | skip_vmx_lc: | ||
54 | ld r3, STACK_FRAME_PARAM(4)(sp) | ||
55 | cmpdi r3, 0 | ||
56 | beq skip_vsx_lc | ||
57 | bl load_vsx | ||
58 | skip_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 | ||
74 | skip_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 | ||
81 | skip_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 | ||
88 | skip_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 | ||
95 | skip_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 | ||
114 | FUNC_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 | ||
55 | static inline int tcheck(void) | ||
56 | { | ||
57 | long cr; | ||
58 | asm volatile ("tcheck 0" : "=r"(cr) : : "cr0"); | ||
59 | return (cr >> 28) & 4; | ||
60 | } | ||
61 | |||
62 | static inline bool tcheck_doomed(void) | ||
63 | { | ||
64 | return tcheck() & 8; | ||
65 | } | ||
66 | |||
67 | static inline bool tcheck_active(void) | ||
68 | { | ||
69 | return tcheck() & 4; | ||
70 | } | ||
71 | |||
72 | static inline bool tcheck_suspended(void) | ||
73 | { | ||
74 | return tcheck() & 2; | ||
75 | } | ||
76 | |||
77 | static 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; | |||
22 | typedef uint16_t u16; | 22 | typedef uint16_t u16; |
23 | typedef uint8_t u8; | 23 | typedef uint8_t u8; |
24 | 24 | ||
25 | 25 | void test_harness_set_timeout(uint64_t time); | |
26 | int test_harness(int (test_function)(void), char *name); | 26 | int test_harness(int (test_function)(void), char *name); |
27 | extern void *get_auxv_entry(int type); | 27 | extern void *get_auxv_entry(int type); |
28 | int pick_online_cpu(void); | 28 | int 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 | ||
35 | static inline bool have_hwcap2(unsigned long ftr2) | 36 | static 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 | ||
41 | static 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 | */ | ||
70 | FUNC_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 | ||
96 | FUNC_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 | */ | ||
17 | FUNC_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 | ||
43 | FUNC_END(load_vsx) | ||
44 | |||
45 | FUNC_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 | ||
71 | FUNC_END(store_vsx) | ||