2

CPUID can be used as a serializing instruction as described here and here. What is the minimal/simplest asm syntax to use it in that way in C++?

// Is that enough?
// What to do with registers and memory?
// Is volatile necessary?
asm volatile("CPUID":::);
MSalters
  • 167,472
  • 9
  • 150
  • 334
Vincent
  • 53,995
  • 57
  • 182
  • 359
  • 3
    Technically, you can't do it at all since inline assembly is a compiler-specific thing that doesn't exist in standard C++. While we could *guess* which compiler you're most likely using, always include that information when asking questions about inline assembly. Also mentioning target ISA is usually a good idea, even it if also can be guessed in this case. – Some programmer dude Jan 29 '18 at 13:39
  • 3
    Use a builtin instead of asm. `cpuid` overwrites registers, at the very least you need to list `eax`,`ebx`,`ecx` and `edx` as clobbers. Yes, `volatile` is necessary. – Jester Jan 29 '18 at 13:39
  • 7
    `#include ` and use the `__cpuid()` function. – Kelvin Sherlock Jan 29 '18 at 13:41
  • What do you need it for? – Maxim Egorushkin Jan 29 '18 at 13:46
  • 1
    If you need to serialize `rdtsc`, use `lfence`. It's guaranteed by Intel to work (at least on Intel CPUs). See https://stackoverflow.com/questions/38994549/is-intels-timestamp-reading-asm-code-example-using-two-more-registers-than-are. (However, [on AMD it seems you need `mfence` instead of `lfence`](https://stackoverflow.com/questions/12631856/difference-between-rdtscp-rdtsc-memory-and-cpuid-rdtsc#comment84001167_12634857), so `cpuid` is apparently more portable) – Peter Cordes Jan 29 '18 at 14:48

1 Answers1

1

Is there a reason you're not using the fence operations? If the goal is to serialize a section of code you can do something like

    asm __volatile__ (
" mfence \n"
" lfence \n"
);
Your code
asm __volatile__ (
" mfence \n"
" lfence \n"
);
Darakian
  • 599
  • 1
  • 8
  • 22
  • 1
    The intel manual says: _"MFENCE does not serialize the instruction stream."_ – Jester Jan 29 '18 at 14:01
  • "Perform a serializing operation on all load-from-memory and store-to-memory instructions that were issued prior to this instruction. Guarantees that every memory access that precedes, in program order, the memory fence instruction is globally visible before any memory instruction which follows the fence in program order." https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=fence&expand=3424 – Darakian Jan 29 '18 at 14:06
  • Yes, but that only deals with memory operations. _"Non-privileged serializing instructions -- CPUID, IRET, and RSM._" and _"The following instructions are memory-ordering instructions, not serializing instructions. These drain the data memory subsystem. They do not serialize the instruction execution stream. Non-privileged memory-ordering instructions -- SFENCE, LFENCE, and MFENCE."_ – Jester Jan 29 '18 at 14:07
  • 1
    @Jester: `lfence` is now (or will be) officially documented as serializing, following years of that being an implementation detail, but still seeing some Intel docs recommend or at least use `lfence; rdtsc`. At least *some* good came out of Spectre... (I'm not 100% sure it's as strongly serializing as `cpuid`, though). But anyway, you're right that `mfence` isn't serializing on the instruction stream, on paper or in practice. Using both `lfence` and `mfence` back to back doesn't seem useful. – Peter Cordes Jan 29 '18 at 14:23
  • Correction: `lfence` is serializing *on the instruction stream*, without flushing the store buffer. It's sufficient for `lfence; rdtsc`. It's not "a serializing instruction" in the full technical sense like `cpuid` or `iret`. And `mfence` is serializing on AMD according to documentation, and in practice also on some Intel CPUs like Skylake, possibly a microcode update to fix an erratum strengthened it to be much stronger than the Intel manual guarantees: [Are loads and stores the only instructions that gets reordered?](//stackoverflow.com/a/50496379) – Peter Cordes Jan 29 '19 at 23:10
  • And also: [Is LFENCE serializing on AMD processors?](//stackoverflow.com/q/51844886) yes, with Spectre mitigation active the relevant MSR will be set so LFENCE blocks speculative execution like on Intel. – Peter Cordes Jan 29 '19 at 23:11
  • Anyway, you forgot `"memory"` clobbers, so compile-time reordering of code into / out of the serialized block is still possible. – Peter Cordes Jan 29 '19 at 23:12