作者:花琦1979 | 来源:互联网 | 2022-10-27 20:03
这与这个问题有关
但是考虑一下,在现代的英特尔CPU上,SEC阶段是以微码实现的,这意味着将进行检查,从而使用烧入的密钥来验证PEI ACM上的签名。如果不匹配,则需要执行某些操作;如果不匹配,则需要执行其他操作。假定这是作为MSROM过程实现的,则必须有一种分支方式,但是鉴于MSROM指令没有RIP。
通常,当一个分支错误地预测到将要采取的指令然后退出时,ROB将检查异常代码,并因此将指令长度添加到ROB行的RIP或仅使用下一个ROB条目的IP,这将导致前端在分支预测更新中恢复到该地址。有了BOB,此功能现在已借给跳转执行单元。显然,这与MSROM例程不可能发生,因为前端与此无关。
我的想法是,有一条特定的跳转指令,只有MSROM例程才能发出,它会跳转到MSROM中的其他位置,并且可以进行配置,以便始终预测不采用MSROM分支指令,并且在分支执行单元遇到此指令时指令并执行分支,它会产生异常代码,并可能将特殊的跳转目标连接到它,并且在退出时会发生异常。另外,执行单元可以处理它,并且可以使用BOB,但我的印象是BOB由分支指令RIP索引,然后还存在这样一个事实,即通常会在退休时处理生成MSROM代码的异常。分支错误预测不需要我不认为的MSROM,而是所有操作都在内部执行。
1> Peter Cordes..:
微代码分支显然很特殊。
根据安迪·格莱夫(Andy Glew)对原始P6的描述,英特尔的P6和SnB系列不支持微代码分支的动态预测(REP有什么设置?)。鉴于SnB-family-string rep
指令的性能相似,我认为此PPro事实甚至适用于最新的Skylake / CoffeeLake CPU 1。
但是,对微码分支的错误预测有一个惩罚,因此它们是静态预测的。(这就是为什么rep movsb
对于ECX中的低/中/高计数,启动成本以5个周期为增量进行调整,以及对齐与未对齐的原因。)
微码指令在uop缓存中占据了整行。 当它到达IDQ的最前面时,它将接管发出/重命名阶段,直到完成发出微代码联动为止。 (有关更多详细信息,另请参见如何在指令周期内执行微代码?以及一些类似perf事件描述的证据idq.dsb_uops
表明,IDQ可以从uop缓存中接受新的uops,而问题/重命名阶段正在从微码序列器中读取数据)
对于rep
-string指令,我认为循环的每次迭代都必须在前端实际发出,而不仅仅是在后端内部循环并重用这些微指令。因此,这涉及来自OoO后端的反馈,以找出指令何时完成执行。
我不知道当问题/重命名切换到从MS-ROM而不是IDQ读取uops时会发生什么的细节。
即使每个uop都没有自己的RIP(属于单个微代码指令),但我猜想分支错误预测检测机制的工作原理与普通分支类似。
rep movs
某些情况下,某些CPU上的设置时间似乎以5个周期为步长(小与大,对齐等)。如果这些是来自微码分支的错误预测,则这似乎意味着该错误预测惩罚是固定数量的循环,除非这是的特殊情况rep movs
。可能是因为OoO后端可以跟上前端吗?从MS-ROM读取比从uop缓存读取甚至更能缩短路径,从而降低了丢失率。
对一些可能的OoO执行程序进行实验rep movsb
(例如,使用两条相关的imul
指令链),以查看它是否(部分)像它们那样对它们进行序列化lfence
将是很有趣的。我们希望不是,但是要实现ILP,imul
必须在不等待后端耗尽的情况下发出以后的命令。
我在Skylake(i7-6700k)上进行了一些实验。初步结果:95字节及更少字节的副本大小便宜,并且被IMUL链的延迟所掩盖,但它们基本上完全重叠。 96字节或更多字节的副本大小会耗尽RS,从而将两个IMUL链串行化。 不论是rep movsb
RCX = 95 vs. 96还是rep movsd
RCX = 23 vs. 24都是无关紧要的。如果我有时间,我会发布更多详细信息。
测量了“使RS吸水”的行为,rs_events.empty_end:u
偶数变为1 / rep movsb
而不是〜0.003。 other_assists.any:u
为零,因此它不是“助手”,或者至少不算作1。
如果微代码分支不支持通过BoB进行快速恢复,也许涉及的任何uop只会在退休时检测到错误的预测?96字节阈值可能是某些替代策略的临界点。RCX = 0也会耗尽RS,大概是因为这也是一种特殊情况。
测试会很有趣rep scas
(它不支持快速字符串,只是慢而笨拙的微代码。)
英特尔1994年的Fast Strings专利描述了P6中的实现。它没有IDQ(因此在阶段之间确实具有缓冲区和uop缓存的现代CPU会有一些变化是很有意义的),但是它们描述的避免分支的机制很简洁,也许仍然用于现代ERMSB:第一次n
复制迭代是针对后端的uops谓词,因此可以无条件地发出它们。还有一个uop会导致后端将其ECX值发送到微码定序器,该定序器将在此之后正确地输入正确数量的额外副本迭代。仅是副本代码(可能是ESI,EDI和ECX的更新,或者可能仅在中断或异常时执行),而不是微代码分支代码。
n
读取RCX后,最初的oups与更多输入可能是我所看到的96字节阈值。idq.ms_switches:u
每rep movsb
增加一个(从4到5)。
https://eprint.iacr.org/2016/086.pdf建议微码在某些情况下可以触发辅助,这可能是复制较大尺寸文件的现代机制,并且可以解释耗尽RS(显然是ROB)的原因,因为它仅在提交(退出)uop时触发,因此就像没有快速恢复的分支一样。
执行单元可以通过将事件代码与微操作的结果相关联来发出帮助或发出故障信号。提交微操作(第2.10节)时,事件代码使乱序调度程序挤压ROB中所有进行中的微操作。事件代码被转发到微码定序器,后者在相应的事件处理程序中读取微操作”
此专利与P6专利之间的区别在于,这种辅助请求可以在以后的指令中已发出一些非微码指令之后发生,这是因为预期只有第一批指令才能完成微码指令。或者,如果它不是微代码批处理中的最后一个uop,它可以像分支一样用于选择其他策略。
但这就是为什么它必须刷新ROB的原因。
我对P6专利的印象是,对MS的反馈发生在以后的指令发出uops之前,如果需要,可以及时发布更多的MS uops。如果我错了,那么也许它已经是2016年论文中描述的相同机制。
通常,当分支错误地预测为采用该指令时,则当指令退出时,
自Nehalem以来,英特尔就拥有了“快速恢复”的能力,它在执行错误的分支时开始恢复,而不是像异常情况一样等待它退休。
这是在通常的ROB退出状态之上设置一个Branch-Order-Buffer的要点,当任何其他类型的意外事件成为非推测性事件时,它可使您回滚。(当Skylake CPU错误预测分支时会发生什么?)
脚注1:IceLake应该具有“快速简短表示”功能,这可能是处理rep
字符串的另一种机制,而不是更改微码。例如,也许像安迪(Andy)这样的硬件状态机提到他希望自己首先设计出来。
我没有任何有关性能特征的信息,但是一旦我们知道了一些信息,我们便可以对新的实现方式做出一些猜测。