鲲鹏开发重点2––ARM CPU的推测执行(Speculative execution)

举报
宏观鲲鹏 发表于 2021/06/19 10:34:31 2021/06/19
【摘要】 举个生活中的例子,成研所的餐线还是有很多美味的,我早餐喜欢吃秦云老太婆摊摊面,服务员远远看到我,就马上为我准备清汤了,根本不用等我走到跟前说出“来碗清汤排骨面”。服务员的行为就可以看成推测执行,根据我的历史记录进行预判,并提前准备。


鲲鹏开发重点2ARM CPU的推测执行(Speculative execution

(老古,大何)

 

 

引子:对Memory Fabric的观察

近期比较热门的Gen-Z是一种语义存储(memory-semantic)体系架构,它本身的主要技术优势:

一是能够将DRAM和非易失性存储器及未来的持久性存储技术结合起来;

二是它还使用一种高带宽、低延迟和高效的协议来简化软硬件设计,降低了解决方案的成本和复杂性。

Gen-Z它已经发展到了一定程度,需要更好地定义来适应更大规模的规范与标准,例如在数据中心越来越受欢迎的成熟NVM Express和新兴Compute Express Link(CXL)协议。

前段时间,我们在项目中考虑Memory Fabric某场景时,尝试了内存管理单元MMU的修改,几经周折,我们也成功在Normal空间禁止了cacheable属性但是,一提到MMU配置我们就谈虎色变,想起曾经的MMU相关死机案例,那都是寻寻觅觅仍然找不到原因的悲伤故事。

于是,我们就跑题了,把Memory Fabric和禁止cacheable属性都放一边,先梳理一下ARM处理器MMU配置相关的问题,也聊一下与MMU配置相关性比较强的CPU特性--推测执行Speculative execution)。由于MMU和Speculative execution都是生僻词,系统工程师和底层软件工程师可能了解多一些,应用软件工程师就很少接触了,本文也主要谈一下MMU和推测执行的关系和约束,不对技术细节展开描述

MMU内存管理单元顾名思义就是用于管理内存的部件,这是CPU内部模块名需要操作系统来进行空间配置和管理所以有时提到的MMU并不完全指硬件部分,也包括软件部分。其作用就是完成VA虚拟地址到PA物理地址的转换,页面大小管理,同时配置地址空间的访问属性,包括Normal(乱序访问)和Device(定序访问)进行区分,cache写回,cache写透,关闭cache等等,配置地址空间的访问权限,如只读,只写,可读可写,XN(不可执行)等等。图示如下:

 

开发重点2-图片1.png

图片来源网络

推测执行,或者叫投机执行,或者叫预测执行,也理解为乱序执行,只是传统意义的乱序执行更多是指令在执行阶段的并行执行,而推测执行更多的是指令在提取和分发阶段的投机行为。考虑分支预测,如果分支判断的条件都还没有计算出来,那么CPU提取哪个分支的指令呢?从流水线上看,推测执行就是允许CPU的Fetch部件根据历史和其它条件预取择”正确分支指令,并译码分发和执行其中“无害”的指令。 

开发重点2-图片2.png

图片来源网络

举个生活中的例子成研所的餐线还是有很多美味的我早餐喜欢吃秦云老太婆摊摊面,服务员远远看到我,就马上为我准备清汤了根本不用等我走到跟前说出来碗清汤排骨面”。服务员的行为就可以看成推测执行,根据我的历史记录进行预判,并提前准备。

 

开发重点2-图片3.png

图片来源网络

备注面条劲道,排骨实在

 

下面进入正题

一、简介Introduction

伴随着处理器引入具备分支预测和推测执行功能的复杂流水线,正确地对MMU编程变得尤为重要,否则将出现非本意的内存访问,严重时将导致处理器挂起或者系统异常。本指南规定了安全编程MMU以避免此类问题的最低要求,假定读者已经理解了MMU运行的基本原理,如果不了解,需要先看相关编程手册补充MMU知识。

二、推测执行Speculative execution

Cortex-A 系列处理器推测执行指令可以提升性能,通常基于分支预测的结果,如果预测正确,将收到较好的性能收益,如果预测失败,所有推测执行的结果将抛弃,流水线将被清空。推测执行可能导致程序访问非本意的内存区域,无论是用于数据读、指令预取还是地址转换表的遍历。MMU必须正确设置才能防止推测执行对系统产生意外的副作用。

