xref: /openbmc/qemu/tests/tcg/aarch64/pauth-4.c (revision a7e8e30e7ca071c8fbf8920a7a4ee9976a0e7544)
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