arm smmuv3

SMMU的作用

SMMU执行与PE中的MMU类似的任务。在请求传递到系统互连之前,它转换来自系统I/O设备的DMA请求的地址。SMMU仅为来自客户端设备的访问提供翻译服务,而不为到客户端设备的访问提供翻译服务。从系统或PE到客户端设备的事务由其他方式管理,例如PE MMU。
在这里插入图片描述
Arm SMMU提供:
翻译-Translation
客户端设备提供的地址从虚拟地址空间转换到系统的物理地址空间。
保护-Protection
来自客户端设备的操作可能会被转换表中的权限所阻止。您可以禁止设备读取、写入、执行或对特定内存区域进行任何访问。
隔离-Isolation
即使两个设备共享到SMMU的连接,来自一个设备的事务也可以与另一个设备区别开来。这意味着可以对每个设备不同地应用转换和保护属性。每个设备可能有自己的专用翻译表,或者根据应用程序的需要与其他设备共享。

为了将设备与translations相关联并识别连接到SMMU的不同设备,来自客户端设备的DMA请求具有额外的属性。StreamID唯一标识事务流。SMMU可以对每个流执行不同的翻译或检查。

StreamID
SMMU为I/O设备的内存管理提供了一种灵活且可扩展的方法。它支持从仅一个设备到具有多个设备的大型系统的各种系统。下图上包括SMMU的系统拓扑的简化示例显示了连接到两个设备的SMMU:GPU和DMA引擎。您可以将每个设备配置为具有自己的一组翻译表。
在这里插入图片描述
SMMU可以选择性地支持两个阶段的转换,其方式与支持虚拟化扩展的PE类似。您可以独立启用翻译的每个阶段。在阶段1中,输入地址从虚拟地址(VA)逻辑地转换为中间物理地址(IPA),然后IPA被输入到阶段2,阶段2将IPA转换为输出物理地址(PA)。阶段1供软件实体使用,例如操作系统或用户空间应用程序。它为实体的物理地址空间内的缓冲区提供隔离或转换,例如操作系统的物理地址范围内的DMA隔离。阶段2适用于支持虚拟化扩展的系统,旨在将设备DMA虚拟化为来宾VM地址空间。

SMMU的操作

SMMU的操作。它包含以下部分:

  • Translation process overview
  • Stream Security
  • Stream identification
  • Fault model
  • Bypass
  • Address Translation
  • Services Page
  • Request Interface

Translation process overview

简化的SMMU翻译过程
在这里插入图片描述

  1. 如果SMMU被全局禁用,则事务在不修改任何地址的情况下通过SMMU。全局属性,例如内存类型或可共享性,可以从SMMU的SMMU_GBPA寄存器应用。或者,SMMU_GBPA寄存器可以被配置为中止所有事务。

  2. 如果全局旁路不适用,则确定配置:
    a.找到流表条目(STE)。
    b.如果STE启用阶段2翻译,则STE包含阶段2翻译表库。
    c.如果STE启用第1阶段翻译,则定位上下文描述符(CD)。如果STE也启用了阶段2翻译,则从使用阶段2翻译的IPA空间提取CD。否则,CD将从PA空间中取出。

  3. 如果配置有效,则执行转换。
    a.如果阶段1被配置为翻译,则CD包含阶段1翻译表基址,该基址指向所遍历的表的基址。如果STE启用了第2阶段,这可能需要第2阶段的翻译。如果级1被配置为旁路,则输入地址被直接提供给级2。
    b.如果阶段2被配置为翻译,则STE包含用于执行阶段2翻译的阶段2翻译表库。如果第1级被启用,则第2级转换第1级的输出,或者如果绕过第1级则转换输入地址。如果stage 2被配置为旁路,则提供stage 2输入地址作为输出地址。

  4. 当transaction通过所有转换阶段时,具有相关内存属性的转换地址被转发到系统中。

如果启用了GPC,则实现Realm Management Extension(RME)的SMMU在访问所有物理地址时要接受Granule Protection Checks(GPC)。但是,获取颗粒保护表(GPT)信息不受GPC约束。必须对照GPT检查所有客户端设备对物理地址的访问。SMMU的这种行为是A轮廓架构的FEAT_RME的对应物。有关RME的更多详细信息,请参阅了解体系结构-Realm Management Extension。

Stream Security

如果未实现RME设备分配,SMMUv3体系结构可选择支持两种安全状态,由SMMU_SIDR1.SECURE_IMPL报告。如果实现了RME设备分配(由SMMU_ROOT_IDR.REALM_IMP报告),则支持额外的领域状态。对于每个安全状态,都有单独的寄存器和流表。流可以是安全的、非安全的或Realm,这是由输入信号SEC_SID确定的。见下表:流安全性确定显示了输入信号SEC_SID如何确定流的安全状态。
在这里插入图片描述
非安全流只能生成非安全的downstream transactions。页面表中的传入NS属性和NS属性将被忽略。安全流可以生成安全和非安全的downstream transactions。Realm流可以生成Realm和非安全downstream transactions。

Secure stream和Secure transaction之间有区别:

  • Secure transaction是指访问安全物理地址空间。
  • Secure stream是处于安全状态的设备的编程接口。

Stream identification

一个系统可能有多个设备共享一个SMMU。通常不同的翻译应用于不同的设备。例如,上图的系统中上包括SMMU的系统拓扑的简化示例中,虚拟机a可以使用DMA引擎,虚拟机B可以使用GPU。SMMU需要识别连接到它的不同设备,并将设备与translations相关联。
什么是StreamID
StreamID是SMMU区分不同客户端设备的方式。最简单地说,一个设备可以有一个StreamID。但是,设备可能能够生成多个StreamID,并根据StreamID应用不同的翻译。例如,对于支持多个通道的DMA引擎,不同的StreamID可能应用于不同的通道。
每个安全状态都有一个单独的StreamID命名空间,即:

  • SecureStreamID 0与Non-secure StreamID是不同的StreamID。
  • Realm StreamID 0与Secure StreamID 0不同。

但是,Realm和Non-secure StreamID命名空间是共享的。可以在Non-secure状态和Realm状态下操作的设备在这两种状态下必须具有相同的StreamID。

StreamID在流表中选择一个STE,该表包含每个设备的配置设置。
RME扩展了SMMU体系结构,以支持没有StreamID的事务。这些交易受GPC约束,但不受第1阶段或第2阶段翻译的约束。Arm希望此支持用于GIC和调试访问端口等设备。也就是说,此支持用于传统上不连接到SMMU但访问需要颗粒保护检查的设备。

SubstreamID作用
SubstreamID可以可选地被提供给实现阶段1翻译的SMMU。
Substream使来自同一设备的事务能够共享相同的第2阶段转换,但具有不同的第1阶段转换。

考虑一个运行多个应用程序的虚拟机。您可能希望一个DMA通道由一个应用程序使用,另一个DMA信道由不同的应用程序使用。这些应用程序位于同一VM内,因此它们具有相同的第2阶段翻译。然而,它们有不同的第一阶段翻译。SMMUv3允许每个流具有多个子流。所有子流共享相同的第2阶段翻译,但每个子流都有自己的第1阶段翻译。例如,如果具有固定StreamID的DMA引擎具有多个通道,则不同的子流ID可能应用于不同的通道。
在这里插入图片描述
当事务中提供了SubstreamID,并且配置启用了子流时,SubstreamID对CD表进行索引,以选择阶段1的翻译上下文。

