Intel 64和IA-32架构定义了若干条串行化指令。这些指令迫使处理器在下一条指令被取并执行前,完成所有先前的指令对标志、寄存器、以及存储器的修改,并将所有被缓存的写注入到存储器中。比如,当一条MOV指令对控制寄存器用于将一个新的值载入到CR0控制寄存器中,以允许保护模式时,处理器必须在它进入保护模式之前执行一次串行化操作。此串行化操作确保当处理器处于实地址模式下时被启动的所有操作在切换到保护模式之前被完成。
串行化指令的概念以奔腾处理器被引入到IA-32架构中,为了支持并行指令执行。串行化指令对于Intel486以及更早的处理器——那些没有实现并行指令执行的处理器而言没有意义。
要注意,在P6和最近处理器家族上的串行化指令的执行限制了投机执行,因为被投机执行指令的结果被丢弃。以下指令是串行化指令:
1、特权串行化指令——INVD、INVEPT、INVLPG、INVVPID、LGDT、LIDT、LLDT、LTR、MOV(用于写控制寄存器,除了MOV CR8以外)、MOV(写到调试寄存器)、WBINVD、以及WRMSR。
2、非特权串行化指令——CPUID、IRET、RSM。
当处理器串行化指令执行时,它确保所有未决的存储器事务在它执行下一条指令之前被完成(包括被存储到其存储缓存的写)。没有任何东西能通过串行化指令,并且一条串行化指令能通过任何其它指令(读、写、取指令、或I/O)。比如CPUID可以在任一特权级上被执行以串行化指令执行,这条指令在程序流上不会有任何效果,除了EAX、EBX、ECX和EDX寄存器被修改。
以下指令是存储器次序指令,而不是串行化指令。这些排空数据存储器子系统。它们并不串行化指令执行流:
1、非特权存储器次序指令——SFENCE、LFENCE、和MFENCE。
SFENCE、LFENCE、和MFENCE指令提供了控制存储器加载和存储的串行化的更粗的粒度(见8.2.5小节)。
以下额外的信息只对串行化指令有价值:
1、当处理器串行化指令执行时,它并不写回在数据Cache中被修改数据的内容到外部存储器。软件可以通过执行SBINVD指令,一条串行化指令,来迫使被修改的数据写回。WBINVD完成所花费的时间和周期数会根据不同Cache层级的尺寸以及其它因素而有所不同。作为一个结果,WBINVD指令的使用会对中断/事件响应时间有影响。
2、当一条允许或禁止分页的指令(即改变控制寄存器CR0的PG标志)被执行时,该指令后面应该跟着一条跳转指令。该跳转指令的目标指令以新设置的PG标志(即分页被允许或禁止)来获取,但跳转指令本身以先前的设置被获取。奔腾4、Intel至强以及P6家族处理器不需要对寄存器CR0的修改后跟着一条跳转指令(因为在奔腾4、Intel至强以及P6家族处理器中,对CR0使用MOV来修改完全是串行化的)。
3、每当一条指令被执行以改变CR3的内容时,并且分页被允许时,下一条指令使用相应于CR3的新值的翻译表被取。从而,下一条指令以及按顺序的下一条紧跟着的指令应该基于CR3的新值有一个映射。(TLB中的全局条目不会被无效化,见4.10.4小节)
4、奔腾处理器以及其后面的处理器家族使用分支预测技术,通过在分支指令被执行之前预取这条分支指令的目的来提升性能。因此,当一条分支指令被执行时,指令执行无法确定被串行化。