现代处理器的分支预测准确率已经相当的高了,高达95%以上,所以预测错误引入的流水线惩罚也越来越忽略不计,预测失败对性能的影响微乎其微,总体上看是利大于弊的。但是,因为推测执行导致的程序异常和系统影响却不可不关注,通过MMU管理可以避免,就像CPU的乱序执行,需要程序员关注一样,手段是添加DMB等指令来阻止对程序有影响的乱序执行,CPU的推测执行也需要程序员关注,只是,这个程序员是更偏向于系统软件的,需要考虑MMU编程来管理。

 

如果说乱序执行和推测执行为什么分开描述,因为手册就是这样描述的,所以就只好这样去理解。但是,推测执行更加隐秘,不是软件流程写错了,而是CPU没有按照你熟知的套路出牌

都是底层的指令级并行技术,软件层面是看不到的,这些并行技术本意是不影响软件意图的,无奈,系统复杂,一旦指令并行影响了应用软件,应用软件程序员抓破头皮也无济于事。

三、推测执行与指令预取规则Speculative execution and instruction prefetching rules

1、除非指令改变系统状态,否则允许推测执行指令。

2、不与内存交互的指令可以推测执行 。(直到内部推测寄存器资源耗尽)

3、针对Nornal属性的读内存操作可以推测执行。(写操作不可以推测执行,针对Device属性和strongly ordered属性的内存不可以推测执行)
4、指令预取将基于预测的程序流进行,包括从分支预测失败后的恢复,指令预取不涉及XN位被置位的地址。

5、推测读操作和指令预取(如果需要)将启动地址转换表walks动作。(发生在地址跨页的时候)

推测执行的影响细化了,并不是我们理解的推测执行什么事情都可以干,对内存无损坏的事情(读访问)可以提前干,对硬件寄存器的读访问不能顺便干。

 

四、MMU编程规则MMU programming rules

1、所有的转换表条目都必须被编程,不管是使用的Level 1,2和3,以及未使用的虚拟地址转换条目也必须用能报错的编码进行编程,访问敏感的区域必须编程为Device属性和Strongly Ordered Memory属性。

2、包含访问敏感属性的内存区域必须设置XN位。

3、TTBR中设置的cache属性必须与转换表地址范围中编程的cache属性相匹配。

这三点规则细化了MMU编程的注意事项,内存属性要设置正确,cache属性要设置正确,必要时要设置XN位(execute never)。

 

五、小结Summary

1、Cortex-A 系列处理器的推测执行可能导致不期望的内存访问

2、如果地址转换表没有全编程将导致不期望的内存操作,改变系统状态或者发生处理器挂起。

3、转换表必须完全编程来阻止不期望的副作用。

感觉这三点总结就是一句话,通过MMU的转换表正确的无遗漏的编程阻止处理器推测执行引入的负面影响。

 

附录:5个例子和FAQs

1、案例回顾1~3

案例1:记得多年前,无线产品线有个特性调试了很久,特性目的就是把一段指令代码搬移到一个临时内存空间,然后跳转过去执行,类似补丁功能,结果总是不对,跳过去就挂。我们怀疑MMU的空间属性配置错误了,结果一语中的,改一下就正常了。之前是PowerPC处理器,如果是ARM上的原理,应该就是XN属性( Execute-never )关闭就好了。

类似任务的栈空间,预先被配置了不可执行属性,如果要在栈上执行指令,这部分空间就需要关闭XN属性。这个和推测执行无关,只是一个XN属性配置错误的案例。

 

案例2:还是多年前的一个案例,PowerPC上的,记得是进行单板上FLASH的装备测试,测试过程中经常出现异常,偶尔在FLASH要测试完毕了才挂,原来是FLASH空间后面的地址并不连续,有一个空洞,后面地址空间覆盖一个FPGA硬件,硬件配置了TA(Terminal ACK)的,就是需要外部回ACK确认信号,而MMU配置时,空间配大了,在测试flash的指令流区间,CPU进行了推测执行,读了越界的地址,由于访问的不是真正的硬件地址,Slave硬件无法回ACK,就导致了CPU挂死。后来修改了MMU配置就好了,这个案例和本文的推测执行主题比较符合。

 

案例3:也是MMU配置问题,也是CPU推测执行导致的,这个案例在接入网和无线都出现了,无线产品线定位代价比较大,攻关组耗时1个多月,接入网搜到无线的经验案例,也耗时三天。问题是因为软件配置的MMU逻辑空间大于实际的物理地址空间,导致CPU预取到错误地址时总线挂起,然后看门狗因为长时间没有喂狗而复位单板。

