1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2015, Cyril Bur, IBM Corp.
5 * This test attempts to see if the VMX registers are correctly reported in a
6 * signal context. Each worker just spins checking its VMX registers, at some
7 * point a signal will interrupt it and C code will check the signal context
8 * ensuring it is also the same.
13 #include <sys/syscall.h>
15 #include <sys/types.h>
24 /* Number of times each thread should receive the signal */
27 * Factor by which to multiply number of online CPUs for total number of
30 #define THREAD_FACTOR 8
32 __thread vector
int varray
[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
33 {13,14,15,16},{17,18,19,20},{21,22,23,24},
34 {25,26,27,28},{29,30,31,32},{33,34,35,36},
35 {37,38,39,40},{41,42,43,44},{45,46,47,48}};
41 extern int preempt_vmx(vector
int *varray
, int *threads_starting
, int *sentinal
);
43 void signal_vmx_sig(int sig
, siginfo_t
*info
, void *context
)
46 ucontext_t
*uc
= context
;
47 mcontext_t
*mc
= &uc
->uc_mcontext
;
49 /* Only the non volatiles were loaded up */
50 for (i
= 20; i
< 32; i
++) {
51 if (memcmp(mc
->v_regs
->vrregs
[i
], &varray
[i
- 20], 16)) {
54 * Shouldn't printf() in a signal handler, however, this is a
55 * test and we've detected failure. Understanding what failed
56 * is paramount. All that happens after this is tests exit with
59 printf("VMX mismatch at reg %d!\n", i
);
60 printf("Reg | Actual | Expected\n");
61 for (j
= 20; j
< 32; j
++) {
62 printf("%d | 0x%04x%04x%04x%04x | 0x%04x%04x%04x%04x\n", j
, mc
->v_regs
->vrregs
[j
][0],
63 mc
->v_regs
->vrregs
[j
][1], mc
->v_regs
->vrregs
[j
][2], mc
->v_regs
->vrregs
[j
][3],
64 varray
[j
- 20][0], varray
[j
- 20][1], varray
[j
- 20][2], varray
[j
- 20][3]);
72 void *signal_vmx_c(void *p
)
77 act
.sa_sigaction
= signal_vmx_sig
;
78 act
.sa_flags
= SA_SIGINFO
;
79 rc
= sigaction(SIGUSR1
, &act
, NULL
);
83 srand(pthread_self());
84 for (i
= 0; i
< 12; i
++)
85 for (j
= 0; j
< 4; j
++)
86 varray
[i
][j
] = rand();
88 rc
= preempt_vmx(varray
, &threads_starting
, &running
);
93 int test_signal_vmx(void)
95 int i
, j
, rc
, threads
;
99 // vcmpequd used in vmx_asm.S is v2.07
100 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07
));
102 threads
= sysconf(_SC_NPROCESSORS_ONLN
) * THREAD_FACTOR
;
103 tids
= malloc(threads
* sizeof(pthread_t
));
107 threads_starting
= threads
;
108 for (i
= 0; i
< threads
; i
++) {
109 rc
= pthread_create(&tids
[i
], NULL
, signal_vmx_c
, NULL
);
113 setbuf(stdout
, NULL
);
114 printf("\tWaiting for %d workers to start... %d", threads
, threads_starting
);
115 while (threads_starting
) {
116 asm volatile("": : :"memory");
118 printf(", %d", threads_starting
);
120 printf(" ...done\n");
122 printf("\tSending signals to all threads %d times...", ITERATIONS
);
123 for (i
= 0; i
< ITERATIONS
; i
++) {
124 for (j
= 0; j
< threads
; j
++) {
125 pthread_kill(tids
[j
], SIGUSR1
);
131 printf("\tKilling workers...");
133 for (i
= 0; i
< threads
; i
++) {
134 pthread_join(tids
[i
], &rc_p
);
137 * Harness will say the fail was here, look at why signal_vmx
140 if ((long) rc_p
|| bad_context
)
143 fprintf(stderr
, "\t!! bad_context is true\n");
144 FAIL_IF((long) rc_p
|| bad_context
);
152 int main(int argc
, char *argv
[])
154 return test_harness(test_signal_vmx
, "vmx_signal");