Fault model

下图SMMU故障记录和报告显示了SMMU如何记录和报告故障的流程。
在这里插入图片描述
传入事务在继续进入系统之前要经过几个逻辑阶段。如果SMMU由于执行定义的原因不支持事务类型或属性,则会记录不支持的上游事务故障(F_UUT)事件,并终止事务并中止。
否则,StreamID和SubstreamID(如果提供)将用于定位事务的配置。如果所需的STE和CD中的任何一个无法定位或无效,则会记录配置错误事件,并终止transaction。
如果找到了有效的配置以便可以访问转换表,则转换过程开始。在此阶段可能会发生其他故障。当transaction进行到转换时,遇到故障时的行为变得可配置。当在第1阶段或第2阶段生成时,构成翻译相关故障的以下故障类型:

  • F_TRANSLATION
  • F_ADDR_SIZE
  • F_ACCESS
  • F_PERMISSION
    这些故障类型对应于VMSA中的故障类型,如下所示:
  • Translation fault
  • Address Size fault
  • Access Flag fault
  • Permission fault
    您可以在Terminate和Stall模型之间切换与翻译相关的故障的行为,这由stage 1和STE的CD.{A,R,S}标志决定。{S2R、S2S}标志。

Terminate model
当stage 1被配置为终止故障时,在stage 1发生故障的transaction是:

  • 当SMMU_IDR0.TERM_MODEL=1或CD.A=1时,终止并向进行访问的客户端设备报告中止。
  • SMMU_IDR0.TERM_MODEL=0和CD.A=0时的RAZ/WI。

当stage 2被配置为终止故障时,在stage 2发生故障的transaction被中止。
客户端设备在终止之后的行为是特定于该设备的。
如果配置为终止故障的阶段也配置有CD.R==1或STE。S2R==1,根据故障的阶段,SMMU将失败访问的细节记录到事件队列中的一个事件记录中。

Stall model
Stall模型允许使用需求分页类型的模型。如果启用了Stall模型,则SMMU会记录已暂停事务的详细信息,并引发中断,以便软件知道。收到中断后,软件会在内存中分页并更新转换表,然后发送Resume命令,告诉SMMU重试转换。upstream device似乎经历了很长的延迟。
或者,软件可以选择终止transaction,而不是重新启动transaction。例如,当设备访问出于安全原因不允许访问的地址范围时。
重试或终止命令是通过SMMU的命令队列发出的。

Bypass

bypass模式下,SMMU不必转换传入transactions的地址。可以将stream或整个安全状态设置为bypass。这意味着输出地址与输入地址相等。然而,其他输入事务属性,例如可缓存性,仍然可以选择性地被覆盖。旁路有三种类型:
Global bypass
当一个安全状态bypass translation时,所有transactions都会绕过该安全状态的translation。软件可以将SMMU_()CR0.SMMUEN设置为0以启用全局bypass。软件还可以选择性地设置SMMU)GBPA以覆盖输入属性。
Stream bypass
当SMMU
(*_)CR0.SMMUN=1时,这种类型的SMMU旁路可用。这是当StreamID选择配置为旁路的STE时(STE.Config==0b100)。对于stream-based bypass,使用STE字段配置属性。STE.MTCFG、MemAttr、ALLOCCFG、SHCFG、NSCFG、PRIVCFG、INSTCFG}可以在事务传递到内存系统之前覆盖任何属性.

Stage bypass
启用translation时,会为translation的每个阶段单独配置bypass,这
也由STE控制。配置:
stage 1级旁路:STE。配置[0]==0
stage 2阶段旁路:STE。配置[1]==0
这几乎与禁用VMSA体系结构中的翻译阶段相同。

Address Translation Services

Address Translation Services (ATS)扩展PCIe协议以支持预先转换DMA地址的SMMU。转换后的地址随后被缓存在PCIe设备的本地TLB中。本地TLB被命名为地址转换缓存(ATC)。在设备中定位已翻译的地址旨在减少延迟,并提供可扩展的分布式缓存系统,从而提高I/O性能。有关ATS机制的更多信息,请参阅PCI Express基本规范。
在这里插入图片描述上图ATS机制显示了ATS的工作流程。PCIe功能生成ATS转换请求,该ATS转换请求通过PCIe层次结构发送到根端口,然后根端口将其转发到SMMU。当SMMU接收到ATS翻译请求时,它执行以下基本步骤:
1.验证功能是否已配置为启用ATS翻译。
2.确定功能是否可以访问ATS翻译请求所指示的存储器并具有相关联的访问权限。
3.确定是否可以向函数提供完整翻译或部分翻译。如果是,SMMU将向功能发出翻译。
4.SMMU将请求的成功或失败传送到根端口,该根端口生成ATS转换完成并通过根端口经由响应TLP传送到功能。

当功能收到ATS翻译完成时,它会更新其ATC以反映翻译或注意到翻译不存在。函数根据完成结果使用翻译地址或未翻译地址生成后续请求。SMMU_CR0.ATSCHK控制SMMU是否允许在不进行进一步检查的情况下bypass transactions。
在具有RME DA的SMMU中,设备许可表(DPT)对转换的事务执行检查。
支持PCIe ATS的SMMU实现可以提供可选的额外硬件接口。例如,MMU-600/MMU-700提供DTI-ATS接口,支持ATS翻译请求和ATS翻译响应。SMMU_IDR0.ATS显示SMMU是否执行ATS。

Page Request Interface

如果只有ATS接口,为了提高DMA的效率,软件需要固定DMA使用的内存。也就是说,内存被锁定在适当的位置,因此它不能被系统的动态分页机制交换出去。与钉扎内存相关的开销可能是适度的。然而,从可分页池中删除大部分内存对系统性能的负面影响可能是显著的。相关联的页面请求接口(PRI)增加了PCIe功能在未固定、动态分页内存上以DMA为目标的能力。有关PRI机制的更多信息,请参阅PCI Express基本规范。
为了支持PRI,SMMUv3体系结构引入了一个可选的PRI队列来存储从PCIe根端口接收的PRI页面请求(PPR)。下图的PRI队列显示了PRI队列的数据结构。PPR包含信息,如StreamID、SubstreamID和页面地址。软件可以使用这些信息来定位目标页面。
在这里插入图片描述以下步骤描述PRI的工作原理:

  1. 当ATS请求由于页面不存在而失败时,PCIe功能可以发出PPR以要求软件使所请求的页面可用。
  2. SMMU将PPR存储在PRI队列中并递增SMMU_PRIQ_PROD。
  3. 软件在PRI队列上接收这些PPR,并递增SMMU_PRIQ_CONS。
  4. 软件可以使用命令队列发出CMD_PRI_RESP以向端点发送PRI响应,以指示PPR的成功或失败。请参见命令。
    标记页面后,软件向SMMU发出肯定PRI响应命令。
    如果请求的地址不可用,软件必须发出否定PRI响应命令。例如,当编程失败导致设备请求非法地址时。

SMMU编程

SMMUv3的编程接口:

  • SMMU registers
  • Stream table
  • CD
  • Event queue
  • Command queue
    大多数配置都存储在内存结构中,因此软件必须为这些结构分配内存。然而,一些配置存储在SMMU寄存器中,例如这些结构中的每一个的位置和大小。

SMMU寄存器