如果MMU没有正确编程,推测执行就有低概率造成严重后果,正向定位的困难很大,因为PC指针都还没有移动,指令就在执行了,trace信息也肯定不准确的。多审视MMU的编程,逐条目比对变得尤为重要。

 

2CPU推测执行示例1~2

以下例子旨在说明推测执行的一些潜在行为,不同处理器的行为会因具体流水线实现而异,同一处理器的行为也会因目标内存系统的速度而异。

推测执行示例1 --分支预测

start     MOV r0, #0x002F000
          MOV r1, #0xFFFFFFFF
          MOV r2, #0
loop     LDR r3, [r0], #0x10
          CMP r1, r3
          ADDNE r2, r2, r3
          BNE loop
          B next_step
示例代码将地址0x2F000开始的内存中数据累加,当值为0xFFFFFFFF时,退出循环,BNE将不被执行,否则以0x10步长地址递增并循环执行。

BNE指令将被预测为“执行”,导致循环加速,当处理器等待一个LDR完成时,它将推测再次执行循环,进入下一次迭代,导致执行更多的LDR操作,可能直到所有LSU单元都已耗尽为止。这里的预取好像是cache预取一样,CPU提前把数据准备好。

因此,在地址0x0002FFF0之后,可能已经下发了3次LDR操作,包括地址0x30000、0x30010、0x30020等等。

这和传统的软件思维不一样,我们软件工程师通常理解的循环是PC指针走到哪里,执行就到哪里。我们不会想到,CPU执行循环居然可以提前跨越几次迭代,把后面几次迭代的数据读操作提前执行了。程序员本来不期望超出地址0x0002FFF0的读操作,由于推测执行,CPU发出了更多的读操作,也访问到一个新的内存页了。

超过0x0002FFF0的读操作的效果取决于MMU地址转换表编程:

1、Normal Memory配置时,读操作会发生,结果会被抛弃。

2、Device 或者Strongly ordered memory配置时,读操作挂起到预测分支被判决的时候,一旦判断分支预测错误,读操作就被放弃。

如果MMU中存在TLB未命中,访问地址0x00030000可能导致地址转换表遍历,如果虚拟地址0x00030000的条目尚未在转换表中编程,则MMU将获得从内存中返回的随机数据。

 

推测执行示例2 --指令预取

start     MOV r0, #0x002F000
            MOV r1, #0xFFFFFFFF
            MOV r2, #0
loop     LDR r3, [r0], #0x10
            CMP r1, r3
            ADDNE r2, r2, r3
            BNE loop
            B next_step 
———section boundary——————————

uart_ctrl  ;   UART control register

uart_read ;UART read register

uart_write ; UART write register

当循环终止时,将出现许多错误预测的分支,多余的指令会自动从流水线上清除,并丢所有的结果。处理器将进入后续的指令执行,开始从"B next_step"的地址预取指令,该指令是Normal内存的顶部地址,下一个区就是Device设备内存区。“B next_step“指令之后没有指令,只会访问敏感的从设备。预取单元将读取一系列"B next_step"地址之后的指令,虽然这个区存放的并不是指令,如果这区设置了“XN“(execute never)属性,预取就不会发生

指令预取将针对访问敏感的从节点执行一系列读操作,这将改变slave的状态,slave可能不支持这样的交易类型,可能收到“SLVERR”响应,或可能以非法操作响应。如果设计正确,salve应返回“SLVERR”以响应指令提取交易,一旦真正执行分支时,错误响应将被丢弃。

跨区跨页边界的内存访问总是容易出问题,没有红绿灯的十字路口也是交通事故频发,所以,MMU属性的正确设置就像保证红绿灯完好无损一样重要

 

3FAQs

为什么所有地址转换表项都必须编程?
处理器将始终将从内存返回的数据解释为有效的转换表条目。在没有清晰编程的条目控制下,MMU将处理数据访问导致随机访问内存。任何未使用的内存区域都必须配置。

为什么我不能只编程我使用的内存位置?

推测执行和指令预取可能导致程序员未曾预料到的内存区被访问。程序中的错误也有可能导致访问非预期的内存区域。所有条目都必须编程以捕获这两个事件。

为什么需要将设备内存的XN位设置为1?

阻止处理器从访问敏感的设备空间预取指令,以造成不可预期的结果。

所有的读操作都会推测执行吗?

只有Normal memory区域的内存才支持推测方式执行读操作。

禁用程序流预测(分支预测)是否会防止推测执行吗?

推测执行总是使能的,不能关闭。

禁用程序流预测(分支预测)是否会阻止指令预取吗?
指令预取总是使能的,不能关闭。

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。