1dd684eadSRichard Henderson #include <stdint.h>
2dd684eadSRichard Henderson #include <assert.h>
3bc97f9f6SAlex Bennée #include <stdio.h>
4bc97f9f6SAlex Bennée #include <stdlib.h>
5*871a7f6aSRichard Henderson #include "pauth.h"
6bc97f9f6SAlex Bennée
7bc97f9f6SAlex Bennée #define TESTS 1000
8dd684eadSRichard Henderson
main()9dd684eadSRichard Henderson int main()
10dd684eadSRichard Henderson {
11*871a7f6aSRichard Henderson char base[TESTS];
12bc97f9f6SAlex Bennée int i, count = 0;
13bc97f9f6SAlex Bennée float perc;
14*871a7f6aSRichard Henderson int pac_feature = get_pac_feature();
15*871a7f6aSRichard Henderson
16*871a7f6aSRichard Henderson /*
17*871a7f6aSRichard Henderson * Exit if no PAuth or FEAT_FPAC, which will SIGILL on AUTIA failure
18*871a7f6aSRichard Henderson * rather than return an error for us to check below.
19*871a7f6aSRichard Henderson */
20*871a7f6aSRichard Henderson if (pac_feature == 0 || pac_feature >= 4) {
21*871a7f6aSRichard Henderson return 0;
22*871a7f6aSRichard Henderson }
23dd684eadSRichard Henderson
24bc97f9f6SAlex Bennée for (i = 0; i < TESTS; i++) {
25bc97f9f6SAlex Bennée uintptr_t in, x, y;
26bc97f9f6SAlex Bennée
27bc97f9f6SAlex Bennée in = i + (uintptr_t) base;
28bc97f9f6SAlex Bennée
29bc97f9f6SAlex Bennée asm("mov %0, %[in]\n\t"
30*871a7f6aSRichard Henderson "pacia %0, sp\n\t"
31dd684eadSRichard Henderson "eor %0, %0, #4\n\t" /* corrupt single bit */
32dd684eadSRichard Henderson "mov %1, %0\n\t"
33dd684eadSRichard Henderson "autia %1, sp\n\t" /* validate corrupted pointer */
34dd684eadSRichard Henderson "xpaci %0\n\t" /* strip pac from corrupted pointer */
35bc97f9f6SAlex Bennée : /* out */ "=r"(x), "=r"(y)
36bc97f9f6SAlex Bennée : /* in */ [in] "r" (in)
37bc97f9f6SAlex Bennée : /* clobbers */);
38dd684eadSRichard Henderson
39dd684eadSRichard Henderson /*
40dd684eadSRichard Henderson * Once stripped, the corrupted pointer is of the form 0x0000...wxyz.
41dd684eadSRichard Henderson * We expect the autia to indicate failure, producing a pointer of the
42dd684eadSRichard Henderson * form 0x000e....wxyz. Use xpaci and != for the test, rather than
43dd684eadSRichard Henderson * extracting explicit bits from the top, because the location of the
44dd684eadSRichard Henderson * error code "e" depends on the configuration of virtual memory.
45dd684eadSRichard Henderson */
46bc97f9f6SAlex Bennée if (x != y) {
47bc97f9f6SAlex Bennée count++;
48bc97f9f6SAlex Bennée }
49bc97f9f6SAlex Bennée }
50*871a7f6aSRichard Henderson
51bc97f9f6SAlex Bennée perc = (float) count / (float) TESTS;
52*871a7f6aSRichard Henderson printf("Checks Passed: %0.2f%%\n", perc * 100.0);
53bc97f9f6SAlex Bennée assert(perc > 0.95);
54dd684eadSRichard Henderson return 0;
55dd684eadSRichard Henderson }
56