Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Jul 2026 11:54:35 +0000
From:      Jessica Clarke <jrtc27@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 70509d1d9cba - main - Merge commit 6b0a46958c56 from llvm-project (by Piotr Kubaj):
Message-ID:  <6a68987b.32f8e.3d475221@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by jrtc27:

URL: https://cgit.FreeBSD.org/src/commit/?id=70509d1d9cba254dfd5b3dd83d8a011b5e125788

commit 70509d1d9cba254dfd5b3dd83d8a011b5e125788
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2026-07-28 11:54:04 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2026-07-28 11:54:04 +0000

    Merge commit 6b0a46958c56 from llvm-project (by Piotr Kubaj):
    
      [libunwind][PPC64] Fix unw_getcontext corrupting callee-saved VSX registers on LE (#198371)
    
      This is the first of two independent fixes for libunwind on ppc64le
      (ELFv2 ABI, little-endian), where two separate bugs together cause
      SIGSEGV during backtracing. This commit addresses the VSX register
      corruption; the TOC-restore fault is handled in a follow-up. Both
      were discovered while debugging lang/rust build failures with
      RUST_BACKTRACE=1 on FreeBSD/powerpc64le (IBM POWER9).
    
      On ppc64le, `unw_getcontext` saves each VS register with an in-place
      `xxswapd n, n` followed by `stxvd2x`. The swap is needed because
      `stxvd2x` stores doublewords in the wrong order on LE. However, the
      macro never applies a second `xxswapd` to restore the register after
      the store, so all 64 VS registers are permanently corrupted on return
      from `unw_getcontext`.
    
      This affects every callee-saved VSX register: f14-f31 (VSR14-VSR31)
      and VR20-VR31 (VSR52-VSR63). After `_Unwind_Backtrace` returns, any
      code that uses these registers sees wrong values. In practice this
      manifests as SIGSEGV inside hashbrown's `reserve_rehash`: VR20-VR31
      are corrupted before a SIMD comparison loop runs, producing an
      out-of-bounds access.
    
      Fix: add a second `xxswapd n, n` after the `stxvd2x` store. Since
      `xxswapd` is its own inverse, the pair is a no-op on the architectural
      register while still writing the correctly byte-swapped value to memory.
    
    MFC after:      1 week
---
 contrib/llvm-project/libunwind/src/UnwindRegistersSave.S | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S b/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S
index 5139a551ad24..bd41dfcb9db4 100644
--- a/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S
+++ b/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S
@@ -418,9 +418,13 @@ LnoR2Fix:
 // register in the incorrect doubleword order.
 // FIXME: when supporting targets older than Power9 on LE is no longer required
 //        this can be changed to simply `stxv n, 16 * n(4)`.
+// Restore the register after storing: xxswapd is its own inverse, so a second
+// xxswapd undoes the in-place corruption of callee-saved VSRs (f14-f31,
+// VR20-VR31) that would otherwise persist after unw_getcontext returns.
 #define PPC64_STVS(n)      \
   xxswapd n, n            ;\
   stxvd2x n, 0, 4         ;\
+  xxswapd n, n            ;\
   addi    4, 4, 16
 #else
 #define PPC64_STVS(n)      \


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a68987b.32f8e.3d475221>