Skip to content

Add PPC64 JIT support for latest upstream codes - #1

Open
runlevel5 wants to merge 8 commits into
mainfrom
ppc64
Open

Add PPC64 JIT support for latest upstream codes#1
runlevel5 wants to merge 8 commits into
mainfrom
ppc64

Conversation

@runlevel5

@runlevel5 runlevel5 commented Apr 2, 2026

Copy link
Copy Markdown
Owner

PPC64 JIT support for Firefox 154+

trung

Brings JIT compilation to PPC64 — both little-endian (ppc64le) and big-endian (ppc64/ppc64be, ELFv1 and ELFv2) — targeting POWER8+ (ISA v2.07+) with POWER9 (ISA v3.0) / POWER10 (ISA 3.1) optimizations. Enables SpiderMonkey's Baseline interpreter, Baseline and Ion JIT compilers, the native regexp JIT, plus full WebAssembly support — tiering, SIMD, huge memory, JSPI, tail calls, and atomics.

This PR revives the JIT port https://github.com/chmeeedalf/gecko-dev by Cameron Kaiser (@classilla) and Justin Hibbits (@chmeeedalf).

This PR would always track against the latest upstream. If you are a packager, please find downstream patches in Releases, if the version you are after are not there, please simply leave a comment in this PR and I will prepare the patches for you.

If you are after the ESR 153 support, please check out #2

Test results

In tests, we trust!

Real little-endian POWER8 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):

Suite POWER8 default
Full jit-tests (--jitflags=all) 13,715 / 0
Full jstests (JSPI on) PASSED ALL

Real little-endian POWER9 hardware (SpiderMonkey with debug, GCC 16, sponsored by Raptor Computing System):

Suite POWER9 default MOZ_PPC64_FORCE_POWER8=1
Full jit-tests (--jitflags=all) 13,715 / 0 13,715 / 0
Full jstests (JSPI on) PASSED ALL PASSED ALL

Real little-endian POWER10 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):

Suite POWER10 default MOZ_PPC64_FORCE_POWER9=1 MOZ_PPC64_FORCE_POWER8=1
Full jit-tests (--jitflags=all) 13,715 / 0 13,715 / 0 13,715 / 0
Full jstests (JSPI on) PASSED ALL PASSED ALL PASSED ALL

ARM64-host simulator for ppc64le:

Suite FORCE_POWER8=1 FORCE_POWER9=1 FORCE_POWER10=1
Full jit-tests 13,715 / 0 13,715 / 0 13,715 / 0
Full jstests (JSPI on) PASSED ALL PASSED ALL PASSED ALL

shell/os.js ("killed process should not have exitStatus") was a parallel-load flake on slower hosts — the test sent SIGINT to a sleep 60 child and could lose the signal-delivery race under heavy concurrent jstests load, then waitpid blocked until the child exited normally and the assertion failed. Fixed 2026-05-08 by switching to SIGKILL (which is uncatchable, atomic, and works under any load). Patch in this PR.

FORCE_POWER10=1 implies FORCE_POWER9=1 (matches what real-P10 silicon advertises in hwcap2 — both ARCH_3_00 and ARCH_3_1). Six clean sweeps total — zero hard FAIL, zero TIMEOUT.

Real big-endian POWER9 hardware — ELFv1 (Debian ppc64) and ELFv2 (Arch POWER ppc64), SpiderMonkey debug shell:

Host Tier Full jit-tests (--jitflags=all) Full jstests
ELFv1 default (P9) 0 correctness failures (47 timeouts ‡) 0 unexpected / ~53,940 pass
ELFv1 MOZ_PPC64_FORCE_POWER8=1 0 correctness failures (46 timeouts ‡) 0 unexpected / ~53,940 pass
ELFv2 default (P9) 0 correctness failures (5 timeouts ‡) 0 unexpected / ~53,940 pass
ELFv2 MOZ_PPC64_FORCE_POWER8=1 0 correctness failures (7 timeouts ‡) 0 unexpected / ~53,940 pass

‡ Same small set of legitimately slow tests under --jitflags=all's heaviest combinations (e.g. --no-blinterp --no-baseline --no-ion --more-compartments, gc/bug-2049401.js) exceeding the harness's default timeout under shared-host CPU contention — both boxes are VMs sharing hardware with other work. The identical test/flag combination also times out on real little-endian POWER10, confirming host-load noise rather than an endianness or correctness issue; every affected test passes cleanly when re-run in isolation.

Big-endian (ppc64be) support

The same backend runs big-endian, on both the ELFv1 and ELFv2 ABIs, across POWER8/9/10:

  • All execution tiers — Baseline interpreter, Baseline JIT, Ion, and the native regexp JIT.
  • Full WebAssembly, including SIMD and atomics. v128 values follow a canonical little-endian register convention; linear memory, globals, atomics, and the JS↔wasm boundary byte-reverse only where the spec observes byte order.
  • ABI handling gated on _CALL_ELF, not byte order — big-endian ELFv2 shares the little-endian call paths (no function descriptors), while ELFv1 uses {entry, TOC, env} descriptors for the JIT / regexp / wasm entry trampolines and symbolic-address calls.
  • Byte-order fixes for JIT entry stubs, bailout stack slots, wasm stack arguments/results, and mozilla::Result narrow storage. jit-test and wasm spec-harness cases that hard-coded little-endian byte order are made endian-neutral.

Big-endian rendering (full browser)

Firefox on big-endian renders correctly — confirmed on real X11, pixel-verified (correct chrome, page background, link colors, text, and DevTools UI) — via a fourth layer of endian work beyond the JIT itself:

  • NSS GHASH hardware acceleration — the vendored PPC64 vpmsumd-based GHASH (AES-GCM) is made endian-correct rather than stubbed out on big-endian, plus a companion fix for a real (both-endian, not just BE) gcm.c/ghash-ppc.c struct-layout mismatch that corrupted the hardware GHASH dispatch and crashed on the first real TLS 1.3 handshake.
  • libwebp VSX decode kernels — the WMERGEH/WMERGEL widening-merge fix, same underlying issue class as the GHASH fix: GNU C vector element indexing is memory-order, so a widening merge lands in the opposite half on big-endian.
  • Skia + software WebRender — big-endian used to flip Gecko's OS_RGBA surface-format synonym to a memory layout (A8R8G8B8) that Skia has no color type for, hitting MOZ_DIAGNOSTIC_CRASH("A8R8G8B8 unsupported by Skia") on the first paint. Fixed by keeping the whole pixel pipeline on one layout (Skia's little-endian value convention) and converting only at the two real boundaries: Skia's scalar blitters (fills, AA text, LCD subpixel text, glyph masks — via a BE_CONVERT macro, no-op on little-endian) and the software-WebRender→X11 handoff (dirty-region swizzle in RenderCompositorSWGL).
  • Known remaining gap: SkRasterPipeline's load/store stages (used for gradients and image sampling through Skia) are unchanged and still assume little-endian — content exercising that path may still show incorrect colors on big-endian. Not yet hit by the JS/DOM-heavy jit-test and jstests suites above, which is why it wasn't caught by that matrix; flagging here rather than leaving it silently uncovered.

