2. 队列项可见语义
任何生产者(无论SMMU还是软件)必须保证如果消耗者可以看见更新PROD值,那么消耗者也可以看到所有新的队列项。对于SMMU输出队列(Event队列和PRI队列),SMMU写队列数据到内存中,当数据在内存共享域中变得可见,SMMU允许更新的PROD值可见。这是新队列项对消耗者可见的第一步。
消耗者只能通过观察更新的PROD索引来观察队列中新的有效项在存在。如果消耗者读取一个超出PROD最后索引的队列项,这个项中保含的数据未知。
NOTE: 中断顺序规则也存在。SMMU通过PROD使得队列的更新可见,在此时不会比发送队列中断更后。
NOTE: 在中断到来时,软件不能假定新的队列项存在,而不去首先读取PROD索引。比如,如果之前的中断handler处理掉所有的事件包括第二批,这里下一个中断handler将没有新的队列项处理。
3 Event队列行为
SMMU可能支持转换错误的配置行为,这使错误事务被STALL,暂停然后恢复,或立即中止并放弃事件。
Event被记录到event队列来回复配置错误或传入事件相关的转换错误。传入的事务会导致一系列错误或fault,若event消耗得不够快,event队列可能overflow。若event队列满时,STALL错误导致的event不会被丢弃,但当event队列消耗event项且下一个空闲时可以被记录。若event队列满时,其他类型的event被丢弃。
NOTE: ARM期望可能被丢弃的event用于debug。后面章节将根据overflow作准确的队列行为。
ARM期望系统软件从event队列消耗event项来避免在正常情况下overflow。
在本文档的所有情况下,当一个event被记录时,若在event队列中对一个新的项有空闲时且队列可写时,event将被记录。队列可写且使能时,没有全局error标志和不会overflow。没有报告的event用来回复STALL事务(比如当没有STALL域,或STALL=0),若没有记录被允许丢弃。当event队列可写,STALL event不会被丢弃并被记录。软件必须消耗来自队列的event来释放空间,否则pending STALL event不会被记录。STALL event不同于其他event。队列以相同环形顺序被填充,这种event不再存在,不会被消耗。
当多个pending event同时往event队列写时,ARM建议一个实现不会优先non-stall event超过stall=1 event。
若event产生来回复中止事务,在事务回复返回到client之前event可见。可查看CMD_SYNC,它强制与中止的事务的event可见。
NOTE: 这意味着产生的event以回复中止的事务并作为SMMU event可以被看到,在事务中止被报告给client设备之间。
4 写“commit”记录event
event记录产生被抽象为以下步骤:
- 触发event产生,比如一个转换错误;
- 在SMMU内部产生event记录;
- 决定可能写一个新队列项;
- 最后event记录被提交且写到event队列项;
- 在event队列里event记录可见:
- -记录数据位置的更新对要求的shareability domain可见;
- -PROD.WR索引被更新新的记录给软件。在队列的语义上,记录不可见直到写index被更新覆盖新的项。
第4点表示event将被写入到队列且变成可见。直到commit,event写可能不会发生(比如,若队列满且软件不消耗任何event项,event写将不会commit)。
若后续write不遭遇外部的abort,被commit在event写在队列中被可见。
STALL event记录的写必须commit直到队列项可写(队列使能且不满)。若不可写,STALL记录被buffer直到队列可写。
5 event合并
允许实现合并多个event记录。当多个相同的event产生时,这可能会产生,当单独event不能应用增加的可用信息,这可用来减少event队列的event记录。
当以下所有条件满足时event可以被合并:
- event类型和所有域都相同,除了明确表明的域;
- 若存在,STALL域为0。STALL错误记录不再被记录。
实现不再要求合并任何event,但不再要求支持STE.MEV标志来使能或继承event的合并。
NOTE: 为调试目的,可通过STE.MEV标志disable event的合并。
软件实现(比如SMMU的虚拟模拟)不要求满足STE.MEV。在guest要求合并被disable后, hypervisor可能造成event被合并。