1. 概述SMMUSystem Memory Management Unit驱动是整个虚拟化系统中至关重要的组件负责管理设备的DMA地址转换和隔离。本文将详细介绍SMMUv3驱动的完整实现流程从初始化到设备绑定的全过程。驱动实现遵循ARM官方的SMMUv3架构规范主要完成以下核心功能硬件特性探测与配置内存数据结构初始化设备重置与使能主设备Master Device管理中断处理机制2. 驱动初始化流程2.1 初始化入口驱动初始化从BSP层调用开始BSP层需要准备SMMU的配置参数包括structsmmu_init_params{chardevice_name[MAX_NAME_LEN];phys_addr_tbase_address;size_tregister_size;uint32_tevent_queue_irq;uint32_tpage_request_irq;uint32_tglobal_error_irq;uint32_tcombined_irq;bool dma_coherent;structmaster_device_params*masters;uint32_tmaster_count;};每个主设备参数包含设备名称用于标识和管理StreamID列表该设备使用的所有StreamIDVMID虚拟机标识符用于隔离不同虚拟机的设备2.2 资源分配初始化的第一步是分配核心数据结构SMMU控制器结构管理整个SMMU硬件的状态和配置寄存器基地址映射硬件特性标志位命令队列、事件队列、页请求队列Stream Table配置VMID位图管理SMMU域结构表示一个地址空间域Stage-2转换配置关联的主设备列表页表基地址VTTBRVMID分配2.3 硬件特性探测驱动通过读取SMMU的ID寄存器来探测硬件支持的特性这是初始化的关键步骤。2.3.1 架构版本识别读取AIDRArchitecture ID Register寄存器获取SMMUv3的版本信息主版本号Major Version次版本号Minor Version根据ARM规范SMMUv3支持v3.0到v3.4等多个版本驱动需要确认硬件版本的兼容性。2.3.2 IDR0寄存器解析IDR0ID Register 0包含SMMU的核心特性信息Stream Table层级单层Stream Table所有STE连续存储两层Stream Table使用L1描述符索引L2表节省内存转换表字节序小端Little-Endian大端Big-Endian混合模式Mixed驱动必须确保转换表字节序与CPU一致。功能特性标志PRIPage Request Interface支持页请求机制ATSAddress Translation Service支持PCIe ATS协议HYP支持Hypervisor模式SEV支持事件信号MSI支持消息信号中断COHACC支持一致性访问Stall模型STALL支持事务暂停FORCE强制暂停模式Stage支持S1P支持Stage-1转换S2P支持Stage-2转换虚拟化场景下驱动要求硬件必须支持Stage-2转换这是虚拟化场景的基础。转换表格式AArch64格式64位页表格式AArch32_64格式兼容32位和64位VMID位宽8位支持256个虚拟机16位支持65536个虚拟机2.3.3 IDR1寄存器解析IDR1ID Register 1提供队列和ID的大小信息队列大小CMDQS命令队列最大条目数的对数值EVTQS事件队列最大条目数的对数值PRIQS页请求队列最大条目数的对数值StreamID位宽SIDSIZE决定支持的最大StreamID数量如果SID位数小于等于Stream Table分割位数则使用线性表而非两层表嵌入式实现检查驱动不支持嵌入式实现TABLES_PRESET、QUEUES_PRESET、REL标志这些模式下表和队列由硬件预设。2.3.4 IDR5寄存器解析IDR5ID Register 5包含地址和页大小信息页粒度支持GRAN4K支持4KB页GRAN16K支持16KB页GRAN64K支持64KB页每种页粒度还对应支持的大页4KB → 2MB、1GB16KB → 32MB64KB → 512MB输出地址大小OAS32位、36位、40位、42位、44位、48位、52位驱动会选择硬件OAS和主机物理地址位数中较小的值。输入地址大小扩展VAX支持52位虚拟地址最大Stall数量STALL_MAX字段指示可以同时暂停的事务数2.4 内存数据结构初始化完成硬件探测后驱动需要初始化三个关键的内存数据结构。2.4.1 命令队列Command Queue命令队列是软件向SMMU发送命令的机制。根据ARM规范命令队列是一个环形缓冲区队列结构基地址64字节对齐的物理地址大小2的幂次方由IDR1.CMDQS决定最大值条目大小16字节128位生产者-消费者模型生产者索引PROD软件写入指向下一个可写位置消费者索引CONS硬件更新指向下一个待处理命令队列操作软件将命令写入PROD位置更新PROD寄存器硬件从CONS位置读取命令执行后更新CONS寄存器环绕处理队列使用WRPWrap位标识是否环绕防止PROD追上CONS导致的队列满判断错误。2.4.2 事件队列Event Queue事件队列用于SMMU向软件报告错误和异常事件队列特性与命令队列类似的环形结构条目大小32字节256位硬件是生产者软件是消费者事件类型根据ARM规范事件包括F_UUT不支持的上游事务C_BAD_STREAMIDStreamID超出范围F_STE_FETCHSTE获取时外部中止C_BAD_STESTE无效F_TRANSLATION转换失败F_PERMISSION权限错误F_ADDR_SIZE地址大小错误F_ACCESS访问标志错误F_TLB_CONFLICTTLB冲突每个事件记录包含事件类型StreamID和SubstreamID故障地址其他上下文信息2.4.3 页请求队列Page Request Queue如果硬件支持PRI特性需要初始化页请求队列功能支持设备的页错误处理允许设备请求缺失页面的映射。队列结构条目大小16字节包含页请求信息和响应机制2.4.4 Stream Table初始化Stream Table是SMMU的核心数据结构将StreamID映射到Stream Table EntrySTE。线性Stream Table当StreamID位数较少时使用连续内存分配每个STE占64字节索引STE_address base (StreamID × 64)两层Stream Table当StreamID位数较多时使用节省内存L1表每个L1描述符8字节包含L2表的物理地址和Span信息L1索引StreamID[高位]L2表按需分配仅在使用时创建每个L2表包含多个STEL2索引StreamID[低位]分割点SPLIT通常在StreamID的第6位分割即L1索引StreamID[15:6]L2索引StreamID[5:0]每个L2表包含64个STE2^6。3. 设备重置流程3.1 禁用SMMU重置前需要先禁用SMMU检查当前状态读取CR0Control Register 0的SMMUEN位如果已使能则需要先禁用。GBPA配置更新GBPAGlobal Bypass Attribute寄存器设置ABORT位使未配置的流产生中止等待UPDATE位清零确认硬件已应用配置清除CR0写入0到CR0寄存器禁用所有队列和SMMU功能。同步等待轮询CR0ACKCR0 Acknowledge寄存器确认硬件已响应。3.2 配置控制寄存器3.2.1 CR1配置CR1Control Register 1配置表和队列的内存属性表内存属性TABLE_SH共享属性Inner ShareableTABLE_OC外部缓存属性Write-BackTABLE_IC内部缓存属性Write-Back队列内存属性QUEUE_SH共享属性Inner ShareableQUEUE_OC外部缓存属性Write-BackQUEUE_IC内部缓存属性Write-Back这些配置确保Stream Table和队列的访问性能和一致性。3.2.2 CR2配置CR2Control Register 2包含其他控制位PTM性能监控使能RECINVSID记录无效的StreamIDE2HEL2主机扩展支持3.3 配置Stream Table将初始化好的Stream Table配置到硬件STRTAB_BASE寄存器写入Stream Table的物理基地址。STRTAB_BASE_CFG寄存器配置Stream Table的格式和大小FMT格式线性或两层SPLIT两层表的分割点LOG2SIZE表大小的对数值3.4 配置和使能命令队列写入队列基地址将命令队列的物理基地址写入CMDQ_BASE寄存器。初始化队列指针CMDQ_PROD生产者索引初始化为0CMDQ_CONS消费者索引初始化为0使能命令队列设置CR0.CMDQEN位等待CR0ACK确认。3.5 配置缓存失效使能命令队列后需要失效所有缓存的配置和TLB配置缓存失效发送CFGI_ALL命令失效所有配置缓存。TLB失效如果支持HYP特性发送TLBI_EL2_ALL命令发送TLBI_NSNH_ALL命令失效所有非安全非Hypervisor的TLB同步命令发送CMD_SYNC命令确保所有命令执行完成。根据ARM规范CMD_SYNC命令有两种模式SEV模式通过事件信号完成MSI模式通过MSI中断完成3.6 配置和使能事件队列写入队列基地址将事件队列基地址写入EVTQ_BASE寄存器。初始化队列指针EVTQ_PROD写入Page 1寄存器空间EVTQ_CONS写入Page 1寄存器空间使能事件队列设置CR0.EVTQEN位等待CR0ACK确认。3.7 配置页请求队列可选如果硬件支持PRI特性写入队列基地址配置PRIQ_BASE寄存器。初始化队列指针配置PRIQ_PROD和PRIQ_CONS寄存器。使能页请求队列设置CR0.PRIQEN位。3.8 配置ATS检查可选如果硬件支持ATS特性设置CR0.ATSCHK位使能ATS一致性检查。3.9 中断配置配置SMMU的中断处理全局错误中断处理严重的硬件错误如SFM_ERR服务失败模式CMDQ_ERR命令队列错误EVTQ_ABT_ERR事件队列写入中止PRIQ_ABT_ERR页请求队列写入中止事件队列中断当事件队列有新事件时触发软件需要读取并处理事件。页请求中断当有新的页请求时触发。组合中断某些实现将多个中断源合并为一个中断。3.10 使能SMMU最后一步是使能SMMU接口禁用旁路模式如果配置为禁用旁路设置CR0.SMMUEN位。使能旁路模式如果允许旁路配置GBPA.ABORT为0。同步确认等待CR0ACK确认SMMU已使能。4. 主设备管理4.1 主设备结构每个主设备代表一个需要SMMU保护的硬件设备structmaster_device{charname[MAX_NAME_LEN];structsmmu_controller*smmu;structsmmu_domain*domain;uint32_t*stream_ids;uint32_tstream_id_count;uint32_tvmid;bool ats_enabled;structlist_nodedomain_list;};4.2 主设备初始化分配设备结构为每个配置的主设备分配内存。StreamID范围检查验证所有StreamID都在SMMU支持的范围内线性表StreamID num_entries两层表StreamID (L1_entries × L2_entries_per_L1)L2表分配对于两层Stream Table按需为使用的StreamID分配L2表。4.3 域终结化Domain Finalization域终结化配置Stage-2转换参数4.3.1 VTCR配置VTCRVirtualization Translation Control Register配置Stage-2转换共享属性SHInner Shareable确保多核一致性缓存属性IRGN/ORGNWrite-Back Write-Allocate最佳性能页粒度TG4KB页最常用的配置物理地址大小PS根据SMMU的OAS配置支持32位到52位。转换起始级别SL根据地址位数计算48位地址通常从Level 1开始52位地址可能从Level 0开始地址大小T0SZT0SZ 64 - 有效物理地址位数4.3.2 VTTBR配置VTTBRVirtualization Translation Table Base Register指向虚拟机的Stage-2页表基地址从虚拟机的地址空间获取。4.3.3 VMID分配从VMID位图中分配一个未使用的VMID用于TLB和缓存的标记。4.4 设备绑定流程将主设备绑定到SMMU域解绑旧域如果设备已绑定到其他域先解绑。域初始化如果域尚未关联SMMU进行域终结化。设置域关联建立主设备和域的双向关联。ATS配置如果设备和SMMU都支持ATS使能ATS。安装STE为设备的每个StreamID配置Stream Table Entry。加入域列表将主设备加入域的主设备列表。5. Stream Table Entry配置5.1 STE结构STE是64字节的数据结构包含4个双字DWordDWord 0VValidSTE有效位CFGConfiguration配置类型BYPASS旁路模式不进行转换ABORT中止模式拒绝所有事务S2_TRANSStage-2转换模式DWord 1SHCFG共享配置EATSATS使能状态DWord 2Stage-2配置S2VMIDStage-2 VMIDS2PTWStage-2页表遍历使能S2AA64AArch64格式S2R读权限VTCRVTCR配置值DWord 3Stage-2配置S2TTBStage-2转换表基地址VTTBR5.2 STE更新流程STE更新需要特别小心因为SMMU可能随时读取STE原子性要求根据ARM规范STE更新分为三种场景场景1初始化Invalid → Bypass/Abort直接写入完整配置不需要同步因为STE尚未激活场景2绑定Bypass/Abort → Translation先写入DWord 1-3发送CFGI_STE命令同步原子写入DWord 0再次发送CFGI_STE命令同步场景3解绑Translation → Bypass/Abort更新DWord 0的CFG字段发送CFGI_STE命令同步配置缓存失效每次STE更新后必须发送CFGI_STE命令指定StreamID设置LEAF位叶子节点失效发送CMD_SYNC确保完成预取优化更新后可以发送PREFETCH_CFG命令预取新配置到缓存。5.3 旁路和中止模式旁路模式不进行地址转换设备直接访问物理地址用于不需要隔离的设备或调试中止模式拒绝所有事务产生事件报告用于安全策略或设备隔离6. 命令队列操作6.1 命令结构命令是16字节的数据结构包含操作码和参数。6.1.1 CFGI_STE命令配置缓存失效STE操作码CFGI_STEStreamID要失效的StreamIDLEAF叶子节点失效标志6.1.2 CFGI_ALL命令失效所有配置缓存操作码CFGI_ALLRANGE覆盖范围通常设为31覆盖所有6.1.3 TLBI命令TLB失效命令有多种类型TLBI_EL2_ALL失效所有EL2的TLB条目。TLBI_NSNH_ALL失效所有非安全非Hypervisor的TLB条目。TLBI_S12_VMALL失效指定VMID的所有Stage-1和Stage-2 TLB条目。TLBI_S2_IPA失效指定VMID和IPAIntermediate Physical Address的TLB条目VMID虚拟机IDIPA中间物理地址LEAF仅失效叶子条目6.1.4 ATC_INV命令ATS缓存失效StreamID设备StreamIDSubstreamID子流ID如果有地址范围要失效的地址GLOBAL全局失效标志6.1.5 CMD_SYNC命令同步命令确保之前的命令都已完成SEV模式设置CS字段为SEVSMMU通过WFE/SEV机制通知完成MSI模式设置CS字段为IRQ提供MSI地址SMMU写入MSI完成通知6.2 命令发送流程构建命令根据命令类型填充16字节的命令结构。检查队列空间确保队列未满PROD ! CONS || WRP(PROD) WRP(CONS)写入命令将命令写入PROD指向的位置。更新PROD递增PROD索引处理环绕。写入PROD寄存器通知硬件有新命令。等待完成可选对于同步命令轮询CONS寄存器直到命令被消费。6.3 命令错误处理错误检测读取CMDQ_CONS寄存器的错误字段。错误类型CERROR_NONE无错误CERROR_ILL非法命令CERROR_ABT命令获取中止CERROR_ATC_INVATC失效超时错误恢复记录错误命令跳过错误命令继续处理后续命令7. 中断处理7.1 全局错误中断中断触发读取GERROR和GERRORN寄存器计算活动错误active_errors GERROR XOR GERRORN错误处理服务失败模式SFM_ERR最严重的错误需要禁用SMMU。命令队列错误CMDQ_ERR调用命令队列错误处理函数。队列中止错误EVTQ_ABT_ERR事件队列写入失败PRIQ_ABT_ERR页请求队列写入失败CMDQ_ABT_ERR命令队列MSI写入失败清除错误将GERROR值写入GERRORN清除错误状态。7.2 事件队列中断读取事件从事件队列的CONS位置读取事件条目32字节。解析事件事件类型StreamID和SubstreamID故障地址其他上下文事件处理根据事件类型进行相应处理记录日志通知虚拟机触发错误恢复更新CONS递增CONS索引写入CONS寄存器。7.3 页请求中断读取页请求从页请求队列读取请求。请求信息StreamID和SubstreamID请求地址权限读/写/执行特权级别组IDGroup ID响应处理发送PRI_RESP命令响应请求SUCC成功页面已映射DENY拒绝请求FAIL处理失败8. ATS支持8.1 ATS概述ATSAddress Translation Service是PCIe的扩展功能允许设备缓存地址转换结果。优势减少SMMU的转换压力提高DMA性能降低延迟要求设备支持PCIe ATS能力SMMU支持ATS特性IDR0.ATS8.2 ATS使能检查支持读取设备的PCIe配置空间检查ATS能力寄存器使能ATS设置设备的ATS使能位配置STE的EATS字段为TRANSPASID支持如果设备支持PASIDProcess Address Space ID需要先使能PASID再使能ATS。8.3 ATS失效当页表更新时需要失效设备的ATS缓存发送ATC_INV命令指定StreamID指定地址范围等待命令完成全局失效设置GLOBAL位失效设备的所有ATS缓存。9. 队列管理机制9.1 环形队列设计所有队列都采用环形缓冲区设计索引结构IDX实际索引位指向队列中的位置WRP环绕位标识是否已环绕OVF溢出位检测异常队列满判断IDX(PROD) IDX(CONS) WRP(PROD) ! WRP(CONS)队列空判断IDX(PROD) IDX(CONS) WRP(PROD) WRP(CONS)9.2 生产者-消费者同步命令队列软件生产者写入命令更新PROD硬件消费者读取命令更新CONS事件队列硬件生产者写入事件更新PROD软件消费者读取事件更新CONS内存屏障写入队列条目后需要内存屏障确保可见性更新索引寄存器前需要确保所有写入完成9.3 队列轮询命令队列轮询等待队列有空间或命令完成读取CONS寄存器检查队列状态超时处理事件队列轮询检查是否有新事件读取PROD寄存器比较本地CONS处理新事件超时机制普通命令100微秒超时同步命令更长的超时时间超时后返回错误10. 总结SMMUv3驱动的实现是一个复杂但结构清晰的过程初始化阶段资源分配分配控制结构和域结构硬件探测读取ID寄存器确定硬件能力数据结构初始化创建队列和Stream Table设备重置配置寄存器使能SMMU运行阶段主设备管理绑定设备到域STE配置建立StreamID到转换配置的映射命令处理通过命令队列控制SMMU中断处理响应错误和事件关键设计原则原子性STE更新必须保证原子性同步性命令执行需要适当的同步错误处理完善的错误检测和恢复机制性能优化ATS支持、预取、缓存配置驱动实现严格遵循ARM SMMUv3架构规范确保与硬件的正确交互。理解这些流程对于虚拟化系统的开发和调试至关重要也为后续的性能优化和功能扩展奠定了基础。通过本文的详细介绍读者应该能够理解SMMU驱动从初始化到设备管理的完整流程以及各个组件之间的协作关系。这些知识对于开发高性能、高可靠性的虚拟化系统具有重要的指导意义。