Scope

  • 19 new files in js/src/jit/ppc64/ — ~17,500 lines.
  • Modifications to ~60 shared files (dispatch headers, build system, wasm, CacheIR, MacroAssembler, WasmStacks).
  • Full Firefox browser builds successfully (GCC + lld).

What's new vs the old chmeeedalf/gecko-dev Firefox-86 port

Inherited: Architecture-ppc64.h register/ABI constants, the Assembler-ppc64.h/cpp instruction-encoding skeleton, some basic MacroAssembler patterns.

New in this port:

  • Build system integration (js/moz.configure, dispatch headers, js/src/jit/moz.build).
  • Full WebAssembly — baseline + Ion, tiering, signal handlers, builtins, tail calls, atomics, huge memory, SIMD, JSPI. The old fork had zero Wasm.
  • Wasm SIMD — complete VMX/VSX (~280 methods), all 10 tiers, full spec tests, both P8 and P9.
  • Warp/Ion backend — complete CodeGenerator, Lowering visitors, LIR-ppc64 (old fork predated Warp).
  • Atomic operations — ~980 lines of CompareExchange / AtomicExchange / AtomicFetchOp.
  • POWER8/9/10 runtime detection via getauxval(AT_HWCAP2), with fallback sequences for every POWER9-only instruction and POWER10 fast paths gated on HasPOWER10().
  • Code-size optimizations — inline constant pool for SIMD + FP constants, POWER9 addpcis FP-constant path, POWER10 prefix-instruction fast paths (see below), GCC-style lis+ori+rldimi 64-bit load (~37 % smaller than a bcl-based stanza).
  • Long-branch relocation, OSI epilogue padding, QEMU-style FlushICache.

Key architecture-specific features

Runtime POWER8/POWER9/POWER10 selection

Detection via getauxval(AT_HWCAP2)PPC_FEATURE2_ARCH_3_00 for POWER9, PPC_FEATURE2_ARCH_3_1 for POWER10.

  • POWER9 native paths (with P8 fallbacks): cnttzd/w, xxbrd, mtvsrws, mcrxrx, addpcis, modsw/u/d/du, vinsert{b,h} (lane insert from VR + immediate byte position), xxinsertw, mfvsrld, mtvsrdd, xs{min,max}jdp, xxspltib, vcmpne{b,h,w}, vneg{w,d}, isel, xscvdphp/xscvhpdp (FP16 scalar conversion), xsxexpdp (P9 exponent extract for nearbyIntDouble). replaceLaneInt{8x16,16x8} on POWER9 emits the 2-insn mtvsrd + vinsert{b,h} sequence (down from 5 insns). clampDoubleToUint8 is fully branchless on P9 via xsmaxjdp + isel — the canonical JS clamp shape collapses to a 4-insn straight-line sequence.
  • POWER10 fast paths (gated on HasPOWER10()):
    • Prefix-instruction memory traffic — generic, not constants-only.
      • Loads (Address operands when displacement exceeds 16 bits): loadPtrpld, loadDoubleplfd, loadFloat32plfs, loadUnalignedSimd128plxv. Replaces the prior addis + ori + ldx-style two-insn stanzas with one prefixed insn.
      • Stores (same shape): storePtrpstd, storeDoublepstfd, storeFloat32pstfs, storeUnalignedSimd128pstxv.
      • Constant materialisation: loadConstantSimd128 3 + xxpermdi → 1 plxv; loadConstantDouble/Float32 2 → 1 plfd/plfs; movePtr(ImmWord) 33–34-bit signed 5 → 1 paddi.
    • Single-instruction lane / byte-reverse / lane-insert collapses: brd collapses byteSwap64 3 → 1 + drops the GPR↔FPR round-trip; brh/brw collapse byteSwap16{Sign,Zero}Extend/byteSwap32 from 3-4 → 2; vinsw/vinsd collapse replaceLaneInt{32x4,64x2} from 2 → 1 (no scratch VSR); vinsbrx/vinshrx cover the same byte/halfword replaceLane on POWER10; vextract{b,h,w,d}m collapses bitmask to 1 insn; vmulld collapses mulInt64x2 from 9-11 insns to 1.
    • CR-bit-to-GPR collapses via setbc/setbcr: 1-insn ma_cmp_set, 1-insn allTrueInt* CR6.EQ extract, and 5 → 3 insn anyTrueSimd128. Replaces the older mfocrf + rlwinm + andi. extraction pattern across the boolean-reduction family.

Test with MOZ_PPC64_FORCE_POWER8=1 (downgrade), MOZ_PPC64_FORCE_POWER9=1 (force P9 on, useful under sim), or MOZ_PPC64_FORCE_POWER10=1 (which implies FORCE_POWER9=1 — matches real-P10 silicon detection). All three configurations PASS the full jit-test + jstests sweeps end-to-end on the simulator.

POWER10 prefix-instruction support

Power ISA v3.1 prefixed instructions are 8 bytes (4-byte prefix word with primary opcode 1 + 4-byte suffix word) and must not straddle a 64-byte aligned block at runtime. The assembler emits them via as_paddi / as_pld / as_plxv / as_plfd / as_plfs, with an automatic leading-nop guard when the prefix would otherwise cross the boundary.

The original guard checked (currentOffset() & 63) == 60 — a buffer-relative test that's only correct when the JitCode allocator base is 64-byte aligned. The allocator only guarantees 16-byte alignment, so across the four base-mod-64 classes {0, 16, 32, 48} the unsafe straddle is exactly (currentOffset() & 15) == 12. The same fix shape applies to the inline-emit path (ensurePrefixedAlignment, commit 8ae818d0fcab) and the constant-pool patcher (PatchConstantPoolLoad, commit aea233e21209). The simulator's POWER10 model doesn't trap misaligned prefixes, which is why these only surfaced when real-P10 silicon came online.

