RFR: 8287325: AArch64: fix virtual threads with -XX:UseBranchProtection=pac-ret [v12]
Hao Sun
haosun at openjdk.org
Mon Sep 25 01:11:48 UTC 2023
> ### Background
>
> 1. PAC-RET branch protection was initially implemented on Linux/AArch64 in JDK-8277204 [1].
>
> 2. However, it was broken with the introduction of virtual threads [2], mainly because the continuation freeze/thaw mechanism would trigger stack copying to/from memory, whereas the saved and signed LR on the stack doesn't get re-signed accordingly.
>
> 3. PR-9067 [3] tried to implement the re-sign part, but it was not accepted because option "PreserveFramePointer" is always turned on by PAC-RET but this would slow down virtual threads by ~5-20x.
>
> 4. As a workaround, JDK-8288023 [4] disables PAC-RET when preview language features are enabled. Note that virtual thread is one preview feature then.
>
> 5. Virtual thread will become a permanent feature in JDK-21 [5][6].
>
> ### Goal
>
> This patch aims to make PAC-RET compatible with virtual threads.
>
> ### Requirements of virtual threads
>
> R-1: Option "PreserveFramePointer" should be turned off. That is, PAC-RET implementation should not rely on frame pointer FP. Otherwise, the fast path in stack copying will never be taken.
>
> R-2: Use some invariant values to stack copying as the modifier, so as to avoid the PAC re-sign for continuation thaw, as the fast path in stack copying doesn't walk the frame.
>
> Note that more details can be found in the discussion [3].
>
> ### Investigation
>
> We considered to use (relative) stack pointer SP, thread ID, PACStack [7] and value zero as the candidate modifier.
>
> 1. SP: In some scenarios, we need to authenticate the return address in places where the current SP doesn't match the SP on function entry. E.g. see the usage in Runtime1::generate_handle_exception(). Hence, neither absolute nor relative SP works.
>
> 2. thread ID (tid): It's invariant to virtual thread, but it's nontrivial to access it from the JIT side. We need 1) firstly resolve the address of current thread (See [8] as an example), and 2) get the tid field in the way like java_lang_Thread::thread_id(). I suppose this would introduce big performance overhead. Then can we turn to use "rthread" register (JavaThread object address) as the modifier? Unfortunately, it's not an invariant to virtual threads and PAC re-sign is still needed.
>
> 5. PACStack uses the signed return address of caller as the modifier to sign the callee's return address. In this way, we get one PACed call chain. The modifier should be saved into somewhere around the frame record. Inevitably, FP should be preserved to make it easy to find this modifier in case of...
Hao Sun has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 17 commits:
- Merge branch 'master' into jdk-8287325
- Not use pacia1716 and reuse retaddr_slot
- Merge branch 'master' into jdk-8287325
- break long lines
- Refactor long assertions in continuationFreezeThaw.cpp
- Introduce CPU_OVERRIDES_RETURN_ADDRESS_ACCESSORS
- Merge branch 'master' into jdk-8287325
- Revert to the implementation with zero as the PAC modifier
- Merge branch 'master' into jdk-8287325
- Update aarch64.ad and jvmci AArch64TestAssembler.java
Before this patch, rscratch1 is clobbered.
With this patch, we use the rscratch1 register after we save it on the
stack.
In this way, the code would be consistent with
macroAssembler_aarch64.cpp.
- ... and 7 more: https://git.openjdk.org/jdk/compare/a2391a92...8bd62e5a
-------------
Changes: https://git.openjdk.org/jdk/pull/13322/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=13322&range=11
Stats: 236 lines in 23 files changed: 94 ins; 32 del; 110 mod
Patch: https://git.openjdk.org/jdk/pull/13322.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/13322/head:pull/13322
PR: https://git.openjdk.org/jdk/pull/13322
More information about the hotspot-dev
mailing list