fn check_for_zen_speclockmap()

in reverie-ptrace/src/validation.rs [384:430]


fn check_for_zen_speclockmap() -> Result<(), PmuValidationError> {
    // When the SpecLockMap optimization is not disabled, rr will not work
    // reliably (e.g. it would work fine on a single process with a single
    // thread, but not more). When the optimization is disabled, the
    // perf counter for retired lock instructions of type SpecLockMapCommit
    // (on PMC 0x25) stays at 0.
    // See more details at https://github.com/rr-debugger/rr/issues/2034.

    // 0x25 == RETIRED_LOCK_INSTRUCTIONS - Counts the number of retired locked instructions
    // + 0x08 == SPECLOCKMAPCOMMIT
    let mut attr = init_perf_event_attr(perf::perf_type_id_PERF_TYPE_RAW, 0x510825, false);

    let fd = start_counter(0, -1, &mut attr, None)?;

    let val = 20_usize;
    let to_add = 22_usize;
    let count = read_counter(&fd)?;

    // A lock add is known to increase the perf counter we're looking at.
    #[cfg(not(feature = "llvm_asm"))]
    unsafe {
        let _prev: usize;
        core::arch::asm!(
            "lock",
            "xadd [{}], {}",
            in(reg) val,
            inout(reg) to_add => _prev,
        )
    }

    #[cfg(feature = "llvm_asm")]
    #[allow(deprecated)]
    unsafe {
        let _prev: usize;
        llvm_asm!("lock; xaddq $2, $1"
            : "=r" (_prev), "+*m" (&val)
            : "0" (to_add)
            : "memory"
            : "volatile");
    }

    if read_counter(&fd)? != count {
        Err(PmuValidationError::AmdSpecLockMapShouldBeDisabled)
    } else {
        Ok(())
    }
}