The simulator decodes prefixed instructions, validated against as -mpower10 + objdump on Fedora 44 / binutils 2.46. Encoding details (MLS Type=2 vs 8LS Type=0 vs 8RR Type=1, R-bit at LE position 20, plxv 5-bit suffix opcode + TX bit at suffix bit 26) live in Simulator-ppc64.cpp source comments and PLAN.md's engineering-lessons section.

WASM SIMD

Full VMX/VSX implementation using PPC64 AltiVec. All 10 tiers — load/store/splat/lane, bitwise, arithmetic, cmp/shift, float, conversions, shuffle/swizzle, extmul/pairwise/dot, relaxed SIMD (FMA/FNMA). NaN semantics correct (min/max propagation, truncSat NaN→zero, promote NaN-quieting). P8 uses lxvd2x/stxvd2x with byte-swap; P9 uses native lxvx/stxvx; P10 collapses the constant-pool variant to a single plxv.

WASM JSPI

WebAssembly.Suspending / WebAssembly.promising via javascript.options.wasm_js_promise_integration. Add ppc64 to the JSPI whitelists in js/moz.configure (both the default_wasm_jspi simulator allowlist and the wasm_jspi simulator-guard die-list — extending the original target.cpu enable to cover sim builds too), and round ContRedZoneSize up to a page-size multiple so the bottom guard page lands on a page boundary under PPC64LE's 64 KiB pages. No arch-specific stack-switch code required.

WASM huge memory

4 GB + 32 MB virtual reservation per wasm memory, bounds-check elimination via SIGSEGV → wasm trap. Signal-handler context indices: gp_regs[32]=NIA, gp_regs[1]=SP, gp_regs[31]=FP, gp_regs[36]=LR.

Simulator (ARM64-host)

A full PPC64 simulator is included so CI can run the JIT on non-PPC64 hosts. Both jit-test and jstests sweeps pass under FORCE_POWER8=1, FORCE_POWER9=1, and FORCE_POWER10=1 configurations (zero hard FAIL, zero TIMEOUT). The sim received many ISA-correctness fixes during development (VMX/VSX decoding, LE lane ordering, FP NaN-payload preservation across f32↔f64, ELFv1 FP-arg shadow slots, single-step profiling for tail calls and non-leaf epilogues), and now decodes:

  • Power ISA v3.0 (POWER9): addpcis, mods*/modu*, mtvsrws, xxspltib, xxinsertw, xscvdpsp(n) HW-conformance fix, xs{max,min}jdp, xscvdphp/xscvhpdp (FP16), xsxexpdp. Closes the historical "~40 wasm/simd tests fail under FORCE_POWER9 on the sim" coverage gap.
  • Power ISA v3.1 (POWER10): prefixed instructions (paddi/pld/plxv/plfd/plfs), plus the new instruction-count-reduction ops (brd, brh, brw, vinsw, vinsd, vinsbrx, vinshrx, vextract*m, setbc/setbcr, vmulld).
  • A simulator-side setXEROV() fix that mirrors OV→OV32 — the JIT's branchMulPtr Overflow path uses POWER9's mcrxrx+bc which reads OV32, and the original sim only set OV. Surfaced as silent BigInt fast-path-mul wrap-around in wasm/regress/bug1836708.js.

Build

Complete from-scratch walkthrough — little-endian (Debian / Ubuntu / Fedora, ppc64le)

Mozilla's ./mach bootstrap cannot download prebuilt toolchains for ppc64, so
everything comes from your distro plus rustup. These steps take a fresh
ppc64le machine to a running browser. Big-endian Debian has its own section
right after this one.

Verified end-to-end on a clean Debian 13 (trixie) ppc64le container on real
POWER9 hardware: these exact commands produce a working firefox binary.

1. Install build dependencies.

Debian / Ubuntu — let apt resolve the whole Firefox dependency tree, then add
the handful of pieces it misses:

# Enable source repositories first:
#   Debian 12+: add "deb-src" lines matching your "deb" lines in
#   /etc/apt/sources.list, or Types: deb deb-src in /etc/apt/sources.list.d/debian.sources
sudo apt update
sudo apt build-dep firefox-esr        # bulk of the dependencies
sudo apt install git curl ccache python3-venv python3-pip \
                 pkg-config nasm nodejs npm libclang-dev clang lld

Fedora:

sudo dnf builddep firefox
sudo dnf install git curl ccache nasm nodejs clang clang-devel lld

2. Install Rust and cbindgen via rustup. Distro packages are almost
always too old — this tree requires Rust >= 1.90 and cbindgen >= 0.29.4
(node only needs >= 12, any current distro package is fine):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source ~/.cargo/env
rustup default stable
cargo install cbindgen

Make sure ~/.cargo/bin stays on PATH for every build shell.

3. Clone this repository and branch.

git clone --branch ppc64 https://github.com/runlevel5/firefox-ppc64.git
cd firefox-ppc64

(For ESR 153 use --branch esr153-ppc64, see PR #2. Packagers who prefer
patch files over a git checkout: apply the numbered patches from
Releases on top of the
matching Mozilla release tarball instead.)

4. Write a mozconfig. Create a file named mozconfig in the tree root
with one of the configurations below (JS shell, full Firefox GCC, or full
Firefox Clang+LTO). Two lines matter on ppc64 no matter which you pick:

ac_add_options --disable-bootstrap                  # never try to fetch Mozilla toolchains
ac_add_options --without-wasm-sandboxed-libraries   # no wasi sysroot for ppc64

5. Build and run.

./mach build
./mach run          # run from the object directory
./mach package      # or produce a distributable tarball in <objdir>/dist/

Hardware/RAM notes: linking libxul.so with lld peaks around 8 GB;
16 GB RAM is a comfortable minimum for the full browser (the JS shell builds
on much less). On bigger machines cap parallelism (mk_add_options MOZ_PARALLEL_BUILD=20) rather than letting mach use every core — wide lld
links can OOM the box.

Troubleshooting:

  • mach fails creating its virtualenv → sudo apt install python3-venv.
  • configure errors about Rust or cbindgen versions → check rustc --version
    (>= 1.90) and cbindgen --version (>= 0.29.4); the rustup/cargo copies in
    ~/.cargo/bin must precede any distro copies on PATH.
  • configure cannot find libclang → install libclang-dev (Debian) /
    clang-devel (Fedora) and point --with-libclang-path at the directory
    containing libclang.so (llvm-config --libdir).
  • OOM during the final link → lower MOZ_PARALLEL_BUILD, ensure the linker
    is lld (--enable-linker=lld), add swap/zram.
  • Big-endian: see the next section.

Complete walkthrough — big-endian Debian (ppc64, ELFv1)

