Skip to content

Conversation

@MacDue
Copy link
Member

@MacDue MacDue commented Sep 26, 2025

This is done by defining __arm_za_disable as a weak symbol with the assumption that if libunwind is being linked against SME-aware code, the ABI routines will be provided (by libgcc or compiler-rt).

@MacDue MacDue requested a review from a team as a code owner September 26, 2025 15:23
@llvmbot
Copy link
Member

llvmbot commented Sep 26, 2025

@llvm/pr-subscribers-libunwind

Author: Benjamin Maxwell (MacDue)

Changes

This is done by defining __arm_za_disable as a weak symbol with the assumption that if libunwind is being linked against SME-aware code, the ABI routines will be provided (by libgcc or compiler-rt).


Full diff: https://github.com/llvm/llvm-project/pull/160905.diff

1 Files Affected:

  • (modified) libunwind/src/UnwindLevel1.c (+27)
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index f3b451ad9b730..0a1d4be976830 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -186,6 +186,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
 }
 extern int __unw_step_stage2(unw_cursor_t *);
 
+#if defined(__aarch64__)
+extern void __attribute__((weak)) __arm_za_disable(void);
+#endif
+
 #if defined(_LIBUNWIND_USE_GCS)
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
@@ -198,6 +202,29 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
   _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
                              (void *)exception_object);
 
+#if defined(__aarch64__)
+  // The platform must ensure that all the following conditions are true on
+  // entry to EH:
+  //
+  // - PSTATE.SM is 0.
+  // - PSTATE.ZA is 0.
+  // - TPIDR2_EL0 is null.
+  //
+  // The first point is ensured by routines for throwing exceptions having a
+  // non-streaming interface. TPIDR2_EL0 is set to null and ZA disabled by
+  // calling __arm_za_disable.
+  //
+  // See:
+  // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#exceptions
+  if (__arm_za_disable) {
+    // FIXME: Is SME is available and `__arm_za_disable` is not, this should
+    // abort.
+    __arm_za_disable();
+  } else {
+    _LIBUNWIND_DEBUG_LOG("failed to call __arm_za_disable in %s", __FUNCTION__);
+  }
+#endif
+
   // uc is initialized by __unw_getcontext in the parent frame. The first stack
   // frame walked is unwind_phase2.
   unsigned framesWalked = 1;

Copy link
Collaborator

@sdesmalen-arm sdesmalen-arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it to code-owners/maintainers of libunwind to review or approve the PR further, but from an AArch64/SME point of view the change looks right to me.

@MacDue MacDue requested a review from MaskRay October 7, 2025 20:16
@MacDue
Copy link
Member Author

MacDue commented Oct 20, 2025

Kind ping @llvm/reviewers-libunwind, @MaskRay 🙂

This is done by defining ` __arm_za_disable` as a weak symbol with the
assumption that if libunwind is being linked against SME-aware code, the
ABI routines will be provided (by libgcc or compiler-rt).
@MacDue
Copy link
Member Author

MacDue commented Oct 29, 2025

Does any libunwind reviewer have an opinion on this approach? If not, we plan to land this soon. An alternative approach would be to re-implement __arm_za_disable in libunwind (tested here: #165451), but it would be nice to avoid that.

(Ping @llvm/reviewers-libunwind)

Copy link
Contributor

@ojhunt ojhunt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly a style review - I don't really know what za is?

}

void Registers_arm64::jumpto() {
#if !defined(__APPLE__)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think better would be gating on a feature specific flag - it makes it easier to understand whether something is written the way it because the feature is not supported, or because the implementation of that feature is different - in essence someone new comes along and says "there's an 'if !', does the mean it is not available, or the abi is different?"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work on macOS too (as the same routines should be present); however, I think weak symbols are handled differently there (looks like it's weak_import instead). I'm going to try that on the CI (as I don't have a Mac to hand right now).

// calling __arm_za_disable.
//
// See:
// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#exceptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should link to something more stable like their tag versions, say https://github.com/ARM-software/abi-aa/blob/2025Q1/aapcs64/aapcs64.rst#exceptions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what that'd be here? I'm aware GCC versions their symbols, but this symbol could be provided by libgcc/ibgcc_s or compiler-rt, and I'm not sure what version information is generally available.

@github-actions

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants