1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2015, Michael Neuling, IBM Corp. |
4 | * |
5 | * Original: Michael Neuling 4/12/2013 |
6 | * Edited: Rashmica Gupta 4/12/2015 |
7 | * |
8 | * See if the altivec state is leaked out of an aborted transaction due to |
9 | * kernel vmx copy loops. |
10 | * |
11 | * When the transaction aborts, VSR values should rollback to the values |
12 | * they held before the transaction commenced. Using VSRs while transaction |
13 | * is suspended should not affect the checkpointed values. |
14 | * |
15 | * (1) write A to a VSR |
16 | * (2) start transaction |
17 | * (3) suspend transaction |
18 | * (4) change the VSR to B |
19 | * (5) trigger kernel vmx copy loop |
20 | * (6) abort transaction |
21 | * (7) check that the VSR value is A |
22 | */ |
23 | |
24 | #include <inttypes.h> |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <unistd.h> |
28 | #include <sys/mman.h> |
29 | #include <string.h> |
30 | #include <assert.h> |
31 | |
32 | #include "tm.h" |
33 | #include "utils.h" |
34 | |
35 | int test_vmxcopy() |
36 | { |
37 | long double vecin = 1.3; |
38 | long double vecout; |
39 | unsigned long pgsize = getpagesize(); |
40 | int i; |
41 | int fd; |
42 | int size = pgsize*16; |
43 | char tmpfile[] = "/tmp/page_faultXXXXXX" ; |
44 | char buf[pgsize]; |
45 | char *a; |
46 | uint64_t aborted = 0; |
47 | |
48 | SKIP_IF(!have_htm()); |
49 | SKIP_IF(htm_is_synthetic()); |
50 | SKIP_IF(!is_ppc64le()); |
51 | |
52 | fd = mkstemp(tmpfile); |
53 | assert(fd >= 0); |
54 | |
55 | memset(buf, 0, pgsize); |
56 | for (i = 0; i < size; i += pgsize) |
57 | assert(write(fd, buf, pgsize) == pgsize); |
58 | |
59 | unlink(tmpfile); |
60 | |
61 | a = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); |
62 | assert(a != MAP_FAILED); |
63 | |
64 | asm __volatile__( |
65 | "lxvd2x 40,0,%[vecinptr];" /* set 40 to initial value*/ |
66 | "tbegin.;" |
67 | "beq 3f;" |
68 | "tsuspend.;" |
69 | "xxlxor 40,40,40;" /* set 40 to 0 */ |
70 | "std 5, 0(%[map]);" /* cause kernel vmx copy page */ |
71 | "tabort. 0;" |
72 | "tresume.;" |
73 | "tend.;" |
74 | "li %[res], 0;" |
75 | "b 5f;" |
76 | |
77 | /* Abort handler */ |
78 | "3:;" |
79 | "li %[res], 1;" |
80 | |
81 | "5:;" |
82 | "stxvd2x 40,0,%[vecoutptr];" |
83 | : [res]"=&r" (aborted) |
84 | : [vecinptr]"r" (&vecin), |
85 | [vecoutptr]"r" (&vecout), |
86 | [map]"r" (a) |
87 | : "memory" , "r0" , "r3" , "r4" , "r5" , "r6" , "r7" ); |
88 | |
89 | if (aborted && (vecin != vecout)){ |
90 | printf("FAILED: vector state leaked on abort %f != %f\n" , |
91 | (double)vecin, (double)vecout); |
92 | return 1; |
93 | } |
94 | |
95 | munmap(a, size); |
96 | |
97 | close(fd); |
98 | |
99 | return 0; |
100 | } |
101 | |
102 | int main(void) |
103 | { |
104 | return test_harness(test_vmxcopy, "tm_vmxcopy" ); |
105 | } |
106 | |