Big-endian Debian is an unofficial port living in debian-ports (sid only),
and the ELFv1 ABI changes the toolchain rules: lld cannot link ELFv1 at
all, and Debian's clang forces lld
— so the build must use GCC with GNU
ld (bfd)
for both target and host. Steps 2, 3 and 5 from the
little-endian walkthrough apply unchanged (rustup supports big-endian
powerpc64-unknown-linux-gnu); the differences:

1. Dependencies. On a debian-ports sid system:

sudo apt update
sudo apt build-dep firefox-esr   # if firefox-esr is unavailable in ports, use:
sudo apt install build-essential git curl ccache python3-venv python3-pip \
                 pkg-config nasm m4 unzip zip \
                 libgtk-3-dev libdbus-glib-1-dev libpulse-dev libasound2-dev \
                 libxt-dev libx11-xcb-dev libpixman-1-dev \
                 nodejs npm libclang-dev

4. mozconfig for big-endian ELFv1:

export CC=gcc
export CXX=g++
ac_add_options --enable-application=browser
ac_add_options --enable-optimize
ac_add_options --disable-debug
ac_add_options --enable-release
ac_add_options --disable-tests
ac_add_options --enable-jit
ac_add_options --disable-bootstrap
ac_add_options --with-libclang-path=`llvm-config --libdir`
ac_add_options --without-wasm-sandboxed-libraries
ac_add_options --enable-linker=bfd
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-ppc64be

Big-endian caveats:

  • bfd needs substantially more RAM than lld to link libxul.so
    (community reports ~20 GB resident); on smaller machines build the JS shell
    (--enable-application=js), which links fine everywhere.
  • The DevTools build step needs a working Node.js, and Debian's big-endian
    nodejs currently segfaults on it — see the dedicated Node.js
    bootstrap
    section below for the two workarounds (DevTools-server-only
    build, or forwarding node to a little-endian helper host).
  • cbindgen must still come from cargo install cbindgen — the ports archive
    version is too old.
  • Big-endian ELFv2 distros (e.g. Arch POWER) use the same recipe minus the
    ELFv1 constraint origin — but clang's forced lld still applies on Debian
    derivatives, so GCC + bfd remains the safe choice on any big-endian
    system.

mozconfig reference

SpiderMonkey (standalone JS shell):

ac_add_options --enable-application=js
ac_add_options --enable-optimize
ac_add_options --disable-debug
ac_add_options --disable-tests
ac_add_options --enable-jit
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-sm-release

./mach build -j20

(On the PPC64 box, cap parallelism at -j20; the auto-detected -j32 saturates the box during lld linking.)

Full Firefox:

export CC=gcc
export CXX=g++
ac_add_options --enable-application=browser
ac_add_options --enable-optimize
ac_add_options --disable-debug
ac_add_options --enable-release
ac_add_options --disable-tests
ac_add_options --enable-jit
ac_add_options --disable-bootstrap
ac_add_options --with-ccache
ac_add_options --with-libclang-path=/usr/lib64
ac_add_options --without-wasm-sandboxed-libraries
ac_add_options --enable-linker=lld
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-ppc64

./mach build -j20

Full Firefox with Clang + LTO (ppc64le):

A Clang + ThinLTO build works on ppc64le and is measurably faster on
DOM/layout-heavy workloads than the plain GCC -O2 build. Two things make it
work: Clang with the LLVM linker (lld), and system NSS — the bundled
NSS ppc-gcm.s uses GAS-style semicolon statement separators that Clang's
integrated assembler rejects, so building against the distro's NSS
(--with-system-nss) sidesteps that entirely. This is exactly what the Fedora
package build does.

export CC=clang
export CXX=clang++
ac_add_options --enable-application=browser
ac_add_options --enable-optimize
ac_add_options --disable-debug
ac_add_options --enable-release
ac_add_options --disable-tests
ac_add_options --enable-jit
ac_add_options --disable-bootstrap
ac_add_options --enable-linker=lld
ac_add_options --enable-lto              # ThinLTO
ac_add_options --with-system-nss         # avoids Clang IAS choking on NSS ppc-gcm.s
ac_add_options --with-system-nspr
ac_add_options --with-libclang-path=`llvm-config --libdir`
ac_add_options --without-wasm-sandboxed-libraries
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-clang

./mach build -j20

Do not add PGO on ppc64le. Profile-guided optimization is currently
broken on this target — GCC ICEs during the instrumented build and Clang's
instrumented build crashes at runtime (see
DKnoto/Firefox-Benchmarks).
LTO alone is the supported configuration.

--with-libclang-path must point at the directory that actually holds
libclang.so. On distros that version the LLVM tree (e.g. Fedora's
/usr/lib64/llvm22/lib64) let llvm-config --libdir resolve it rather than
hard-coding /usr/lib64.

For RPM packagers: the Fedora spec builds this with
rpmbuild --with build_with_clang --with build_with_lto.

Big-endian (ppc64be): Node.js bootstrap