下图显示了SMMU寄存器的映射页面。
在这里插入图片描述SMMU寄存器占用两个连续的64K页面,即SMMU寄存器页面0和SMMU寄存器页1,这是架构上所需的。可选或实施定义的功能可能会有其他页面:

  • 如果支持VATOS接口,则存在一个64KB的页面,其中包含VATOS寄存器。
  • 如果支持Secure VATOS接口,则存在一个64KB的页面,其中包含S_VATOS寄存器。
  • 如果支持增强型命令队列接口,则可能存在一个或多个命令队列控制页。
  • 如果安全状态支持增强型命令队列接口,则可能存在一个或多个安全命令队列控制页。

具有RME的SMMU添加仅在根PA空间中可访问的根控制页。它的基地址不同于在其他PA空间中可访问的寄存器的地址。
具有RME DA的SMMU添加了两个连续的64K领域注册页面,即领域注册页面0和领域注册页面1,这两个页面只能在领域和根PA空间中访问。领域寄存器页面0的基址=SMMU寄存器页面0+0x20000+的基址(SMMU_ROOT_IDR0.BA_RELM*0x10000)。
SMMU寄存器页0中的寄存器分为:

  • 非安全寄存器SMMU_*,从偏移0x0开始。
  • 安全寄存器SMMU_S*,从偏移量0x8000开始
    等效领域寄存器SMMU_R*位于领域寄存器页面0中。

大多数寄存器集是相同的,但处于不同安全状态的同一寄存器可能具有不同的地址偏移量。例如
SMMU_CMDQ_BASE
SMMU寄存器页0中的偏移0x90,设置Non-secure Command queue的基地址。
SMMU_S_CMDQ_BASE
SMMU寄存器页0中的偏移量0x8090,设置Secure Command queue的基地址。
SMMU_R_CMDQ_BASE
领域寄存器第0页中的偏移0x90,设置Realm Command queue的基地址。

除了用于数据结构的寄存器之外,还有控制SMMU的其他功能的其他寄存器:

  • 报告已实现功能的标识字段
  • 顶层控制,例如启用SMMU和队列
  • 中断配置
  • 全局错误报告
  • 地址转换操作

Stream table

SMMU使用存储器中的一组数据结构来定位translation数据。请参阅翻译过程概述。SMMU_(*_)STRTAB_BASE保存初始结构的基地址,即Stream table。Stream table条目(STE)包含stage 2的转换表基指针。它还定位了stage 1的配置结构,这些结构包含转换表的基指针。
传入事务的StreamID由SEC_SID限定,确定用于查找的Stream table,并定位STE。
Stream table可以支持两种格式:

  • Linear Stream table
  • 2-level Stream table

使用SMMU_IDR0.ST_level字段可以发现对2-level Stream table格式的支持。软件配置SMMU_(*_)STRTAB_BASE_CFG以指定所用流表的格式。

Linear Stream table
Linear Stream table是STE的连续数组,由StreamID从0开始索引。阵列的大小可配置为STE大小的2的n次方倍,最大可达SMMU在硬件中支持的StreamID位的最大数量。
在这里插入图片描述为了定位事务的STE,e Stream tables通过transaction的StreamID进行索引:
STE_addr = STRTAB_BASE.ADDR + StreamID * sizeof(STE)

2-level Stream table
2-level Stream table由一个top-level table组成,该top-level table包含指向多个二级表的描述符,这些二级表包含STE的线性阵列。您可以配置整个结构所覆盖的StreamID的范围,最大可达SMMU支持的最大StreamID。但是,二级表不必完全填充,而且可能大小不同。这节省了内存,并避免了对非常大的StreamID空间进行大的物理连续分配的要求。
在这里插入图片描述2-level Stream table对于StreamID宽度较大的软件非常有用,并且它无法轻松分配那么多连续内存,或者StreamID的分布相对稀疏。例如,对于PCIe这样的用例,最多支持256条总线,并且RequesterID或StreamID空间至少为16位。请参阅PCIe注意事项。然而,由于每个PCIe链路通常有一个PCIe总线,并且每个总线可能有一个设备,因此在最坏的情况下,有效的StreamID可能每256个可能的StreamID只出现一次。例如,如果StreamID的数量是16比特,则第一有效StreamID是0,第二有效StreamID为256,第三有效StreamID则为512,依此类推。

top-level table由StreamID[n:x]索引,其中n是覆盖的最上面的StreamID位,x是由SMMU_(*_)STRTAB_BASE_CFG给出的可配置拆分点。分裂。根据每个表的跨度,二级表的索引最多为StreamID[(x-1):0]。

L1STD_addr = STRTAB_BASE.ADDR + StreamID[n:x] * sizeof(L1STD)
STE_addr = L1STD.L2Ptr + StreamID[(x - 1):0] * sizeof(STE)

上图显示了SPLIT==8的2-level Stream table的示例。

软件最初分配L1 Stream Table ,该表设置SMMU配置为接受的最大流ID宽度。L1表中的每个条目表示一个StreamID块,其大小通过SMMU_()STRTAB_BASE_CFG设置。分裂。SMMU_)STRTAB_BASE_CFG。SPLIT设置L2 Stream Table的最大大小。
那么L1 Stream Table描述符(L1STD)可能无效,或者指向L2 Stream Table。软件可以根据需要分配这些L2 Stream Table。
L2 Stream Table不必覆盖L1STD表示的StreamID的全部范围。L1STD包含一个Span字段,用于设置指向的表的大小。任何位于L1条目内但在Span之外的StreamID都被视为无效。

L1 Stream Table Descriptor

L1Stream 描述符如下:
在这里插入图片描述

STEs

STE存储该Stream.的上下文信息。每个STE是64个字节。
STE字段遵循如下约定:

  • 与stage 1翻译相关的字段的S1前缀
  • 与stage 2阶段翻译相关的字段的S2前缀
  • 两者都不适用于与特定翻译阶段无关的字段
    以下列表列出了一些常用字段:
  1. Common configuration
    Valid: STE is valid or not
    Config: stage 1/stage 2 translation enabled or bypass
    CONT: contiguous Hint
    EATS: enables PCIe ATS translation and traffic
    STRW: StreamWorld control corresponding to translation regime in VMSA
  2. Stage 1 translation settings
    S1Fmt: format of the CD table
    S1ContextPtr: stage 1 Context descriptor pointer
    S1CDMax: number of CDs pointed by S1ContextPtr, 2S1CDMax
    S1DSS: default substream
    S1CIR/S1COR/S1CSH: CD table memory attributes
  3. Stage 2 translation settings
    S2T0SZ: size of IPA covered by stage 2 translation table
    S2SL0: starting level of stage 2 translation table walk
    S2IR0/S2OR0/S2SH0: memory attributes of stage 2 translation table walk
    S2TG: stage 2 Translation Granule size
    S2PS: physical address size

CDs

CD存储与stage 1 translation相关的所有设置。每张CD有64个字节。指向CD的指针来自STE,而不是寄存器。只有在执行 stage 1 translation时才需要CD。对于只有stage 2 translation 或bypass的stream,只需要STE。

CD将StreamID与stage 1 translation表基指针相关联,以针对每个stage 2 配置将VA转换为IPA。如果使用substreams,则多个CD表示多个stage 1 translations,,每个substream一个。当未启用阶stage 1 translation,具有SubstreamID的translation将终止。

