基于RISC-V的MSI硬件辅助中断虚拟化设计
作者: 吴军平 王镇道 石雪倩
关键词:中断;MSI;RISC-V; 硬件辅助虚拟化;IOMMU
中图分类号:TP332 文献标识码:A
文章编号:1009-3044(2024)28-0095-04
0 引言
RISC-V因其开放性和先进性而备受关注。自主研发基于RISC-V指令集的CPU已成为一种新趋势,为实现芯片的自主可控提供了新方向。中断是处理器设计中十分重要的组成部分,它可以通过在特定事件发生时暂停当前任务的执行,转而处理该事件,从而提高处理器的处理效率[1]。在虚拟化技术中,准确且高效的中断处理方式也是虚拟化技术研究的重要方向[2]。
MSI相比于传统的线中断具有较强的拓展性,更低的延迟,通常被PCIE等高性能外设使用[3]。当前广泛应用的RISC-V 外部中断控制器PLIC[1]并不能对MSI直接处理,需要通过硬件将MSI转换为线中断。这种处理方式不仅需要额外的硬件开销,还会导致在中断虚拟化时频繁的特权模式切换,极大地影响了处理器的虚拟化性能[4]。
本文基于RISC-V AIA(Advanced Interrupt Archi⁃tecture) 协议,首次提出了一种RISC-V架构下的MSI 硬件辅助中断虚拟化设计。本设计提供了专门的MSI 中断控制器(IMSIC) [5]和IOMMU[6],可以作为IP集成到RISC-V架构的处理器中。本设计可以直接对MSI接收处理,并且在中断虚拟化时减少VMM的参与,将中断直通到虚拟机[7],为提升虚拟机中断响应效率提供了硬件支持。
1 顶层结构设计
本文设计主要由IOMMU 和IMSIC 两大组件构成。IOMMU的主要功能是将指向虚拟地址的MSI重定向到真实的物理地址,IMSIC负责接收MSI和发送中断通知。图1展示了设计的顶层结构。
系统中IOMMU 的存在使得在虚拟机中运行的guest OS可以直接控制I/O设备,而只需很少的VMM 参与。直接控制设备的guest OS使用客户物理地址(GPA) 对设备进行编程。当设备用这些地址发送MSI 时,IOMMU根据VMM提供的地址转换成数据结构,将这些GPA转换为HPA(实际物理地址)。MSI经过IOMMU的地址转换,得到HPA,然后通过系统总线将中断信息写入IMSIC的中断文件的MSI接收区域中。
每个IMSIC都对应特定的硬件线程(hart) 。单个IMSIC由多个中断文件构成,这些中断文件是接收和处理MSI的硬件资源的集合。不同的hart特权态对应不同的中断文件。本文讨论的是虚拟中断,每个中断的目标是guest OS。因此,为每个guest OS分配相应的客户中断文件是必要的。在本文后续提到的设计中,只讨论IMSIC的客户中断文件。IMSIC的客户中断文件负责接收MSI,并管理中断状态信息,将优先级最高的中断信息发送到CSR hgeip 对应位置。CSRhgeip记录虚拟机的中断通知状态,每一位对应一个独立的虚拟机。这些中断状态随后会被汇总到CSRhip的VSEIP字段中。如果虚拟机处于活跃状态,系统会将中断直接传递给虚拟机。如果虚拟机不活跃,中断信息将被保存在hgeip中,系统可以选择唤醒虚拟机,或等到虚拟机投入运行时,再将中断信息注入到虚拟机。AIA协议中规定hart采用CSR指令间接访问IMSIC 中断文件的寄存器资源。CSR vsiselect 和vsireg作为间接访问的窗口,VGEIN信号用于在多个客户中断文件中选择匹配的中断文件,以便与之进行交互。
2 子模块硬件设计
下文将分别介绍IOMMU和IMSIC组件的设计。
2.1 IOMMU的设计
IOMMU的顶层结构如图2所示。IOMMU内部主要包括TCU(转换控制单元)和IOATC(IOMMU地址转换缓存)两个关键组成部分。在外部接口方面,设计采用APB总线接口用于软件对寄存器信息的访问,而AXI 总线的读通道则用于进行IOMMU 的访存操作。此外,外部接口还包括MSI重映射请求和转换完成的信号。
在读取特定数据时,传统的多级页表访问方法需要多次访问主存,导致显著的时间开销。为了提高IOMMU的性能,设计中引入了IOATC,它通过缓存设备上下文(DC) 和MSI页表项(MSIPTE) 来减少对主存的访问需求。该缓存采用全相联结构,有效提升命中率。具体来说,设备上下文的缓存项使用输入的de⁃vice_id 作为标签;而MSIPTE 缓存项则使用输入的GPA和从DC中获取的客户软上下文标识作为标签。
为了解决缓存一致性问题,IOMMU采用队列数据结构,并通过与软件的交互来维护一致性。当缓存项需要更新或失效时,软件会向命令队列发送失效命令。IOMMU会根据命令中的标志信息,对相关缓存项进行失效处理。
DC将设备与地址空间关联,并保存用于地址转换的设备参数。IOMMU使用24位的设备硬件标识符(device_id)遍历设备目录表(DDT) ,以定位到相应的DC。DDT是一种基数树的数据结构。device_id被分为三段,分别标记为DDI[2]、DDI[1]、DDI[0],以进行3 级查表。设备目录表指针存储在ddtp 寄存器中。IOMMU使用高位字段DDI[2]查表,获取非叶项。在非叶项中,保存着下一级页表的物理页编号(PPN) 。第二级查表与第一级类似,而第三级查表则得到叶项,其中叶项实际为查找的DC 的内容,由DDI[0]索引。对于DC的查找,本文的设计主要采用状态机的思想,状态跳转关系如图3所示。IOMMU收到地址转换请求后,首先会向缓存查询是否存在所需的DC,若命中,则直接取回使用;若未命中,则开始3级查表的流程。每次读取内存信息后,IOMMU将对其内容进行合法性检查,非法则跳转FAULT状态,记录并上报错误信息。
DC中与MSI相关的参数主要包括MSI地址掩码(address mask) 、地址模式(address pattern) 和MSI页表指针(msiptp) 。地址掩码和地址模式一起用于识别请求是否为MSI 类型,并辅助索引MSI 页表项(PTE) 。MSI页表指针用于找到控制MSI地址转换为页表的入口物理地址。
当MSI 地址A 满足如下关系:(A >> 12) &~msi_addr_mask = (msi_addr_pattern & ~msi_addr_mask)时,则IOMMU确认进行MSI重定向。IOMMU首先查询IOATC中是否存在目标MSIPTE,若命中则直接取回PTE,否则需要访问内存获得。访存前,IOMMU从地址A中提取一个中断文件编号I,I = ex⁃tract(A >> 12, msi_addr_mask)。extract函数示例如下:若x = a b c d e f g h,y = 1 0 1 0 0 1 1 0,则extract(x,y) = 0 0 0 0 a c f g。使用msiptp的PPN字段作为基地址,(I << 4) 作为偏移量,组合得到PTE的访存地址。每个PTE占据16字节,IOMMU将验证MSIPTE的合法性,如果合法,则根据MSIPTE的内容执行地址转换,否则电路状态会跳转至FAULT状态,将错误信息发送至错误队列中。当MSIPTE处于基本翻译模式时,假设转换前的地址为A,则转换后得到的地址为(MSIPTE.PPN << 12) | A[11:0]。访问MSI页表项的状态机设计如图4所示。
2.2 IMSIC 的设计
IMSIC由多个中断文件组成,其中客户中断文件负责处理虚拟MSI中断。IMSIC中断文件的硬件设计结构框架如图5所示。在本设计中,每个客户中断文件支持的中断数量为127。IOMMU将以GPA编程的MSI重定向到中断文件的接收区域(receive region) 的内存映射寄存器中。接收区域硬件将不同形式的中断转换为统一的脉冲信号,并将中断信息存储到外部中断挂起寄存器组(eip array) 中。中断处理模块(inter⁃rupt handle) 管理中断的处理流程的逻辑,包括APB总线接口的控制、中断仲裁和中断流程的交互等。寄存器模块(regs) 维护中断文件的寄存器,这些寄存器保存了中断的配置信息。
对于CSR间接访问的实现,本设计采用APB总线协议,实现hart与中断文件之间的数据交互。在vsise⁃lect 中设置中断文件内部寄存器的编号(0x70–0xFF) ,hart访问vsireg就可以对编号对应的中断文件寄存器访问。具体地,vsiselect寄存器的值连接到总线的地址线,而vsireg的值连接到总线的数据线。同时,信号VGEIN用于指示数据的分配情况。
接收区域发出的中断标识由中断处理模块进行译码,然后传送到eip寄存器阵列。中断寄存器的配置信息与中断处理模块相连。当多个中断同时挂起且使能,需要向CPU发送中断信息时,IMSIC需要仲裁以确定优先级最高的中断。在IMSIC中,中断优先级数值与中断标识保持一致,并且中断标识越小,中断优先级越高。由于中断标识号由软件分配,软件可以通过配置标识符来控制中断优先级。固定的中断优先级减少了优先级仲裁电路的硬件成本。
vstopei寄存器是在处理器内部实现的一个CSR 寄存器。Hart使用CSR指令来访问vstopei,相比通过系统总线访问内存映射寄存器的方案,可以加快中断响应速度。当Hart接收到中断信号后,会主动读取vstopei以获取外部中断标识,同时向vstopei写入任意值(写入值被忽略),以指示客户中断文件清除中断的挂起位。清零中断挂起位的信息通过APB总线传递,APB地址线的最高位作为访问操作的标志位。最高位为1表示清零挂起,数据线传输清零的中断标识。经过中断文件的译码后,APB的信息将用于清零寄存器组中的中断挂起位。挂起位的清除意味着CPU已经处理了对应的中断标识。在这个过程中,CPU需要对vstopei执行原子读写操作,以避免因延迟问题导致中断信息丢失。
3 仿真结果与分析
本文采用VCS和Verdi仿真软件进行仿真验证。对IOMMU部件的功能测试点包括缓存命中和未命中时的行为逻辑,验证地址转换结果的准确性。针对IMSIC部件,主要进行中断控制逻辑的测试,包括中断的挂起、仲裁、发送以及中断完成等功能的正确性。
3.1 MSI 地址转换仿真
对IOMMU进行MSI地址转换的应用场景的仿真结果如下。图6是IOMMU对MSI重映射时,缓存命中的仿真结果。
信号msi_trans_en_i 在第一个时钟上升沿被拉高,待转换的地址msi_gpa_i输入,此时电路的状态从IDLE跳转到MSIC_LKUP,同时向MSI缓存请求对应的缓存项。第二个时钟周期等待缓存回应。第三个时钟上升沿,缓存指示命中,并将缓存项交付给TCU,电路状态变为 MSIPTE_RDY。在该状态下,转换结果地址由组合逻辑输出。MSI地址为0xaa_bbbb_cccc_d123,MSIPTE的44位PPN字段为0xddd_eeee_ffff,转换结果应为0xdd_deee_efff_f123,输出结果和电路行为符合预期。
图7是IOMMU对MSI重映射时,缓存未命中的仿真结果。
IOMMU收到MSI重映射请求,TCU查询缓存,缓存返回未命中信号。当电路状态跳转到MSI_ACC(编码为3) ,访存查询msi请求信号msi_rqst_vld_o拉高,并将访存地址交给总线控制单元,指示访问内存。从图7可以看到信号msi_resp_vld_i有两次变为高电平,这是因为MSIPTE是128位,需要进行两次64位的数据传输。在第二次传输时,msi_resp_last_i将会拉高,说明已经接收到完整的PTE。此时电路状态跳转到MSI_CHECK(编码为4) ,IOMMU会对PTE的合法性进行检查。检查通过则把访存得到的PTE填充到缓存中,并且电路跳转到MSIPTE_RDY(编码为2) 。转换结果地址在该状态输出,输出地址与预期一致,电路功能设计正确。生成访存地址时,设计使用extract 函数提取中断文件编号。如图7所示,输入的gpa为0xaa_bbbb_cccc_d123,msi 掩码为1011_1110_0000_1001,电路计算得到的中断文件编号为0x9b。extract 的硬件功能设计正确。