Skip to content

Minor tweaks to the measureme::counters module. #147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 1, 2021
Merged
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
60 changes: 48 additions & 12 deletions measureme/src/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,16 @@
//! * if I/O can be isolated to separate profiling events, and doesn't impact
//! execution in a more subtle way (see below), the deterministic parts of
//! the program can still be profiled with high accuracy
//! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, thread scheduling)
//! * intentional uses of randomness may change execution paths, though for
//! cryptographic operations specifically, "constant time" implementations
//! are preferred / necessary (in order to limit an external observer's
//! ability to infer secrets), so they're not as much of a problem
//! * even otherwise-deterministic machine-local communication (to e.g. system
//! services or drivers) can behave unpredictably (especially under load)
//! * while we haven't observed this in the wild yet, it's possible for
//! file reads/writes to be split up into multiple smaller chunks
//! (and therefore take more userspace instructions to fully read/write)
//! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, timers)
//! * ASLR ("Address Space Layout Randomization"), may be provided by the OS for
//! security reasons, or accidentally caused through allocations that depend on
//! random data (even as low-entropy as e.g. the base 10 length of a process ID)
Expand All @@ -65,9 +74,17 @@
//! ASLR and ASLR-like effects, making the entire program more sensitive
//! * the default hasher is randomized, and while `rustc` doesn't use it,
//! proc macros can (and will), and it's harder to disable than Linux ASLR
//! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
//! has a 10 second "purge timer", which can introduce an ASLR-like effect,
//! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
//! * most ways of measuring time will inherently never perfectly align with
//! exact points in the program's execution, making time behave like another
//! low-entropy source of randomness - this also means timers will elapse at
//! unpredictable points (which can further impact the rest of the execution)
//! * this includes the common thread scheduler technique of preempting the
//! currently executing thread with a periodic timer interrupt, so the exact
//! interleaving of multiple threads will likely not be reproducible without
//! special OS configuration, or tools that emulate a deterministic scheduler
//! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
//! has a 10 second "purge timer", which can introduce an ASLR-like effect,
//! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
//! * hardware flaws (whether in the design or implementation)
//! * hardware interrupts ("IRQs") and exceptions (like page faults) cause
//! overcounting (1 instruction per interrupt, possibly the `iret` from the
Expand Down Expand Up @@ -525,10 +542,10 @@ mod hw {
} else {
asm!(
// Dummy `cpuid(0)` to serialize instruction execution.
"xor eax, eax",
"xor %eax, %eax", // Intel syntax: "xor eax, eax"
"cpuid",

"mov ecx, {rdpmc_ecx:e}",
"mov {rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {rdpmc_ecx:e}"
"rdpmc",
rdpmc_ecx = in(reg) reg_idx,
out("eax") lo,
Expand All @@ -539,6 +556,12 @@ mod hw {
out("ecx") _,

options(nostack),

// HACK(eddyb) LLVM 9 and older do not support modifiers
// in Intel syntax inline asm; whenever Rust minimum LLVM
// version becomes LLVM 10, remove and replace above
// instructions with Intel syntax version (from comments).
options(att_syntax),
);
}
}
Expand All @@ -556,14 +579,14 @@ mod hw {
unsafe {
asm!(
// Dummy `cpuid(0)` to serialize instruction execution.
"xor eax, eax",
"xor %eax, %eax", // Intel syntax: "xor eax, eax"
"cpuid",

"mov ecx, {a_rdpmc_ecx:e}",
"mov {a_rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {a_rdpmc_ecx:e}"
"rdpmc",
"mov {a_rdpmc_eax:e}, eax",
"mov {a_rdpmc_edx:e}, edx",
"mov ecx, {b_rdpmc_ecx:e}",
"mov %eax, {a_rdpmc_eax:e}", // Intel syntax: "mov {a_rdpmc_eax:e}, eax"
"mov %edx, {a_rdpmc_edx:e}", // Intel syntax: "mov {a_rdpmc_edx:e}, edx"
"mov {b_rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {b_rdpmc_ecx:e}"
"rdpmc",
a_rdpmc_ecx = in(reg) a_reg_idx,
a_rdpmc_eax = out(reg) a_lo,
Expand All @@ -577,6 +600,12 @@ mod hw {
out("ecx") _,

options(nostack),

// HACK(eddyb) LLVM 9 and older do not support modifiers
// in Intel syntax inline asm; whenever Rust minimum LLVM
// version becomes LLVM 10, remove and replace above
// instructions with Intel syntax version (from comments).
options(att_syntax),
);
}
(
Expand Down Expand Up @@ -786,10 +815,17 @@ mod hw {
let mut _tmp: u64 = 0;
unsafe {
asm!(
"lock xadd qword ptr [{atomic}], {tmp}",
// Intel syntax: "lock xadd [{atomic}], {tmp}"
"lock xadd {tmp}, ({atomic})",

atomic = in(reg) &mut atomic,
tmp = inout(reg) _tmp,

// HACK(eddyb) LLVM 9 and older do not support modifiers
// in Intel syntax inline asm; whenever Rust minimum LLVM
// version becomes LLVM 10, remove and replace above
// instructions with Intel syntax version (from comments).
options(att_syntax),
);
}

Expand Down