Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5

# Compiled locally rather than checked in (unlike the take_strings-*
# binaries) since it has no arch-specific dependencies beyond libc.
- name: Build bench fixtures
working-directory: bench/testdata
run: cc -O2 -o llsc_tzconvert_bench llsc_tzconvert_bench.c

# Generate the codspeed.yml for this Valgrind version. The script derives
# the version label from `valgrind --version`, so each matrix job emits its
# own config (e.g. valgrind.codspeed / valgrind-3.26.0 / valgrind-3.25.1).
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2568,3 +2568,9 @@ test-suite.log

# Capstone build install prefix (built from the third_party/capstone submodule)
/.capstone

# fake CodSpeed benchmark fixture binary (compiled from testdata/llsc_tzconvert_bench.c)
/bench/testdata/llsc_tzconvert_bench

# python bytecode cache left behind when something imports generate_config.py as a module
/bench/__pycache__/
7 changes: 7 additions & 0 deletions bench/generate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
"testdata/take_strings-aarch64 varbinview_non_null",
"echo Hello, World!",
"python3 testdata/test.py",
"stress-ng --cpu 1 --cpu-ops 10",
"stress-ng --cpu 4 --cpu-ops 10",
Comment thread
not-matthias marked this conversation as resolved.
# Repeated localtime()/__tz_convert() calls: the guest CAS loop
# (outline-atomics LDAXR/STXR helper) that triggered the ARM64
# fallback-LL/SC livelock fix. Built by the "Build bench fixtures" CI
# step from testdata/llsc_tzconvert_bench.c (not checked in as a binary).
"testdata/llsc_tzconvert_bench 5000",
]

# Callgrind configurations: (extra args, config name, requires_codspeed). The
Expand Down
3 changes: 3 additions & 0 deletions bench/testdata/llsc_tzconvert_bench.c
Git LFS file not shown
30 changes: 25 additions & 5 deletions coregrind/m_machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,12 +844,27 @@ static Bool VG_(parse_cpuinfo)(void)

#if defined(VGP_arm64_linux)

/* Check to see whether we are running on a Cavium core, and if so auto-enable
the fallback LLSC implementation. See #369459. */
/* Check /proc/cpuinfo for cores whose exclusive monitor cannot be relied on
for guest LDXR/STXR passthrough, and auto-enable the fallback (CAS-based)
LL/SC implementation for them:
- Cavium/ThunderX (implementer 0x43): strict monitor, see #369459.
- CODSPEED: Cortex-A72 (part 0xd08). Under instrumentation the
LDAXR..STXR window spans two translations with hundreds of host
instructions in between (an AArch64 conditional branch always ends a
superblock, guest_arm64_toIR.c dis_ARM64_branch_etc), so guest progress
depends on the monitor surviving all of that. Observed live (2026-07,
intermittent ARM64 callgrind CI hangs): a sticky per-run state where an
uncontended glibc CAS retries ~1M/s forever at 100% CPU, and retry
storms silently inflate callgrind-measured costs at atomic sites.
The fallback records the LL value and implements SC as a real host CAS,
independent of the hardware monitor. On unlisted cores
--sim-hints=fallback-llsc still force-enables it. */

static Bool VG_(parse_cpuinfo)(void)
{
const char *search_Cavium_str = "CPU implementer\t: 0x43";
const char *search_Cavium_str = "CPU implementer\t: 0x43";
const char *search_ARM_impl = "CPU implementer\t: 0x41";
const char *search_A72_part = "CPU part\t: 0xd08";

Int n, fh;
SysRes fd;
Expand Down Expand Up @@ -890,8 +905,13 @@ static Bool VG_(parse_cpuinfo)(void)
file_buf[num_bytes] = '\0';
VG_(close)(fh);

/* Parse file */
if (VG_(strstr)(file_buf, search_Cavium_str) != NULL)
/* Parse file. Cortex-A72 = ARM Ltd (0x41) part 0xd08; require both so an
unrelated implementer reusing the part value does not match. (Both
strings anywhere in the file is close enough: a false positive only
enables the fallback, which is the safe direction.) */
if (VG_(strstr)(file_buf, search_Cavium_str) != NULL
|| (VG_(strstr)(file_buf, search_ARM_impl) != NULL
&& VG_(strstr)(file_buf, search_A72_part) != NULL))
vai.arm64_requires_fallback_LLSC = True;

VG_(free)(file_buf);
Expand Down
Loading