The full browser build runs Node.js at build time to transform the DevTools
debugger modules (devtools/client/* via mozbuild/action/node.py). Nothing
Node produces ships in the binary — it is a build-time tool only — but the
build cannot finish without it, and Node on big-endian ppc64 is currently a
problem:

  • Mozilla ships no prebuilt Node toolchain for ppc64, so the build needs a
    system Node.
  • Debian's ppc64 (BE) nodejs is an unofficial port frozen at 20.19.5 and
    its libnode segfaults during a V8 conservative-stack-scan GC
    (heap::base::Stack::IteratePointersImpl) when running the DevTools
    transform — an endianness-specific V8/Node bug, unrelated to this port.

Two ways to get past it:

1. Skip the DevTools client (simplest). Set the DevTools build to
server instead of all. This drops the browser-side debugger UI but keeps
the DevTools server (remote debugging still works) and needs no Node:

export MOZ_DEVTOOLS=server   # requires a one-line source edit; see note below

MOZ_DEVTOOLS cannot be set from mozconfig (it is an imply_option), so
change imply_option("MOZ_DEVTOOLS", "all") to "server" in
browser/moz.configure, or wait for a proper --disable-devtools-style knob.

2. Offload Node to a working host (full DevTools). If you have a
little-endian ppc64le box (or any box with a working Node), run only the Node
steps there while the compile stays on the BE machine. Node just reads/writes
files in the source and object trees, so share the tree and forward node:

  • On the LE helper, mount the BE build tree (e.g. via sshfs) and confirm its
    Node runs devtools/client/shared/build/build.js without crashing.
  • On the BE box, put a node wrapper first on PATH that sshes the command
    to the helper, rewriting the tree-path prefix (BE mountpoint ↔ helper
    mountpoint) in both the arguments and in the dep: lines Node prints back
    (the build system consumes those for incremental rebuilds):
#!/bin/bash
# ~/nodewrap/node  — forward Node to an LE helper that shares this tree.
LOCAL=/path/to/be/firefox          # tree path on the BE box
REMOTE=/path/to/helper/mount       # same tree, as seen on the helper
args=(); for a in "$@"; do args+=("${a//$LOCAL/$REMOTE}"); done
out=$(ssh helper "cd $(printf %q "${PWD//$LOCAL/$REMOTE}") && \
      node $(printf '%q ' "${args[@]}")"); rc=$?
printf '%s\n' "${out//$REMOTE/$LOCAL}"; exit $rc
PATH=~/nodewrap:$PATH ./mach build -j20

Longer term the clean fix is a Node that does not crash on ppc64 BE (e.g.
building Node from source — Arch POWER's nodejs-lts-iron recipe builds
20.20.0 for powerpc64 with --with-intl=system-icu).

Known limitations

  • Clang full Firefox: works with --with-system-nss + lld (see the Clang + LTO build recipe above). Only the bundled NSS is a problem — its ppc-gcm.s uses GAS-style semicolons that Clang's integrated assembler rejects — so building against the distro NSS avoids it. PGO is still unavailable on ppc64le (GCC ICE / Clang runtime crash); LTO-only.
  • ld.bfd: does link libxul.so successfully on ppc64le, but needs substantially more RAM during the link than lld (community reports ~20+ GiB resident, putting it out of reach for hosts with under ~24 GiB total). The P10 box uses BFD as a workaround for an LLD R_PPC64_TOC16_HA bug; lld stays the practical default everywhere else for speed.

TODO

@runlevel5
runlevel5 marked this pull request as draft April 2, 2026 04:12
@runlevel5
runlevel5 force-pushed the ppc64 branch 4 times, most recently from 3e0d256 to 6df5cde Compare April 9, 2026 23:09
runlevel5 pushed a commit that referenced this pull request Apr 9, 2026
Upstream commit: https://webrtc.googlesource.com/src/+/fe210de7215dc375cba88a42df2715e4a4d6706f
    Let dav1d retain references to wrapped bitstream buffers.

    (cherry picked from commit fcea1cf20ab03a15d2ca702629208e965edb3990)

    Bug: chromium:486421953
    Change-Id: I855616d8206711b371df05a306730468ec8d23e7
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453200
    Commit-Queue: Philip Eliasson <philipel@webrtc.org>
    Reviewed-by: Erik Språng <sprang@webrtc.org>
    Cr-Original-Commit-Position: refs/heads/main@{#47051}
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/454341
    Reviewed-by: Johannes Kron <kron@webrtc.org>
    Cr-Commit-Position: refs/branch-heads/7680@{#1}
    Cr-Branched-From: d1972add2a63b2a528a6471d447f82e0010b5215-refs/heads/main@{#46853}
@runlevel5
runlevel5 force-pushed the ppc64 branch 3 times, most recently from 4bc3c4e to 3458b07 Compare April 13, 2026 22:57
runlevel5 pushed a commit that referenced this pull request Apr 14, 2026
Upstream commit: https://webrtc.googlesource.com/src/+/de817d4ccf67a457e310c6a1eca6eafcd9c2977e
    [M147] Revert^3 "Default enable WebRTC-HeaderExtensionNegotiateMemory"

    Original change's description:
    > Revert^3 "Default enable WebRTC-HeaderExtensionNegotiateMemory"
    >
    > This reverts commit 2f069781037ac1f9965d39152c6c97ea98ce6aff.
    >
    > Reland "Default enable WebRTC-HeaderExtensionNegotiateMemory"
    >
    > This reverts commit 2f069781037ac1f9965d39152c6c97ea98ce6aff.
    >
    > Reason for revert: Abundance of caution - want more canary time.
    >
    > Original change's description:
    > > Revert^2 "Default enable WebRTC-HeaderExtensionNegotiateMemory"
    > >
    > > This reverts commit 74d988fd57f8f1b6722d8ac6f49c686b9f2bc196.
    > >
    > > Reland "Default enable WebRTC-HeaderExtensionNegotiateMemory"
    > >
    > > This reverts commit 74d988fd57f8f1b6722d8ac6f49c686b9f2bc196.
    > >
    > > Reason for revert: Added code to skip stopped transceivers
    > >
    > > Original change's description:
    > > > Revert "Default enable WebRTC-HeaderExtensionNegotiateMemory"
    > > >
    > > > This reverts commit 4ecf297a4c0af68ff8af8c3a8e6b0832bddd14d5.
    > > >
    > > > Reason for revert: Impacted unexpected application usages
    > > >
    > > > Original change's description:
    > > > > Default enable WebRTC-HeaderExtensionNegotiateMemory
    > > > >
    > > > > Spec change: w3c/webrtc-extensions#238
    > > > >
    > > > > Chromestatus entry for change: https://chromestatus.com/feature/5135528638939136
    > > > >
    > > > > Bug: webrtc:439514253
    > > > > Change-Id: I296f2f06dd69b4e30be419b44c926acfd2722e2d
    > > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/407821
    > > > > Commit-Queue: Harald Alvestrand <hta@webrtc.org>
    > > > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
    > > > > Cr-Commit-Position: refs/heads/main@{#45993}
    > > >
    > > > Bug: webrtc:439514253, chromium:467164231
    > > > Change-Id: I95dbc8cbaf1b769ffaea291801684bc26e4b9ccb
    > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/433102
    > > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
    > > > Commit-Queue: Harald Alvestrand <hta@webrtc.org>
    > > > Cr-Commit-Position: refs/heads/main@{#46456}
    > >
    > > Bug: webrtc:439514253, chromium:467164231
    > > Change-Id: I2df85ba25016374a52abb13037cdca74fb1a395d
    > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453240
    > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
    > > Commit-Queue: Guido Urdaneta <guidou@webrtc.org>
    > > Cr-Commit-Position: refs/heads/main@{#47038}
    >
    > No-Try: True
    > Bug: webrtc:439514253, chromium:467164231, webrtc:489813847
    > Change-Id: Id2151293ffe14d2238a1363dd7df679c8a27c42f
    > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453820
    > Commit-Queue: Harald Alvestrand <hta@webrtc.org>
    > Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
    > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
    > Cr-Commit-Position: refs/heads/main@{#47093}

    (cherry picked from commit 5f9534d9205a870d40aff649967a38fbde7d7653)

    Bug: chromium:491748676,webrtc:439514253,chromium:467164231,webrtc:489813847
    Change-Id: Id2151293ffe14d2238a1363dd7df679c8a27c42f
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/455980
    Auto-Submit: Chrome Cherry Picker <chrome-cherry-picker@chops-service-accounts.iam.gserviceaccount.com>
    Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
    Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
    Cr-Commit-Position: refs/branch-heads/7727@{#1}
    Cr-Branched-From: 5788235ac856f62f1522d1491c4a8b00dba10c82-refs/heads/main@{#47086}
@runlevel5
runlevel5 marked this pull request as ready for review April 16, 2026 22:55
@runlevel5

Copy link
Copy Markdown
Owner Author

@classilla @carlosgonz0 @chmeeedalf please feel free to give this PR a try. I have tried to hand test it as much as possible but I am sure I might have missed some edge cases

runlevel5 added a commit that referenced this pull request Apr 18, 2026
The four call sites of xxinsertw in MacroAssembler-ppc64-inl.h were
emitted unconditionally:
  - replaceLaneInt32x4         (line 3523)
  - replaceLaneFloat32x4       (line 3532)
  - convertFloat64x2ToFloat32x4 (lines 4716, 4720, both lanes)

xxinsertw is POWER9 (ISA 3.0) only; binutils confirms `as -mpower8
xxinsertw 0,1,0` rejects the opcode. On real POWER8 silicon these
helpers would SIGILL the first time a wasm SIMD program reaches them
(replaceLane / demote / lane-load fast paths). The "POWER8 forced"
mode (MOZ_PPC64_FORCE_POWER8=1) only flips runtime gating, so our
POWER9 dev box never caught this — the silicon executes the
unconditional xxinsertw fine regardless of what HasPOWER9() returns.

Wrap each helper in `if (HasPOWER9()) { /* original 2-insn path */ }
else { /* POWER8 fallback */ }`. The fallbacks:

replaceLaneInt32x4 (~5 insns) — mirrors the existing replaceLaneInt16x8
POWER8-compatible pattern: extract the relevant doubleword to a GPR
(mfvsrd or xxpermdi+mfvsrd), rldimi rhs into the right 32-bit slot,
mtvsrd back, xxpermdi to recombine. Lane → (dword, wordInDword)
mapping: dword = lane / 2, wordInDword = lane % 2.

replaceLaneFloat32x4 (~8 insns) — convert the f64 rhs to single via
xscvdpspn (lands in BE bits 0..31 of an FPR), extract bits to a GPR
via mfvsrd + srdi 32, then run the same int-insert sequence as above.

convertFloat64x2ToFloat32x4 (~14 insns) — per-lane extract to GPR
(swap halves with xxpermdi DM=2 for lane 0, then xscvdpsp + mfvsrd +
srdi/rldicr to place each single in low/high 32 bits of a GPR),
combine via or, then mtvsrd + xxpermdi DM=0 to place in LE dw0 with
LE dw1 zeroed.

Aliasing matrix considered for each helper:
- replaceLaneInt32x4: rhs is GPR, lhsDest is FPR — no FPR/GPR aliasing.
- replaceLaneFloat32x4: rhs is FPR. If rhs == lhsDest, the initial
  xscvdpspn snapshots rhs into scratch before any write to lhsDest.
- convertFloat64x2ToFloat32x4: pre-existing VR2 stash already handles
  dest == src.

Verified:
- 191/191 wasm/simd jit-tests on POWER9 default AND POWER8 forced.
- 13572/13572 full jit-test suite on POWER9 default AND POWER8 forced
  (zero failures on either run).
- Argon2 reference hash 60c920340f5dbf67... matches under default,
  baseline, and optimizing tier on both micro-archs.

POWER9 path code-size and runtime are unchanged; the new branches are
emitted only when HasPOWER9() returns false at compile time of each
JIT function.
runlevel5 added a commit that referenced this pull request Apr 18, 2026
Move the xxinsertw / replaceLane / convertFloat64x2ToFloat32x4 entry
out of the open punch list. Document the three new POWER8 fallback
shapes, instruction-count costs, aliasing analysis, and verification
results on both micro-arch gating modes. Note the remaining gap that
real POWER8 silicon validation is still recommended.
runlevel5 added a commit that referenced this pull request Apr 18, 2026
Update the Status section to capture the POWER8-forced JetStream 3.0
result alongside the POWER9 default score:

  POWER9 default  : 36.82 pts
  POWER8 forced   : 35.50 pts  (~3.6% slower)

This is the first full POWER8-fallback run after the xxinsertw
fallbacks landed (Tier C #1, commit 065161b), and confirms the
POWER8 paths execute end-to-end without crashes. The ~3.6% gap is
within the expected envelope given the POWER8 fallback cost (VR-staged
abs/neg, inline FP constant loads, rldimi-based replaceLane).
@runlevel5
runlevel5 force-pushed the ppc64 branch 2 times, most recently from b5618d4 to 788c91c Compare April 26, 2026 03:40
runlevel5 pushed a commit that referenced this pull request Apr 28, 2026
Upstream commit: https://webrtc.googlesource.com/src/+/1822467bec1c91b8d782e9c7f24342d1d65f01f2
    [Merge-148] Cherry pick "Move the NullVideoDecoder into a separate file and target."

    Original change's description:
    > Move the NullVideoDecoder into a separate file and target.
    >
    > This is necessary because the Chromium video decoder factory needs to
    > be able to instantiate it for fallback purposes (e.g. Decode error
    > causing the HW to no longer be available).
    >
    > Bug: chromium:500960863
    > Change-Id: I724a5f28aa0a0a615972dd49eebde701c3b7ec90
    > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/462243
    > Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
    > Commit-Queue: Henrik Boström <hbos@webrtc.org>
    > Cr-Commit-Position: refs/heads/main@{#47366}

    Bug: chromium:500960863
    Change-Id: I724a5f28aa0a0a615972dd49eebde701c3b7ec90
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/464521
    Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
    Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
    Cr-Commit-Position: refs/branch-heads/7778@{#1}
    Cr-Branched-From: ca896b7ffef011bbf6957c99d413c5aac602c99f-refs/heads/main@{#47319}
runlevel5 added a commit that referenced this pull request Apr 28, 2026
… list)

Same outcome as audit #1: nothing's actually wrong. All three threads
are either identical to a reference backend's well-tested pattern or
match the documented PPC64 convention (32-bit ops = sign-extended
canonical int32). Notes in PLAN.md so a future reader doesn't re-open
these.
@runlevel5
runlevel5 force-pushed the ppc64 branch 2 times, most recently from a363036 to 9108914 Compare April 28, 2026 23:31
Comment thread mfbt/Assertions.h
"st.d %1,%0,0;\n" // Write the line number to the crashing address
: // no output registers
: "r"(aAddress), "r"(aLine));
# elif defined(__powerpc64__)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

runlevel5 added a commit that referenced this pull request May 6, 2026
…eeper mystery

Adds probe_vrsave_p9.c (transient) — tests whether Linux PPC64LE
honors VRSAVE for context-switch save/restore decisions. Both phases
PASS: VRs are preserved across sched_yield+usleep regardless of
VRSAVE value (default 0xffffffff or forced 0). Kernel saves all VRs
unconditionally. Hypothesis #1 (Mozilla not maintaining VRSAVE)
ruled out.

Extends WasmSignalHandlers.cpp [lc1-vr] patch to also dump key GPRs
(r1, r4, r11, r24) from ucontext alongside VRs. Captured GPRs are
sane and consistent (r24 = wasm base, r1 = sp matches startWasmTrap's
sp, r11 = r4 + 304). ucontext reads ARE reliable. Hypothesis mozilla-firefox#4
(misreading ucontext) ruled out.

That leaves a gap between static disasm (predicts non-negative
trunc_sat output via pmax→pmin chain) and runtime captured VRs
(vr6 lane 0 = 0xFF000000 = -16M). Strongest remaining: gdb's PowerPC
disassembler misinterprets an instruction in the chain, so we're
reading code that's not actually executing.

Math at trap is fully consistent with captured values:
  vr6 * 18 (mod 2^32) + vr8 = vr1 → produces {0xEE000000, 0xFFFFFFF7, 5, 7}
  vr1 + vr2 = vr16 → produces {1.13e9, 1.08e9, 7.29e8, 3.75e8}
  lane0(vr16) << 4 + base produces r4 = 0x41A29110 → OOB at base+1.1GB

Bug is real, captured, and corruption is in v6 (X coords) coming out
of the trunc_sat chain at JIT 0x4afc despite static analysis saying
the chain produces non-negative output.
runlevel5 added a commit that referenced this pull request May 7, 2026
…duce

Built probe_lc1_chain_p9.c — bare-minimum C+inline-asm replay of
the trunc_sat → 300-op filler → vmuluwm pattern. 0 corruptions in
10M iterations on P9. So the bug is NOT a generic "long VSU dep
chain" silicon issue; it requires specific lc.wasm chain context
the synthetic doesn't capture.

Captured today's actual JIT disasm via [lc1-bytes] hook, saved to
artifacts/lc-trap-2026-05-07.{bin,disasm.txt} (gitignored). Today's
chain matches the May 5 layout structurally: vs33 (=v1) trunc_sat
at 0x4bb0, multiply at 0x50f0, no intermediate writes to vs33 in
between. The architectural register that gets corrupted varies per
run (vr5 in May 5; vr1 today), confirming the bug is a regalloc/
rename-routing event, not register-specific.

A faithful 515-instruction-window standalone reproducer would
require careful state setup; not undertaken this session.
@sharkcz

sharkcz commented May 7, 2026

Copy link
Copy Markdown

FWIW it seems ld.bfd can link libxul.so on my Fedora 42 (256 GB system) ...

@runlevel5

Copy link
Copy Markdown
Owner Author

FWIW it seems ld.bfd can link libxul.so on my Fedora 42 (256 GB system) ...

@sharkcz that's ALOT of RAM you have. It's good to know it does work, let me update the notes

@runlevel5

Copy link
Copy Markdown
Owner Author

@sharkcz I believe you have POWER8 hardware, wondering if you could help run full jit-test and jstests for me and let me know the results? Many thanks

runlevel5 added a commit that referenced this pull request May 8, 2026
Updates the POWER8 status block + "Truly open" item #1 to reflect the
2026-05-08 result: full jit-test sweep clean on the architected-P8
KVM guest after Cluster A (commit 0e92b3e) and Cluster B
(commit 3dcf4a1). Cluster B's real codegen fix remains open as
a follow-up tracking with upstream Bug 1666747.
@sharkcz

sharkcz commented May 11, 2026

Copy link
Copy Markdown

@sharkcz I believe you have POWER8 hardware, wondering if you could help run full jit-test and jstests for me and let me know the results? Many thanks

yes, I should be able to run the tests on a P8 system. What is the procedure you are using?

@runlevel5

Copy link
Copy Markdown
Owner Author

yes, I should be able to run the tests on a P8 system. What is the procedure you are using?

@sharkcz you need to build the software on your P8 first, check the Build section of the PR description for HOWTO. Then run the tests with ./mach jit-test and ./mach jstests. I've done the test run with POWER8 VM but unsure if it would work the same way with a real non-VM POWER8 (in theory it should be because KVM would translate down to micro-arch of the host right)

@runlevel5

Copy link
Copy Markdown
Owner Author

@sharkcz @kth5 FYI https://github.com/runlevel5/firefox-ppc64/releases/tag/FIREFOX_152_0_5_RELEASE_PPC64 can be cleanly applied with patch. I've converted the binary test WASM file to a WAT format.

@runlevel5
runlevel5 force-pushed the ppc64 branch 9 times, most recently from 84a9b76 to 38af16d Compare July 20, 2026 14:30
@runlevel5
runlevel5 force-pushed the ppc64 branch 6 times, most recently from 3183f45 to 43989b5 Compare July 22, 2026 11:28
@chmeeedalf

Copy link
Copy Markdown

Could someone with better Debian skills than I have build a Debian package, or tell me how to build one? I tried following the Build instructions in the PR description and it threw a very helpful "Error 2" with no visible reason.

@runlevel5

Copy link
Copy Markdown
Owner Author

Could someone with better Debian skills than I have build a Debian package, or tell me how to build one? I tried following the Build instructions in the PR description and it threw a very helpful "Error 2" with no visible reason.

@chmeeedalf FYI I have submitted a patch for Debian downstream package, but that's for Firefox 152. Debian has not yet bumped theirs to 153 or newer.

Could you please let me know which Debian distribution version you are using?

@runlevel5

Copy link
Copy Markdown
Owner Author

@chmeeedalf I've just updated the PR with full instructions for Debian. I got it compile successfully on Debian 13.5

@chmeeedalf

Copy link
Copy Markdown

@runlevel5 great, thanks. I was hoping I could build a .deb package for 14/testing, but probably not going to happen, because the Debian firefox-esr is 140.

@runlevel5

runlevel5 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

great, thanks. I was hoping I could build a .deb package for 14/testing, but probably not going to happen, because the Debian firefox-esr is 140.

@chmeeedalf I strongly believe Debian team will soon cut a dedicated git branch for the esr-153. While waiting, nothing stop you from building your own local Debian package. I highly encourage you to chime in https://salsa.debian.org/mozilla-team/firefox/-/merge_requests/17 to bring that work to the attention of the Debian team.

runlevel5 and others added 3 commits August 22, 2026 00:08
Adapted from work done by Raptor Engineering for chromium's vendored
SKIA. Gated to little-endian: the SSE-derived swizzle and permute
helpers assume the ppc64le vector-register byte order, so big-endian
falls back to the portable paths.

Co-authored-by: Timothy Pearson <tpearson@raptorengineering.com>
Gated to little-endian: the VSX kernels assume the ppc64le vector-register
byte order, so big-endian falls back to the portable C paths.

Assisted-by: Lance Albertson <lance@osuosl.org>
Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: Lance Albertson <lance@osuosl.org>
Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: James Zern <jzern@google.com>
@runlevel5

Copy link
Copy Markdown
Owner Author

@sharkcz is there anything left to do to get the patch officially adopted downstream with Fedora?

runlevel5 and others added 5 commits August 26, 2026 08:26
Based on the work done by Cameron Kaiser and Justin Hibbits
https://github.com/chmeeedalf/gecko-dev

Co-authored-by: Cameron Kaiser <classilla@floodgap.com>
Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com>
Assisted-by: Lance Albertson <lance@osuosl.org>
Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: Timothy Pearson <tpearson@solidsilicon.com>
Assisted-by: Dan Horák <dan@danny.cz>
Assisted-by: Hiếu Lê <modology@gmail.com>
Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Enable the SpiderMonkey JIT and WebAssembly on big-endian PPC64 (ELFv1
and ELFv2).

Co-authored-by: Cameron Kaiser <classilla@floodgap.com>
Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com>
Assisted-by: Lance Albertson <lance@osuosl.org>
Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: Timothy Pearson <tpearson@solidsilicon.com>
Assisted-by: Dan Horák <dan@danny.cz>
Assisted-by: Hiếu Lê <modology@gmail.com>
Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Assisted-by: Alexander Baldeck <alex.bldck@gmail.com>
The build system defines HAVE_PLATFORM_GHASH for both PPC64 endians,
but the POWER8 vpmsumd GHASH implementation was compiled out on
big-endian, leaving platform_ghash_support, gcm_HashInit_hw,
gcm_HashWrite_hw and gcm_HashZeroX_hw unresolved and freebl failing
to link.

Make ghash-ppc.c endian-correct instead of stubbing it out. GNU C
vector element indexing follows memory order, so the doubleword
element reads, the pair constructors and the vec_splat index of the
most-significant byte must mirror on big-endian, while vec_xl_be,
vec_xst_be and the whole-register operations (vpmsumd, vec_sll,
vec_rl, xor) already produce identical register values on both
endians. The new USE_PPC_CRYPTO_GHASH define drops the little-endian
restriction for ghash-ppc.c only; the other USE_PPC_CRYPTO consumers
remain little-endian.

Also give gcm.c the same -mcrypto/-maltivec cflags as ghash-ppc.c in
gcm.gyp. gcmHashContext's vec_u64 x/h fields are gated on
__ALTIVEC__/__VSX__, so without this gcm.c and ghash-ppc.c disagree on
sizeof(gcmHashContext) and every field after x/h -- including the
ghash_mul function pointer -- lands at a different offset in each
translation unit, corrupting the hardware GHASH dispatch. This is not
endian-specific: it affects ppc64le the same way whenever
disable_crypto_vsx doesn't already imply matching flags elsewhere.
Found by crashing on a real TLS 1.3 handshake (AES-GCM record decrypt)
in a full browser build, not just the isolated GHASH unit tests.

Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=2027768
Big-endian used to flip the OS_RGBA surface format synonyms to the
A8R8G8B8 memory layout, which Skia has no color type for, so surface
creation hit MOZ_DIAGNOSTIC_CRASH("A8R8G8B8 unsupported by Skia") as
soon as anything was drawn. Keep the synonyms pinned to the B8G8R8A8
memory layout on both endians so the whole pixel pipeline operates on
one layout, and convert for the display server at the compositor
boundary instead.

Skia's SkPMColor channel shifts describe a little-endian uint32_t
view of that layout, so on big-endian a packed color value and the
in-memory destination pixels disagree on byte order. Introduce
BE_CONVERT (a no-op on little-endian) and apply it at the scalar
blitter load/store boundaries: solid fills, the blit_row_color32
kernel, A8 glyph masks, LCD16 subpixel text, BW masks, the black
blitter, and the direct-blit fill value. Alpha extraction always uses
the unconverted value. The SurfaceFormatBit shifts mirror on
big-endian so channel accessors keep addressing the same bytes, and
kARGBAlphaOffset moves to byte 0 for the RGBX verification.

Software WebRender resolves frames in the B8G8R8A8 memory layout, but
X11 consumes native-endian 32-bit pixel values, so swizzle the dirty
region to the A8R8G8B8 layout when handing the buffer to the widget.
Skia-drawn image surfaces get the inverse reorder in imgFrame before
they enter the surface cache.

Known gap: SkRasterPipeline's load/store stages and the headless
screenshot readback still assume little-endian and are unchanged.
Define GP_PLAT_ppc64_linux so the profiler uses the real Linux sampler
instead of platform-noop.cpp, and capture PC/SP/FP/LR from the signal
ucontext (NIA, r1, r31, LR). A new UNWINDING_REGS_HAVE_LR register-set
variant forwards LR to JS::ProfilingFrameIterator, whose PPC64 support
already landed with the wasm profiling work.

Native stack walking uses a dedicated backchain walker: the PPC64 ELF
ABIs require every function that allocates a stack frame to store the
caller's stack pointer at *(sp) and its return address at
caller_sp + 16, at every optimization level, so the native call stack
can be recovered without unwind tables or LUL support. The walk is
bounds- and alignment-checked against the sampled thread's stack and
stops at JIT frames, which are covered by the JS frame merging instead.
The walker needs no initialization, so it also serves the fast-init
path used for backtrace samples.

shared-libraries-linux.cc is enabled for symbolication, and the
sysfs-based CPU-frequency counter compiles on the no-LUL branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants