master
c 67 lines 1.81 KB
Raw
1 /*
2 * Test that PERFORM RANDOM NUMBER OPERATION TRNG is interruptible.
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 #include <assert.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <asm/ucontext.h>
13
14 static unsigned char buf1[16 * 1024 * 1024];
15 static unsigned char buf2[16 * 1024 * 1024];
16
17 static volatile sig_atomic_t interrupted;
18
19 static void sigprof_handler(int sig, siginfo_t *info, void *ucontext)
20 {
21 struct ucontext *uc = ucontext;
22 unsigned long addr = uc->uc_mcontext.regs.psw.addr;
23
24 if (*(unsigned short *)(addr - 4) == 0xb93c) {
25 interrupted++;
26 }
27 }
28
29 static void prno_trng(void *b1, unsigned long l1, void *b2, unsigned long l2)
30 {
31 register unsigned long r0 asm("r0") = 114; /* TRNG */
32 register unsigned long r2 asm("r2") = (unsigned long)b1;
33 register unsigned long r3 asm("r3") = l1;
34 register unsigned long r4 asm("r4") = (unsigned long)b2;
35 register unsigned long r5 asm("r5") = l2;
36
37 asm volatile("0: ppno %[r2],%[r4]\n" /* prno alias for old toolchains */
38 " jo 0b"
39 : [r2] "+r" (r2), [r3] "+r" (r3)
40 , [r4] "+r" (r4), [r5] "+r" (r5)
41 : "r" (r0)
42 : "cc", "memory");
43 }
44
45 int main(void)
46 {
47 struct itimerval it = {
48 .it_interval = { .tv_usec = 10000 }, /* 0.01s */
49 .it_value = { .tv_usec = 10000 },
50 };
51 struct sigaction act = {
52 .sa_sigaction = sigprof_handler,
53 .sa_flags = SA_SIGINFO,
54 };
55 int err;
56
57 err = sigaction(SIGPROF, &act, NULL);
58 assert(err == 0);
59 err = setitimer(ITIMER_PROF, &it, NULL);
60 assert(err == 0);
61
62 prno_trng(buf1, sizeof(buf1), buf2, sizeof(buf2));
63 printf("interrupted %d times\n", interrupted);
64 assert(interrupted >= 3);
65
66 return EXIT_SUCCESS;
67 }