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).

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
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.

3 participants