[llvm] [llvm-exegesis][AArch64] Check for PAC keys before disabling them (PR #138643)

Anatoly Trosinenko via llvm-commits llvm-commits at lists.llvm.org
Wed May 7 13:05:56 PDT 2025


https://github.com/atrosinenko requested changes to this pull request.

If my understanding is correct, the problem is that llvm-exegesis may fail with an error like "AUTIA: Failed to disable PAC keys", depending on the CPU features. It looks like I have managed to reproduce this issue in QEMU (in full-system emulation mode), the results are below.

As far as I see, PAuth-related `prctl`s are not documented in man pages well, but thankfully the kernel sources are quite readable on themselves:
* `prctl` entry point is in [kernel/sys.c](https://github.com/torvalds/linux/blob/d76bb1ebb5587f66b0f8b8099bfbb44722bc08b3/kernel/sys.c#L2473), and [here](https://github.com/torvalds/linux/blob/d76bb1ebb5587f66b0f8b8099bfbb44722bc08b3/kernel/sys.c#L2698) are relevant operations
* the requests are ultimately processed in [arch/arm64/kernel/pointer_auth.c](https://github.com/torvalds/linux/blob/d76bb1ebb5587f66b0f8b8099bfbb44722bc08b3/arch/arm64/kernel/pointer_auth.c#L67)
* according to the Caveats section of [`man prctl`](https://man7.org/linux/man-pages/man2/prctl.2.html), as well as to [`man PR_PAC_RESET_KEYS`](https://man7.org/linux/man-pages/man2/PR_PAC_RESET_KEYS.2const.html), it is probably better to pass `prctl` arguments as `long`

Each configuration was tested by running
```bash
strace -f -e prctl \
    /path/to/llvm-project/build-aarch64/bin/llvm-exegesis \
        -mtriple=aarch64-linux-gnu \
        -mcpu=neoverse-v2 \
        -mode=latency \
        --opcode-name=AUTIA \
        --use-dummy-perf-counters
```

On the main branch (commit cd6c4b61034850fffcb221a449a8ee1fdd8ada8a), with emulated CPU set to `neoverse-v1,pauth-impdef=on` (Neoverse-V2 is not supported in QEMU 9.2.1, but Neoverse-V1 seems to be enough to reproduce the issue. Similarly, `pauth-impdef=on` should not affect the issue, but makes emulation faster) I got
```
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = 0
---
mode:            latency
key:
  instructions:
    - 'AUTIA X23 X23 X15'
  config:          ''
  register_initial_values:
    - 'X23=0x0'
    - 'X15=0x0'
cpu_name:        neoverse-v2
llvm_triple:     aarch64-unknown-linux-gnu
min_instructions: 10000
measurements:    []
error:           ''
info:            Repeating a single implicitly serial instruction
assembled_snippet: F70F1FF8170080D20F0080D2F711C1DAF711C1DAF711C1DAF711C1DAF70741F8C0035FD6
...
+++ exited with 0 +++
```
and setting CPU to `cortex-a72` gives this output:
```
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to disable PAC keys
+++ exited with 0 +++
```
(by the way, return code is 0, which is a bit surprising...). This is probably because of `if (!system_supports_address_auth()) return -EINVAL;` check in the kernel, assuming  `system_supports_address_auth()` means "FEAT_PAUTH was detected at run-time" (instead of "the kernel was compiled with PAuth support" or something like this).

This PR (commit 2a9af0f62741e43dd3d6f760a47c0a60833a04bd) produces an error like the following with both CPU models:
```
prctl(PR_PAC_GET_ENABLED_KEYS, 0x7ff2234598, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to get PAC key status
+++ exited with 0 +++
```
Turned out, all arguments should be set to 0 and the bitmask is returned as the return value of `prctl`.

I applied a quick fix:
```diff
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 7e6382693c3e..3d59955177cb 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -213,8 +213,8 @@ private:
       // For systems without PAC, this is a No-op but with PAC, it is
       // safer to check the existing key state and then disable/enable them.
       // Hence the guard for switching.
-      unsigned long PacKeys = 0;
-      if (prctl(PR_PAC_GET_ENABLED_KEYS, &PacKeys, 0, 0, 0) < 0) {
+      unsigned long PacKeys = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0);
+      if ((long)PacKeys < 0) {
         return "Failed to get PAC key status";
       }
 
```
With CPU set to `neoverse-v1,pauth-impdef=on` the following output is produced:
```

prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0) = 0xf (PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY)
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = 0
---
mode:            latency
key:
  instructions:
    - 'AUTIA X23 X23 X0'
  config:          ''
  register_initial_values:
    - 'X23=0x0'
    - 'X0=0x0'
cpu_name:        neoverse-v2
llvm_triple:     aarch64-unknown-linux-gnu
min_instructions: 10000
measurements:    []
error:           ''
info:            Repeating a single implicitly serial instruction
assembled_snippet: F70F1FF8170080D2000080D21710C1DA1710C1DA1710C1DA1710C1DAF70741F8C0035FD6
...
+++ exited with 0 +++
```
but with `cortex-a72` it fails with:
```
prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to get PAC key status
+++ exited with 0 +++
```

Probably, `EINVAL` is always returned when FEAT_PAUTH is not supported by the CPU.

https://github.com/llvm/llvm-project/pull/138643


More information about the llvm-commits mailing list