ppc_testing_main.cc and test_suite_main.cc each defined the apu/gpu backend-selection cvars, which are also defined in cpu/testing/test_backend_cvars.cc (compiled into both test targets). With XENIA_BUILD_TESTS=ON this produced "ld: duplicate symbol cvars::apu / cvars::gpu" and neither xenia-cpu-tests nor xenia-cpu-ppc-tests would link.
Remove the redundant definitions from the two mains; test_backend_cvars.cc remains the single definition site.
PPC lwarx/stwcx (RESERVED_LOAD/STORE) was the largest a64 backend CPU consumer in on-device profiling (~30%): every guest atomic routed through the generic GuestToHostThunk -- a 448-byte q4-q31 vector spill plus an FPCR restore -- into C helpers that emulated the reservation bitmap with compare-exchange retry loops.
On hosts with FEAT_LSE (all Apple arm64) emit dedicated GPR-only leaf thunks that use single LSE atomics (ldsetal/ldclral/casal) and are reached with a plain BLR. The a64 register allocator only keeps live guest values in x22-x28 and v4-v31, so a GPR-only leaf preserves all guest state without the vector spill or FPCR write. Hosts without FEAT_LSE keep the existing C-helper + CallNativeSafe path.
Behavior is identical to the x64 backend and the previous C helpers (verified atomic-by-atomic); memory ordering is unchanged, as the PPC frontend still emits dmb ish around each operation. Validated on the arm64 host: xenia-cpu-tests [atomic] (5/5) and xenia-cpu-ppc-tests instr_stwcx/instr_lxarx (8/8).
Match the macOS UploadBufferPool ceiling (kUploadBufferPoolMaxBytes) on
iOS, bumping it from 128 MB to 512 MB. On a cold, batched, texture-upload
heavy frame, every materialization in the frame's deferred command buffer
needs its own staging buffers (dest + constants + source + repack scratch)
simultaneously, so the size-keyed best-fit pool grows to a high-water mark
that exceeded the old 128 MB cap and fell through to per-upload transient
allocations. Raising the cap lets the warm pool retain and reuse those
buffers across frames instead of re-allocating, eliminating the per-frame
newBufferWithLength churn.
This only raises the ceiling; the pool still grows lazily to its actual
high-water mark. kScaledResolveRetiredMaxBytes stays at 64 MB on iOS
(256 MB on macOS), so the XE_PLATFORM_IOS split is retained.