当使用 stage 1 段翻译时,STE。S1ContextPtr字段提供其中一个的地址
如下,由STE.S1Fmt 和STE.S1CDMax配置:

  • single CD
  • single-level CD表的起始地址
  • L1CD的第一级L1表的起始地址

在存在虚拟机监控程序软件的情况下,预计:

  • Stream table 和stage 2 translation表由hypervisor管理。
  • 客户控制下的设备相关的CD表和stage 1阶段翻译表由guest OS管理。

Single CD
下图显示了一个示例配置,其中StreamID从线性流表中选择STE。STE指向第2阶段的转换表,并指向第1阶段配置的单个CD。CD指向第1阶段的翻译表。
在这里插入图片描述

Single-level CD table
下图显示了一个STE指向多个CD阵列的配置。传入的SubstreamID选择其中一个CD,因此SubstreamID确定translations使用哪个stage 1翻译。
在这里插入图片描述
2-level CD table
当使用Substreams时,CD阵列可以是2级的,其方式与Stream table非常相似。
下图配置结构示例显示了一个复杂的布局,其中使用了一个2-
level Stream table。其中两个STE指向一张CD或一组平面CD。第三个STE指向一个2级CD表。对于多个级别,在没有大型物理连续表的情况下,可能会支持许streams和许多substreams。
在这里插入图片描述L1表是由SubstreamID的高位索引的L1CD的连续阵列。每个L1CD。L1表中的L2Ptr配置有CD的线性二级L2表的地址。L2表是由SubstreamID的低位索引的CD的连续阵列。用于L1和L2索引的SubstreamID比特的范围由STE.S1Fmt配置。

Virtual Machine Structure

虚拟机结构(VMS)是SMMU概念,并且是从指针字段STE定位的结构。VMSPtr。VMS保存每个VM的配置设置。具有相同VMID的安全状态中的多个STE必须指向相同的VMS。目前VMS只支持内存系统资源划分和监控(MPAM)功能。它从guest OS配置的虚拟CD.PARTID值映射到物理PARTIT值。有关MPAM功能的更多信息,请参阅了解体系结构-内存系统资源分区和监视(MPAM)概述。

Caching

实现任何类型的缓存都不需要SMMU实现。然而,预计性能要求至少需要缓存一些配置或翻译信息。
配置或翻译的缓存可能表现为每种类型的结构的单独缓存,或者将结构组合到较小数量的缓存中。
当软件想要更改配置时,它需要使SMMU中的任何缓存无效。它通过向命令队列发出配置缓存无效命令来实现这一点。请参见命令队列。当软件想要更改翻译时,它还需要使SMMU中的任何缓存无效。它通过向命令队列发出TLB无效命令或通过广播发送TLB无效来实现这一点。

Command queue

SMMU通过存储器中的循环命令队列进行控制。例如,当软件更改STE或翻译时,它需要使SMMU中的相关缓存无效。这可以通过向命令队列发出相应的无效命令来完成。有关命令类的信息,请参见命令。
在SMMUv3.3之前,每个安全状态有一个命令队列。实现SMMUv3.3的SMMU可以可选地支持多个命令队列,以减少同时向SMMU提交命令的多个PE之间的争用。
在这里插入图片描述SMMU_CMDQ_BASE存储命令队列的基本地址和大小。在添加新命令之前,软件需要检查命令队列上是否有空间。当软件将一个或多个命令添加到队列中时,它会更新SMMU_CMDQ_PROD指针,以告诉SMMU新命令可用。当SMMU处理命令时,它会更新SMMU_CMDQ_CONS指针。软件读取SMMU_CMDQ_CONS指针,以确定命令已消耗且空间空闲。

如果SMMU_CMDQ_PROD。WR==SMMU_CMDQ_CONS。RD和SMMU_ CMDQ_PROD。WR_WRAP=SMMU_CMDQ_CONS。RD_WRAP,队列已满。
SMMU_CMDQ_CONS更新仅显示命令已被使用。这可能并不意味着命令的效果是可见的。CMD_SYNC命令可用于同步。只有当先前命令的效果可见时,才会使用它。例如
CMD_TLBI_EL3_ALL
CMD_SYNC
当CMD_SYNC被消耗时,CMD_TLBI_EL3_ALL的效果保证是可见的。

Commands

Command queue中的所有条目都是16字节长。所有命令队列条目都是小端序。每个命令都以一个8位的命令操作码开始。以下列表显示了命令的类别:
Prefetch commands
预取翻译或配置。
TLB invalidation commands
使与标记(VMID、ASID、VA或all)匹配的给定异常级别的所有TLB条目无效。
Configuration cache invalidation commands
对于给定的StreamID(对于STE)或StreamID和SubstreamID(对于CD),使指定范围<all,range>内的所有配置缓存项无效。
Synchronization command
为与同步命令发出到同一命令队列的先前命令提供同步机制。
PRI response command
当SSV==1时,通知对应于StreamID和SubstreamID的设备,PRGIndex指示的页面请求组已完成给定响应。
ATC invalidation command
使所有与标记(StreamID、SubstreamID、地址范围)匹配的ATC条目无效。
Stall resume/termination command
恢复或终止对用给定StreamID和STAG参数标识的停滞事务的处理。
DPT invalidation commands
这些命令从DPT TLB中删除缓存的DPT信息。

Event queue

如果发生配置错误和故障,则会将它们记录在Event queue中。这些事件包括由传入设备流量引起的事件,例如:

  • 在收到设备traffic后提取配置时发现配置错误。
  • 由设备traffic地址引起的页面故障。

每个安全状态有一个Event queue。当事件队列从空转换为非空时,SMMU生成一个中断。队列的结构与Command queue的结构相同,只是生产者和消费者的角色颠倒了。对于Command queue,SMMU是使用者,而对于Event queue,SMDU是生产者。
在这里插入图片描述如果事件消耗得不够快,由传入事务引起的一系列故障或错误可能会填充Event queue,并导致其溢出。如果Event queue已满,则从不丢弃由停滞的错误事务导致的事件。当事件队列中的条目被消耗并且下一个空间可用时,它们将被记录下来。如果Event queue已满,则会丢弃其他类型的事件。预计系统软件将快速使用事件队列中的条目,以避免在正常操作过程中溢出。

Event records

Event records的大小为32字节,所有事件记录都是小端序。Event queue中可能会记录三类事件:

  • 配置错误
  • 翻译过程中的失误
  • 其他

以下列表显示了一些示例:

  • CERROR_ILL:非法或未识别的命令
  • C_BAD_STREAMID:事务流ID超出范围
  • C_BAD_STE:使用的STE无效
    F_TRANSLATION:翻译错误
    有关事件记录的完整描述,请参阅Arm System Memory Management Unit version 3。

Global errors

与编程接口有关的全局错误报告到适当的SMMU_(*_)GERROR寄存器中,而不是报告到基于内存的Event queue中。这些错误往往是严重的,例如阻止SMMU向前推进。例如,访问配置数据结构之一时的外部中止。以下列表显示了所有Global errors:

  • Command queue错误
  • Event queue访问中止,当标记中止时,Event queue的传递停止
  • PRI队列访问中止,当中止被标记时,向PRI队列的传输停止
  • CMD_SYNC消息信号中断(MSI)写入中止
  • Event queue MSI写入中止
  • PRI队列MSI写入中止(仅限非安全GERROR)
  • GERROR MSI写入中止
  • SMMU进入服务故障模式

SMMU_()GERROR为每个全局错误提供一个比特标志。当触发错误条件时,通过切换GERROR中的相应标志来激活错误。在某些情况下,SMMU行为会在错误处于活动状态时发生变化。例如,当命令队列错误处于活动状态时,不会从命令队列中使用命令。
当SMMU
_)IRQ_Ctrl.gerror_irqen==1时,当SMMU激活非gerror MSI写入中止的错误时,会触发gerror中断。

Minimum configuration

以下顺序显示SMMU初始化的最低配置:

  1. 分配Stream table。
  • 为Stream table分配内存。
  • 通过写入SMMU_STRTAB_BASE_CFG来配置Stream table的格式和大小。
  • 通过写入SMMU_STRTAB_base来配置Stream table的基地址。
  • 通过设置STE,防止未初始化的内存被解释为有效配置。对于每个STE,V=0以将其标记为无效。
  • 通过执行DSB操作,确保SMMU可以观察到写入的数据。
  1. 分配Command和Event queues。
  • 为Command和Event queue分配内存。
  • 通过配置SMMU_CMDQ_base、SMMU_CDMQ_PROD、SMMU-CMDQ_CONS、SMMU_EVENTQ_base、SMMU_EVENTY_PROD和SMMU_EVENTQ_CONS来指定基地址、大小、生产者指针和消费者指针。
  1. 设置用于访问Stream table、Command和Event queues的内存属性
  • 配置SMMU_CR1寄存器。
  1. 为Event queues和GERROR启用IRQ
  • 配置SMMU_IRQ_CTRL寄存器。
  1. 启用Command和Event queues
  • 通过将SMMU_CR0.CMDQEN位设置为1启用Command queues。
  • 通过轮询SMMU_CR0ACK直到CMDQEN读取为1,检查启用操作是否完成。
  • 通过将SMMU_CR0.EVENTQEN位设置为1来启用Event queues。
  • 通过轮询SMMU_CR0ACK直到EVENTQUEN读取为1,检查启用操作是否完成。
  1. 使TLB和配置缓存结构无效.
  • 向Command queue发出命令:
    • 要使TLB条目无效,请确保软件为翻译上下文发出适当的命令。例如,要使非安全EL1上下文的TLB条目无效,请发出CMD_TLBI_NSNH_ALL;对于EL2上下文,请发出CMD_TLBI_EL2_ALL。
    • 要使SMMU配置缓存无效,请发出CMD_CFGI_ALL命令。
    • 要强制完成以前的所有命令,请发出CMD_SYNC。
  • 安全软件可以通过一次写入使所有TLB和缓存失效:
    • 设置SMMU_S_INIT。INV_ALL变为1。
    • 轮询SMMU_S_INIT。INV_ALL,以在继续SMMU配置之前检查其是否设置为0。
  1. 使能 translation
  • 将SMMU_CR0.SMUEN位设置为1。
  • 通过轮询SMMU_CR0ACK直到SMMUEN读取为1,检查启用操作是否完成。

系统架构注意事项

与SMMU相关的一些系统注意事项。

I/O coherency

如果设备的事务窥探PE缓存中的可缓存内存区域,则该设备与PE缓存的I/O一致。这通过避免缓存维护操作(CMO)来提高性能。该设备不需要访问外部存储器。PE不会窥探设备缓存。
如果设备的I/O与PE缓存一致,则与该设备共享的内存不需要CMO。此内存在CPU上映射为内部回写(iWB)、外部回写(oWB)和内部可共享(ISH)。如果设备的I/O与PE缓存不一致,则与CPU上映射为iWB oWB ISH的设备共享的内存需要CMO。
这些类型的SMMU访问可以是I/O一致的:

  • SMMU发起的transactions
    • Translation table walks
    • Fetch of L1STD, STE, L1CD, and CD
    • Command queue, Event queue, and PRI queue access
    • MSI interrupt write
  • 设备发起的transactions
    • 如果SMMU与系统的接口支持I/O一致性,则可以使简单的非相干设备具有I/O一致性。来自客户端设备的事务的可缓存性和可共享性属性可以被SMMU覆盖,因此输出到互连中的事务可以窥探PE缓存。
      SMMU是否支持发布一致接入由SMMU_IDR0.COHACC指示。
      为了支持I/O一致性访问,SMMU需要提供正确一致性保证的互连端口。例如,AMBA互连中的ACE Lite端口可以支持I/O一致访问。

Client device

客户端设备的一些要求,例如:

  • Address size
  • Cache
  • Requirements for a PCIe device or Root Port
  • StreamID assignment
  • Message Signalled Interrupts

Address size
SMMU的体系结构输入地址大小是64位。如果出现以下任何情况:

  • 客户端设备输出小于64位的地址。
  • 客户端设备和SMMU输入之间的互连支持少于64位的地址。
    以系统特定的方式将较小的地址转换为64位SMMU输入地址。SMMU对扩展的64位地址执行输入范围检查:
  • N被定义为由CD-T0SZ或CD-T1SZ控制的VA区域大小,例如40比特。
  • 如果使用顶部字节忽略,分别为CD.TBI0或CD.TBI1,则VA[55:N-1]都相同。
  • 如果未使用顶部字节忽略,则VA[63:N-1]均相同。

Cache
连接在SMMU后面的设备不能包含与系统其他部分完全一致的缓存,因为窥探与物理缓存线有关,但SMMU不能进行从PA到VA的反向转换。设备可能包含不支持硬件一致性的缓存,这些缓存必须由软件维护。
包括具有非一致缓存的加速器的系统拓扑的简化示例.
在这里插入图片描述然而,包含使用ATS从SMMU填充的TLB的客户端设备可以维护完全一致的物理寻址高速缓存,使用TLB在执行高速缓存访问之前将内部地址转换为物理地址。SMMU上游的任何物理寻址的高速缓存必须是一致的。例如,CXL.缓存或CCIX客户端设备,它使用ATS来转换虚拟地址和一致的物理寻址缓存。

系统拓扑的简化示例,包括具有一致缓存的CXL加速器
在这里插入图片描述

PCIe相关

与PCIe子系统一起使用时,SMMU实现必须至少支持完整的16位PCIe RequesterID范围。系统必须确保根端口以一对一或线性方式从PCI RequesterID生成StreamID,从而使StreamID[15:0]==RequesterID[15:0]。可以通过连接来自多个PCI域(或“段”)的RequesterID来构建更大的StreamID,例如:

StreamID[17:0]=={pci_rp_id[1:0],pci_bus[7:0],pci_dev[4:0],pci_fn[2:0]};即StreamID[17:0]={pci_domain[1:0],RequesterID[15:0]};

与支持PASID的PCIe系统一起使用时,系统必须确保根端口以一对一的方式从PCI PASID生成SubstreamIDs。我们建议SMMU支持客户端根端口支持的相同数量或更少的PASID位,以便软件能够通过SMMU检测端到端的SubstreamIDs功能。其动机是,软件可以查看SMMU_IDR1.SSIDSIZE寄存器字段,并了解PASID的可用位数。如果根端口支持的位少于SMMU_IDR1.SSIDSIZE,则需要在其他地方(例如固件表)告知软件这一点。
Arm-Base系统体系结构要求,如果系统支持PCIe PASID,则必须至少支持16位PASID。这种支持必须是完整的系统支持,从根端口到需要PASID支持的SMMU。
属于PCIe端点的流不得停滞。Terminate模型是唯一可行的选择。暂停PCIe事务可能会导致PCIe端点超时(可能很难恢复),或者在某些情况下出现死锁。出于安全考虑,允许系统强制执行Terminate模型。例如,LTI协议包括LAFLOW信号,AXI/ACE Lite Issue H包括AxMMUFLOW信号,DTI协议包括DTI_BU_TRANS_REQ。流量。这些信号和消息都支持NoStall模式,可以强制执行Terminate模型。如果发生转换故障,则即使SMMU已为此转换上下文启用了暂停故障,也会返回故障响应,而不依赖于SMMU软件配置。
具体而言,PCIe流量不得被阻塞,等待任何PE操作,包括排出事件队列或重新启动停滞的事务。PCIe流量必须始终向前推进,而不会出现依赖于软件的无限延迟。

Peer-to-peer
PCIe对等通信(P2P)使两个PCIe设备能够在彼此之间直接传输数据,而无需使用主机内存作为临时存储。是否支持通过系统的P2P流量是系统特定的。在PCIe层次结构启用P2P通信而不经过SMMU的系统中,SMMU无法隔离PCIe设备。
为了解决这个问题,PCIe规范包括对PCIe访问控制服务(ACS)的支持:

  • 对于ACS,当交换机端口看到到对等交换机端口的请求时,它将P2P请求向上游转发到根端口以进行请求验证。它检查是否允许将事务作为完成方以对等设备为目标。
  • 根端口决定是否可以将此请求转发到其预期的目标设备。
  • PCIe规范表明此决定是在重定向请求验证逻辑的帮助下做出的。
  • SMMU是唯一可以强制执行这种隔离的代理,因此它扮演重定向请求验证逻辑的角色。
  • 如果P2P请求的SMMU查找导致错误响应,则P2P请求具有ACS违规错误。这可能是由以下一种或多种原因引起的:
    • 该请求没有访问目标位置所需的权限。
    • 请求的VA不具有存在于对应于请求者设备上下文的翻译表结构中的有效VA到IPA或VA到PA翻译。
    • 存在配置错误或某些暂时错误。

No_snoop
PCIe事务包含No_snoop属性。如果在PCIe事务中设置了No_snoop属性,则表示允许事务“选择退出”硬件缓存一致性。软件缓存一致性确保访问不会在缓存中命中,因此允许I/O访问以避免窥探缓存。与事务关联的内存属性必须替换为Normal-iNC-oNC-OSH。
对No_snoop的支持取决于系统。如果实现了它,No_snoop将Normal可缓存类型的最终访问属性转换为SMMU下游的Normal-iNC-oNC-OSH。

ATS
PCIe功能可以确定在其地址转换缓存内缓存转换是有益的。功能或软件可以考虑以下内容,例如:

  • 在长时间内频繁访问的存储器地址范围,或其相关缓冲区内容受到显著更新率的影响
  • 内存地址范围,例如:
    • Work and completion queue结构
    • 用于低延迟通信的数据缓冲区
    • 图形帧缓冲区
    • 用于缓存函数特定内容的主机内存

StreamID分配

系统设计者为请求者分配一个唯一的StreamID以输入到SMMU。StreamID命名空间是每个SMMU的,因此StreamID在每个SMMU中必须是唯一的。
在具有RME DA的SMMU扩展的机密计算架构(CCA)系统中,设备接口可能以可信或不可信模式运行:

  • 在不受信任的模式下操作时,SEC_SID= Non-secure
  • 在可信模式下操作时,SEC_SID=Realm
    呈现给SMMU的StreamID在两种模式中是相同的。例如,RequesterID为0x100的PCIe设备输入到StreamID为0x1100的SMMU,但SEC_SID可能会因为设备配置的更改而更改。
    在Linux中,SMMUv3驱动程序不支持使用相同StreamID的设备访问同一个SMMU。
    由于与物理设备相关联的StreamID是特定于系统的,因此系统软件将StreamID作为每个设备的固件描述的一部分提供给操作系统。ACPI表和设备树都可以向操作系统提供每个设备的StreamID。

MSIs

在Arm GICv3体系结构中,GIC中断转换服务(ITS)隔离MSIs。请参阅特定于位置的外围设备中断Arm通用中断控制器v3和v4。
ITS接收包含EventID和DeviceID输入的MSI写入。它使用这些信息来选择正确的PE或虚拟PE,以及触发中断的IRQ编号。
ITS需要DeviceID输入来隔离中断源。Arm-Base系统体系结构提供了如何从通过SMMU的StreamID生成DeviceID的规则。实现中断源区分和SMMU DMA区分的相同粒度的最简单方法是从设备的SMMU StreamID生成设备的DeviceID。高级软件和固件系统描述有利于确保这种关系尽可能简单。DeviceID是从StreamID一对一导出的,或者具有简单的线性偏移。
ITS寄存器映射提供了一个包含一个MSI目标寄存器的页面。可以使用SMMU将此页面安全地暴露给设备,例如:

  • 当设备被分配给用户空间驱动程序时,页面可以通过stage 1阶段的翻译映射到设备,以便用户空间驱动为具有VA目的地的MSIs编程。
  • 当设备被分配给虚拟机时,页面可以通过stage 2阶段的翻译映射到设备,以便 guest OS 为具有IPA目的地的MSIs编程。

在non-CCA系统中,设备总是发布呈现给SMMU的MSIs,其中SEC_SID=Nonsecure
在具有用于RME DA的SMMU的CCA系统中,与TEE设备接口安全协议(TDISP)兼容的设备可以通过两种方式发布MSI:

  • 如果MSI是通过配置空间中的MSI能力配置的,则它被发送到T=0的主机SoC,并因此被呈现给SEC_SID=非安全的SMMU。
  • 如果MSI是通过设备接口的受保护MMIO区域中的MSI-X能力配置的,则它被发送到T=1的主机SoC,并因此被呈现给SEC_SID=Realm的SMMU。

无论使用哪种MSI机制,来自单个设备接口的MSIs都被呈现给具有相同DeviceID的GIC ITS接口。MSI的目标PA空间是根据转换表中的配置来确定的。

SMMU用例

包括:
•Stage 1用例
•Stage 2用例

Stage 1用例

单个stage 1翻译的使用。
Scatter-gather
一些高级设备可以使用scatter-gather列表向地址请求DMA,其中包含形成单个请求的非连续缓冲区的多个地址。
但是,简单的设备通常不支持scatter-gather。它们只能向连续缓冲区请求DMA。当系统运行时,物理内存会变得碎片化,因此不一定能保证连续的缓冲区。操作系统可能必须将大范围的DMA请求分解为多个较小范围的DMA要求。这会影响性能。
SMMU可以解决这个问题。操作系统使用SMMU向设备提供连续的缓冲区,即使该缓冲区在物理上不连续。这是通过在转换表中分配具有连续虚拟地址的页面来实现的,该转换表将页面映射到非连续物理地址。然后,OS使用虚拟地址对DMA地址进行编程。
在Linux中,如果设备驱动程序使用DMA API为不支持 scatter-gather的设备分配分散页面,则SMMU驱动程序会执行“收集”工作。这项工作对设备驱动程序是透明的。
由于此地址空间仅为设备创建,因此与应用程序进程虚拟内存地址空间无关。广播TLB维护不能用于使SMMU TLB与PE无效。尽管SMMU也使用ASID来区分不同的地址空间,如PE,但SMMU的ASID命名空间和PE的ASID名称空间是独立的。为了确保它们位于不同的ASID命名空间中,操作系统需要将CD-ASET设置为1,这样从该上下文创建的SMMU TLB条目就不会因某些广播无效而无效。

32-bit devices in a 64-bit OS
一些传统设备仅支持32位地址的DMA。由于操作系统可能会在超出32位范围的物理地址上分配DMA缓冲区,因此需要一种解决方案来确保这些遗留设备仍然工作。
SMMU通过基于其StreamID为每个32位设备创建单独的虚拟内存映射来解决这个问题。这种地址转换使设备能够对32位范围内的地址发出DMA请求,即使物理地址超出了这个范围。
在Linux中,如果同时满足以下两个条件。

  • 设备驱动程序使用DMA API为设备分配页面。
  • 页面的物理地址超过4GB。
    SMMU驱动程序完成地址映射工作,将4GB以下的IOVA映射到4GB以上的分配页面。这项工作对设备驱动程序是透明的。
    与前面的散 scatter-gather例一样,此地址空间仅为设备创建。它与应用程序进程的虚拟内存地址空间无关。您不能使用广播TLB维护来使PE中的SMMU TLB无效。
    在64位系统上支持32位传统设备的替代方案是不可取的:操作系统在低地址限制内维护DMA“反弹缓冲区”池,并在缓冲区和原始64位位置之间复制数据。例如,SWIOTLB对没有SMMU的系统或在Linux中禁用SMMU时执行此操作。对于大型传输,使用SMMU要快得多。

OS device isolation
恶意设备可能会通过互连启动不正确的DMA传输。DMA传输可能会损坏或检索不属于恶意设备的数据。在具有SMMU的系统中,设备只能访问为DMA映射的页面。
许多操作系统具有设备驱动程序在执行DMA传输时使用的通用API。例如,在Linux中,当使用非缓存一致DMA时,这些DMA API会安排分配,确保适当的地址限制,并执行缓存维护操作。这些类型的API可以跟踪任何特定设备访问哪些页面。
这些DMA API将SMMU配置为映射正确引用的地址,但防止访问任何其他地址。检测并包含任何编程错误。出现故障的设备或驱动程序错误不会影响为DMA配置的页面集之外的数据。与允许设备进行不受限制的DMA相比,这可以提高系统可靠性。当可能存在不受信任或恶意设备时,这对于安全性尤其重要。例如,它们通过外部互连连接。
在这个用例中,SMMU转换表不与PE共享。共享ASID是不必要的。

Userspace device driver
某些系统可能需要用户空间设备驱动程序。用户空间驱动程序用于性能、灵活性、健壮性或安全性。例如,应用程序可能需要在不使用系统调用的情况下对加速器进行低延迟访问,并避免在用户空间和内核空间内存之间复制数据的开销。
为此,操作系统将设备MMIO寄存器映射到用户进程虚拟地址空间。如果用户空间控制的设备可以请求DMA,则产生的事务与用户处理处于相同的信任级别。该设备必须位于SMMU后面。SMMU确保来自设备的DMA访问只能正确地执行到用户进程的地址映射内的允许区域。SMMU保护系统不受恶意或不正确的用户空间程序控制的DMA的影响。
当设备被分配给应用程序时,软件会分配DMA目标的特殊内存区域。然后,OS为设备设置SMMU使用的私有转换表,映射这些存储器区域用于设备访问。我们建议该内存在进程VA空间和设备地址空间中出现在相同的地址,以便程序员可以以明显的方式配置DMA指针,但这不是强制性的。
在Linux中,VFIO子系统允许从应用程序使用设备。VFIO允许应用程序在进程中选择映射到所选内存区域的IOVA,并且应用程序在将DMA指针编程到设备中时使用IOVA。SMMU使支持进程的所选区域的存储器能够被设备的DMA访问。设备和PE通过该内存共享数据。SMMU防止设备访问进程地址空间的任何其他部分或其他进程的地址空间。
因为用户空间内存通常是按需分配和交换的,所以必须考虑DMA上的页面错误。在许多系统中,与转换相关的故障对DMA传输是致命的。许多设备驱动程序通过固定作为DMA目标的页面来避免与翻译相关的故障。因为DMA只发生在特定的内存区域,而且这些区域通常很小,所以固定内存是一个合理的要求。

Userspace Shared Virtual Addressing (SVA)
用例Userspace设备驱动程序提供了一个用户空间设备驱动程序,但有一些限制:SMMU转换表必须在用户空间设备驱动器的地址空间中映射特殊的DMA区域。
此用例考虑了与设备共享整个用户进程地址空间的替代方案,而不是特定区域。与设备共享进程地址空间依赖于DMA的CPU内核内存管理。它消除了应用程序和设备驱动程序的一些复杂性。设备MMIO寄存器由PE以与用户空间设备驱动程序中相同的方式进行虚拟映射。然而,现在SMMU将设备与整个进程地址空间而不是子集相关联。该设备需要在物理上能够访问任何用户空间虚拟地址。例如,SVA不能用仅能使用32位地址的设备和使用48位虚拟地址的进程来实现。
为了实现公共地址空间,SMMU可以直接使用进程转换表和ASID。由于使用了通用ASID,并且虚拟地址在PE和SMMU上具有相同的含义,因此可以使用广播TLB维护来使来自PE的SMMU转换无效。我们建议广播无效,因为可以避免手动TLB无效命令到SMMU的可能较慢的往返程序。使用常见的失效方法也可能会简化软件。
在进程试图对每个页面进行DMA编程的情况下,固定每个页面是不切实际的。DMA可能发生在任何地址,无论页表是否映射了它,因此设备和系统必须支持DMA访问中的页故障。这意味着:

  • 当检测到页面故障时,设备DMA transfer不得被致命中止。
  • 需要一种机制来通知操作系统以下内容以恢复DMA transfer。
    • 出现故障。
    • 需要执行操作才能访问所需页面。

SMMU和设备都协同支持DMA上的页面故障为非致命故障的要求。例如,设备DMA流可以在SMMU中配置为在故障时停止。当故障发生时,SMMU向软件报告故障描述符,并且故障事务被暂停,直到页面故障得到解决。软件向SMMU发出命令以重试事务,或者如果故障是由不正确的访问引起的,则中止事务。设备在对其DMA请求的响应中经历一个小延迟。
或者,如果更智能的设备被告知故障,它可能能够有效地调度业务。例如,SMMU被配置为中止故障事务,并且设备被通知错误。设备将事件报告给其设备驱动程序,该驱动程序解决了的原因
页面错误。这种方法的优点是避免了SMMU中的流量停滞,这可能会影响其他事务。但是,使用此方法需要特定于设备的软件代码。例如,Linux不支持仅支持中止故障transaction的非PCIe设备的SVA。
PCIe PRI也使用类似的方法,它在ATS响应中向设备报告故障。PRI提供标准的页面请求接口,使设备能够通过根端口和SMMU请求软件解决页面故障。PRI不需要特定于设备的页面故障解决程序。这有助于减少标准软件(如管理程序)中特定于设备的软件需求。
在Linux中,VFIO子系统提供了一个接口来启用应用程序的SVA。要支持SVA,设备、总线和SMMU必须支持以下功能:

  • 每个设备有多个地址空间,例如使用PCI PASID扩展。SMMU驱动程序分配一个PASID,设备在DMA transactions中使用它。
  • I/O页面故障。
    • 对于PCIe设备,需要PRI。
    • 对于非PCIe设备,需要Stall模式。
    • 核心内存管理处理来自SMMU的转换故障。
  • MMU和SMMU实现兼容的页表格式。

Stage 2用例

satge 2段翻译的使用。
VM设备分配
hypervisor可以将设备分配给不受信任的VM,并配置SMMU以保护系统的其余部分不受VM控制的设备的影响。
PE stage 2将映射设备MMIO寄存器转换到IPA空间中,就好像guest OS正在物理机器上运行一样。SMMU中的stage 2转换将VM的客户物理存储器映射到用于DMA的设备。guest OS似乎在具有直接连接设备的物理机器上运行。guest使用guest物理地址(IPA)对设备进行编程,并且没有stage 1翻译。设备分配使设备能够DMA到任何guest 内存,就像物理机器上的直接连接设备一样。
PE stage 2转换表直接与SMMU共享,或者SMMU使用的单独转换表与PE表保持同步。SMMU和PE使用相同的IPA地址空间。
设备可能无法容忍DMA页面错误,包括将设备分配给VM时的错误。如果有任何设备分配给访客,许多hypervisors通过固定所有VM内存来避免DMA上的页面故障。
在Linux中,通过利用主机内核中的VFIO子系统,设备可以由用户空间虚拟机管理器(VMM)(如QEMU)专门管理。在分配了设备的虚拟机中,虚拟机应该能够像在主机中一样看到完全相同的设备。通过将设备分配给guest,您可以在guest中获得与在主机中几乎相同的性能。
对于这个用例,Linux中的SMMU使用一个单独的转换表。但是,IPA到PA的映射与VM的stage 2转换表相同。stage 1翻译默认用于SMMU,尽管从逻辑上讲它是stage 2翻译。像QEMU这样的VMM可以选择使用stage 2翻译,但通常使用stage 1翻译。这没有什么区别,因为IPA到PA的映射是相同的。
使用guest OS SMMU分配VM设备
如果hypervisor将设备分配给虚拟机,它也可能呈现出供访客使用的SMMU的外观,因此虚拟机和分配的设备也可以享受stage 1用例的好处。要实现这一点,请将软件模拟的虚拟SMMU(简称vSMMU)分配给VM。与vSMMU的交互由hypervisor转换为使用真实SMMU编程接口执行的操作。
之后guest OS可以使用satge 1用例、编程配置和将表转换到其VM分配的SMMU接口中的任何一个。hypervisor维护的satge 2转换表嵌套在虚拟机维护的satge 1转换表之下。例如,如果guest OS使用用户空间设备驱动程序,则stage 1表保护IPA空间不受客户的用户空间进程的影响,而hypervisor的satge 2转换表保护主机的物理地址空间不受任何客户控制的DMA的影响。
这种场景也可以仅通过翻译的一个实际阶段和翻译表的软件阴影来支持。hypervisor序观察编程到vSMMU接口中的来宾配置和转换表指针。hypervisor将来guest stage 1的转换表内容与hypervisor的satge 2的表合并为单个hypervisor序拥有的影子转换表,用于单个转换阶段。发送到vSMMU的访客无效命令触发对访客翻译表条目的re-shadowing 。
在Linux中,目前不支持嵌套satge 1转换和satge 2转换。然而,与VM设备分配一样,它仍然需要在VM引导之前固定所有来宾内存以填充stage 2的表。当前支持影子转换表,但它在VM中不使用vSMMU。相反,它使用准虚拟IOMMU或virtio IOMMU。virtio iommu使来宾能够使用map/unmap接口将IOVA到IPA的映射传递到主机。主机代表客户在SMMU中安装IOVA到PA的映射。virtio-iomu是由Linux和一些VM实现的,如QEMU、云管理程序和crosvm。引入它的主要用例是guest中的用户空间设备驱动程序。
Media protection
一些受保护的媒体解决方案使用SMMU来保护特定的媒体缓冲区,这些缓冲区可以是内存分割或由不受信任的操作系统提供。这是通过诸如加密引擎和视频解码器之类的设备来实现的,这些设备共享不受信任的OS的IPA内存视图,但受保护的媒体缓冲区除外,这些媒体缓冲区对于不受信任OS是不可见或不可访问的。与设备使用的权限相比,这是通过对不受信任的操作系统使用更严格的stage 2阶段权限来实现的。这个用例实际上并不需要翻译。也就是说,stage 2可以是身份映射。缓冲区的配置是在固件(受保护的媒体管理器)和不受信任的OS之间的协作下执行的。

固件负责为不受信任的OS和设备创建satge 2转换表,并确保系统的配置始终符合预定义的策略。该策略指定了一组约束,包括是否应允许系统中的给定设备访问特定的内存位置。对于不受信任的操作系统和设备,存在不同的stage 2阶段转换表。SMMU阶段2转换表映射预先布置的受保护媒体缓冲页,从而提供对允许的设备的访问。然而,不可信OS的IPA空间可能不映射预先安排的受保护媒体缓冲区页面,或者可能以减少的权限来映射它们,从而限制不可信OS对缓冲区的访问。
主机隔离
pKVM hypervisor在KVM的主机和hypervisor部分之间提供了权限分离,其中hypervisor受来宾信任,但主机不受信任。在引导过程中,主机最初是受信任的,但在KVM初始化后,其权限会降低,因此,如果对手稍后能够访问主机的大型攻击面,则无法访问访客数据。
目前使用pKVM时,主机仍然可以指示具有DMA功能的设备(如GPU)访问来宾和hypervisor内存,这会破坏这种隔离。防止DMA攻击需要由hypervisor拥有的SMMU。
实现主机隔离的最简单方法是共享stage 2页表,该表将PE和SMMU的IPA转换为PA。无论主机在CPU上可以访问什么,它也可以使用DMA进行访问。由于已将内存传递给系hypervisor或guests,主机无法访问内存,DMA设备也无法访问这些内存。
这种机制有一些限制。pKVM通常惰性地填充主机阶段2的页表。也就是说,直到主机首次访问主机阶段2的页表,才填充这些页表。这取决于CPU页面故障。然而,DMA通常不会出错,因为Linux目前不支持stage 2 SVA。因此,必须在启动时填充整个第2阶段页面表集。这很容易做到,因为IPA到PA的映射是平坦的。

将某些页面传递给来guests会变得更加复杂,因为这涉及到从宿主stage 2的页面表中删除这些页面。为了节省内存并有效地使用TLB,stage 2阶段的转换使用块映射进行映射,例如1GB或2MB块,而不是单独的4KB单元。当从该范围中捐赠页面时,hypervisor必须删除块映射,并将其替换为排除捐赠页面的表。因为设备可能同时在该范围内的其他页面上执行DMA,所以此替换操作必须是原子操作。否则,DMA可能会在映射无效的一小段时间内到达SMMU,并致命地中止。CPU/SMMU体系结构仅在支持FEAT_BBM时才支持块映射的原子替换。有关FEAT_BBM的更多信息,请参阅A剖面架构的Arm架构参考手册。

一种灵活的替代方案使用SMMU中的私有页表,与CPU页表完全断开连接。有了这一点,SMMU可以实现一组减少的特征,甚至只实现一个阶段的翻译。这也为主机提供了一个虚拟I/O地址空间,从而为大缓冲区和寻址能力有限的设备提供了更高效的内存分配。

  • 23
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值