4848//! * if I/O can be isolated to separate profiling events, and doesn't impact
4949//! execution in a more subtle way (see below), the deterministic parts of
5050//! the program can still be profiled with high accuracy
51- //! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, thread scheduling)
51+ //! * intentional uses of randomness may change execution paths, though for
52+ //! cryptographic operations specifically, "constant time" implementations
53+ //! are preferred / necessary (in order to limit an external observer's
54+ //! ability to infer secrets), so they're not as much of a problem
55+ //! * even otherwise-deterministic machine-local communication (to e.g. system
56+ //! services or drivers) can behave unpredictably (especially under load)
57+ //! * while we haven't observed this in the wild yet, it's possible for
58+ //! file reads/writes to be split up into multiple smaller chunks
59+ //! (and therefore take more userspace instructions to fully read/write)
60+ //! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, timers)
5261//! * ASLR ("Address Space Layout Randomization"), may be provided by the OS for
5362//! security reasons, or accidentally caused through allocations that depend on
5463//! random data (even as low-entropy as e.g. the base 10 length of a process ID)
6574//! ASLR and ASLR-like effects, making the entire program more sensitive
6675//! * the default hasher is randomized, and while `rustc` doesn't use it,
6776//! proc macros can (and will), and it's harder to disable than Linux ASLR
68- //! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
69- //! has a 10 second "purge timer", which can introduce an ASLR-like effect,
70- //! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
77+ //! * most ways of measuring time will inherently never perfectly align with
78+ //! exact points in the program's execution, making time behave like another
79+ //! low-entropy source of randomness - this also means timers will elapse at
80+ //! unpredictable points (which can further impact the rest of the execution)
81+ //! * this includes the common thread scheduler technique of preempting the
82+ //! currently executing thread with a periodic timer interrupt, so the exact
83+ //! interleaving of multiple threads will likely not be reproducible without
84+ //! special OS configuration, or tools that emulate a deterministic scheduler
85+ //! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
86+ //! has a 10 second "purge timer", which can introduce an ASLR-like effect,
87+ //! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
7188//! * hardware flaws (whether in the design or implementation)
7289//! * hardware interrupts ("IRQs") and exceptions (like page faults) cause
7390//! overcounting (1 instruction per interrupt, possibly the `iret` from the
@@ -525,10 +542,10 @@ mod hw {
525542 } else {
526543 asm ! (
527544 // Dummy `cpuid(0)` to serialize instruction execution.
528- "xor eax, eax" ,
545+ "xor % eax, % eax" , // Intel syntax: "xor eax, eax"
529546 "cpuid" ,
530547
531- "mov ecx, {rdpmc_ecx:e}" ,
548+ "mov {rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {rdpmc_ecx:e}"
532549 "rdpmc" ,
533550 rdpmc_ecx = in( reg) reg_idx,
534551 out( "eax" ) lo,
@@ -539,6 +556,12 @@ mod hw {
539556 out( "ecx" ) _,
540557
541558 options( nostack) ,
559+
560+ // HACK(eddyb) LLVM 9 and older do not support modifiers
561+ // in Intel syntax inline asm; whenever Rust minimum LLVM
562+ // version becomes LLVM 10, remove and replace above
563+ // instructions with Intel syntax version (from comments).
564+ options( att_syntax) ,
542565 ) ;
543566 }
544567 }
@@ -556,14 +579,14 @@ mod hw {
556579 unsafe {
557580 asm ! (
558581 // Dummy `cpuid(0)` to serialize instruction execution.
559- "xor eax, eax" ,
582+ "xor % eax, % eax" , // Intel syntax: "xor eax, eax"
560583 "cpuid" ,
561584
562- "mov ecx, {a_rdpmc_ecx:e}" ,
585+ "mov {a_rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {a_rdpmc_ecx:e}"
563586 "rdpmc" ,
564- "mov {a_rdpmc_eax:e}, eax" ,
565- "mov {a_rdpmc_edx:e}, edx" ,
566- "mov ecx, {b_rdpmc_ecx:e}" ,
587+ "mov %eax, {a_rdpmc_eax:e}" , // Intel syntax: "mov {a_rdpmc_eax:e}, eax"
588+ "mov %edx, {a_rdpmc_edx:e}" , // Intel syntax: "mov {a_rdpmc_edx:e}, edx"
589+ "mov {b_rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {b_rdpmc_ecx:e}"
567590 "rdpmc" ,
568591 a_rdpmc_ecx = in( reg) a_reg_idx,
569592 a_rdpmc_eax = out( reg) a_lo,
@@ -577,6 +600,12 @@ mod hw {
577600 out( "ecx" ) _,
578601
579602 options( nostack) ,
603+
604+ // HACK(eddyb) LLVM 9 and older do not support modifiers
605+ // in Intel syntax inline asm; whenever Rust minimum LLVM
606+ // version becomes LLVM 10, remove and replace above
607+ // instructions with Intel syntax version (from comments).
608+ options( att_syntax) ,
580609 ) ;
581610 }
582611 (
@@ -786,10 +815,17 @@ mod hw {
786815 let mut _tmp: u64 = 0 ;
787816 unsafe {
788817 asm ! (
789- "lock xadd qword ptr [{atomic}], {tmp}" ,
818+ // Intel syntax: "lock xadd [{atomic}], {tmp}"
819+ "lock xadd {tmp}, ({atomic})" ,
790820
791821 atomic = in( reg) & mut atomic,
792822 tmp = inout( reg) _tmp,
823+
824+ // HACK(eddyb) LLVM 9 and older do not support modifiers
825+ // in Intel syntax inline asm; whenever Rust minimum LLVM
826+ // version becomes LLVM 10, remove and replace above
827+ // instructions with Intel syntax version (from comments).
828+ options( att_syntax) ,
793829 ) ;
794830 }
795831
0 commit comments