This is a discussion on Serializing instructions - ASM x86 ASM 370 ; Note: cross-posted to comp.lang.asm.x86 and comp.arch Hello everyone, The ChangeLog for Linux kernel 126.96.36.199 states: commit e4a835d383dc58212a9648ef905cb8087e0c4ab2 Author: Arjan van de Ven <arjan(at)linux.intel.com> Date: Mon Dec 11 21:45:01 2006 +0100 [PATCH] x86-64: Mark rdtsc as sync only for netburst, not ...
Note: cross-posted to comp.lang.asm.x86 and comp.arch
The ChangeLog for Linux kernel 188.8.131.52 states:
Author: Arjan van de Ven <arjan(at)linux.intel.com>
Date: Mon Dec 11 21:45:01 2006 +0100
[PATCH] x86-64: Mark rdtsc as sync only for netburst, not for core2
On the Core2 cpus, the rdtsc instruction is not serializing (as defined
in the architecture reference since rdtsc exists) and due to the deep
speculation of these cores, it's possible that you can observe time go
backwards between cores due to this speculation. Since the kernel
already deals with this with the SYNC_RDTSC flag, the solution is
simple, only assume that the instruction is serializing on family 15...
The price one pays for this is a slightly slower gettimeofday (by a
dozen or two cycles), but that increase is quite small to pay for a
really-going-forward tsc counter.
I don't understand the part where he says "the solution is simple, only
assume that the instruction is serializing on family 15..."
He seems to imply that RDTSC is serializing on NetBurst?? But, AFAIU,
RDTSC has *never* been a serializing instruction.
Why would Linux assume that RDTSC is serializing on family 15?
Volume 3A: System Programming Guide states
7.4 SERIALIZING INSTRUCTIONS
The Intel 64 and IA-32 architectures define several serializing
instructions. These instructions force the processor to complete all
modifications to flags, registers, and memory by previous instructions
and to drain all buffered writes to memory before the next instruction
is fetched and executed. For example, when a MOV to control register
instruction is used to load a new value into control register CR0 to
enable protected mode, the processor must perform a serializing
operation before it enters protected mode. This serializing operation
insures that all operations that were started while the processor was in
real-address mode are completed before the switch to protected mode is made.
The concept of serializing instructions was introduced into the IA-32
architecture with the Pentium processor to support parallel instruction
execution. Serializing instructions have no meaning for the Intel486 and
earlier processors that do not implement parallel instruction execution.
It is important to note that executing of serializing instructions on P6
and more recent processor families constrain speculative execution
because the results of speculatively executed instructions are
discarded. The following instructions are serializing instructions:
o Privileged serializing instructions - MOV (to control register, with
the exception of MOV CR8), MOV (to debug register), WRMSR, INVD, INVLPG,
WBINVD, LGDT, LLDT, LIDT, and LTR.
o Non-privileged serializing instructions - CPUID, IRET, and RSM.
When the processor serializes instruction execution, it ensures that all
pending memory transactions are completed (including writes stored in
its store buffer) before it executes the next instruction. Nothing can
pass a serializing instruction and a serializing instruction cannot pass
any other instruction (read, write, instruction fetch, or I/O). For
example, CPUID can be executed at any privilege level to serialize
instruction execution with no effect on program flow, except that the
EAX, EBX, ECX, and EDX registers are modified.