1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2024 ARM Limited.
17 #include <sys/socket.h>
19 #include <linux/kernel.h>
20 #include <linux/if_alg.h>
22 #define DATA_SIZE (16 * 4096)
24 static int base
, sock
;
26 static int digest_len
;
29 static char *alg_name
;
31 static struct iovec data_iov
;
32 static int zerocopy
[2];
36 static void handle_exit_signal(int sig
, siginfo_t
*info
, void *context
)
38 printf("Terminated by signal %d, iterations=%d, signals=%d\n",
43 static void handle_kick_signal(int sig
, siginfo_t
*info
, void *context
)
48 static char *drivers
[] = {
50 /* "crct10dif-arm64-neon", - Same priority as generic */
68 static bool create_socket(void)
71 struct sockaddr_alg addr
;
73 char *c
, *driver_name
;
77 ret
= socket(AF_ALG
, SOCK_SEQPACKET
, 0);
79 if (errno
== EAFNOSUPPORT
) {
80 printf("AF_ALG not supported\n");
84 printf("Failed to create AF_ALG socket: %s (%d)\n",
85 strerror(errno
), errno
);
90 memset(&addr
, 0, sizeof(addr
));
91 addr
.salg_family
= AF_ALG
;
92 strncpy((char *)addr
.salg_type
, "hash", sizeof(addr
.salg_type
));
94 proc
= fopen("/proc/crypto", "r");
96 printf("Unable to open /proc/crypto\n");
104 /* Look through /proc/crypto for a driver with kernel mode FP usage */
106 c
= fgets(buf
, sizeof(buf
), proc
);
109 printf("Nothing found in /proc/crypto\n");
115 /* Algorithm descriptions are separated by a blank line */
117 if (is_shash
&& driver_name
) {
118 for (i
= 0; i
< ARRAY_SIZE(drivers
); i
++) {
119 if (strcmp(drivers
[i
],
140 /* Remove trailing newline */
141 c
= strchr(buf
, '\n');
145 /* Find the field/value separator and start of the value */
146 c
= strchr(buf
, ':');
151 if (strncmp(buf
, "digestsize", strlen("digestsize")) == 0)
152 sscanf(c
, "%d", &digest_len
);
154 if (strncmp(buf
, "name", strlen("name")) == 0)
155 alg_name
= strdup(c
);
157 if (strncmp(buf
, "driver", strlen("driver")) == 0)
158 driver_name
= strdup(c
);
160 if (strncmp(buf
, "type", strlen("type")) == 0)
161 if (strncmp(c
, "shash", strlen("shash")) == 0)
165 strncpy((char *)addr
.salg_name
, alg_name
,
166 sizeof(addr
.salg_name
) - 1);
168 ret
= bind(base
, (struct sockaddr
*)&addr
, sizeof(addr
));
170 printf("Failed to bind %s: %s (%d)\n",
171 addr
.salg_name
, strerror(errno
), errno
);
175 ret
= accept(base
, NULL
, 0);
177 printf("Failed to accept %s: %s (%d)\n",
178 addr
.salg_name
, strerror(errno
), errno
);
184 ret
= pipe(zerocopy
);
186 printf("Failed to create zerocopy pipe: %s (%d)\n",
187 strerror(errno
), errno
);
191 ref
= malloc(digest_len
);
193 printf("Failed to allocated %d byte reference\n", digest_len
);
197 digest
= malloc(digest_len
);
199 printf("Failed to allocated %d byte digest\n", digest_len
);
206 static bool compute_digest(void *buf
)
212 while (iov
.iov_len
) {
213 ret
= vmsplice(zerocopy
[1], &iov
, 1, SPLICE_F_GIFT
);
215 printf("Failed to send buffer: %s (%d)\n",
216 strerror(errno
), errno
);
221 ret
= splice(zerocopy
[0], NULL
, sock
, NULL
, wrote
, 0);
223 printf("Failed to splice buffer: %s (%d)\n",
224 strerror(errno
), errno
);
225 } else if (ret
!= wrote
) {
226 printf("Short splice: %d < %d\n", ret
, wrote
);
229 iov
.iov_len
-= wrote
;
230 iov
.iov_base
+= wrote
;
234 ret
= recv(sock
, buf
, digest_len
, 0);
236 printf("No digest returned\n");
239 if (ret
!= digest_len
) {
240 if (errno
== -EAGAIN
)
242 printf("Failed to get digest: %s (%d)\n",
243 strerror(errno
), errno
);
256 /* Ensure we have unbuffered output */
257 setvbuf(stdout
, NULL
, _IOLBF
, 0);
259 /* The parent will communicate with us via signals */
260 memset(&sa
, 0, sizeof(sa
));
261 sa
.sa_sigaction
= handle_exit_signal
;
262 sa
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
263 sigemptyset(&sa
.sa_mask
);
264 ret
= sigaction(SIGTERM
, &sa
, NULL
);
266 printf("Failed to install SIGTERM handler: %s (%d)\n",
267 strerror(errno
), errno
);
269 sa
.sa_sigaction
= handle_kick_signal
;
270 ret
= sigaction(SIGUSR1
, &sa
, NULL
);
272 printf("Failed to install SIGUSR1 handler: %s (%d)\n",
273 strerror(errno
), errno
);
274 ret
= sigaction(SIGUSR2
, &sa
, NULL
);
276 printf("Failed to install SIGUSR2 handler: %s (%d)\n",
277 strerror(errno
), errno
);
279 data
= malloc(DATA_SIZE
);
281 printf("Failed to allocate data buffer\n");
284 memset(data
, 0, DATA_SIZE
);
286 data_iov
.iov_base
= data
;
287 data_iov
.iov_len
= DATA_SIZE
;
290 * If we can't create a socket assume it's a lack of system
291 * support and fall back to a basic FPSIMD test for the
292 * benefit of fp-stress.
294 if (!create_socket()) {
295 execl("./fpsimd-test", "./fpsimd-test", NULL
);
296 printf("Failed to fall back to fspimd-test: %d (%s)\n",
297 errno
, strerror(errno
));
302 * Compute a reference digest we hope is repeatable, we do
303 * this at runtime partly to make it easier to play with
306 if (!compute_digest(ref
)) {
307 printf("Failed to compute reference digest\n");
311 printf("AF_ALG using %s\n", alg_name
);
314 if (!compute_digest(digest
)) {
315 printf("Failed to compute digest, iter=%d\n", iter
);
319 if (memcmp(ref
, digest
, digest_len
) != 0) {
320 printf("Digest mismatch, iter=%d\n", iter
);