0%

SMMU的BBML语意

SMMUv3 spec 3.21里定义了BBML的基本逻辑。软件在修改页表的时候,硬件可能还在访问,
这个会带来同步问题。如果,我们的世界里只有CPU,这个问题比较容易解决,如果是单核,
没有同步问题,如果是多核,一个核改页表的时候,另外一个core可能在使用页表做翻译,
这就有同步问题。解决办法应该是,先加锁,再清页表,再做tlbi,这样同步的页表翻译在
tlbi之前都是可以的,在tlbi以及barrier之后触发fault,fault在之前的锁上排队。

但是,这个过程里,如果有IO设备也在访问相关的页表,这个同步应该怎么做? 其基本逻辑
也是一样的,只不过tlbi上增加了针对设备一层tlb的无效化。

但是,IO设备访问memory分为两种情况,一种是像在内核中一个设备的dma访问一段内存,
这个dma访问是不能stop的; 一种是像SVA中一个设备的dma访问一段内存,页表变动的时候,
可以进入fault流程,fault流程可以在锁上排队,也就是dma是可有stop的。对于可以stop
的dma,我们使用如上的办法可以解决页表切换时的同步问题。

但是对于内核dma的情况,就搞不定了。首先,一般情况下在做内核dma的时候,页表不会
变动,但是在做虚拟化热迁移的时候,需要把大页解开成小页,就可能遇到在做内核dma
的时候需要变动页表。

SMMU BBML定义了0、1、2三种level,0就是需要软件保证整个同步,如上我们已经描述的。
level1的基本逻辑是这样的, 我们只看他从大页拆分成小页的过程,首先改变block页表的
nTbit到1(这个flag的含义是不在tlb里缓存这个block的tlb),然后做tlbi把tlb清掉,然后
在原子的把block页表换成散开的page页表,这个过程中如果有IO一侧访问页表都是没有同步
问题的,因为如上的过程通过nT和tlbi配合把可能的tlb先清掉,然后换页表又是原子的。

注意SMMU spec上说,这里的页表变动是只有大页拆小页的变动,也就是说,页的物理位置,
属性相关的都不能在这个过程中有变化。

Level2和level1的使用场景是一致的,只是level2不需要nTbit的帮助。他要求硬件设计的
时候在出现一个地址对应多个tlb的时候先选择一个使用,然后用一个tlbi把相关的tlb都
清掉,然后page table walk从新的页表里得到tlb。