目录
问题
1) 单板打开中断路由,配置到不同的核上后,系统会挂住。
2) msi 中断ID cpu是否可以读取。
针对第二个问题(中断向量的读取)
1) 理论上讲 pcie endpoint写入 arm特定地址后,可以读出来,但是实际此地址是只写的。
如下 distributor寄存器描述,
但distributor到 pe还有 rd以及cpu interface 两个接口,如下面arm官网中的此经典图。
2) 我们再翻看cpu interface的寄存器描述,看到此处有个像是和中断向量相关的,看它的具体介绍为:
具体介绍说此寄存器提供了中断的中断ID,PE读这个寄存器就表示响应了这个中断。那么这个寄存器是由谁写的呢?应该是D或者RD中的一个。这里我们特别注意的是对于secure和non-secure这个寄存器的偏移量不同,我们这里采用non-secure模式,因而实际的偏移量为0x0020这个寄存器
代码实现中 irqstat = get_ICC_IAR1(); 接口准确获取了中断号信息。
MSI中断
在arm gic的msi消息中断实现中,存在两种方式
直接写D或者RD地址空间的寄存器
这种方式配置比较简单,即将dirstributor中的 setspi_nsr的地址写入到endpoint pcie设备中即可,例如假如此dirstributor所在的地址空间为 0x29800000,setspi_nsr的偏移量为0x40,则将地址0x29800040写入到 enpoint pcie设备msi寄存器的addr字段,同时将中断向量(和具体cpu相关),例如100,写入到msi寄存器的data字段即可,使能msi,此后如果endpoint发生中断,则向cpu 的distributor 发送一个 包含此地址和数据的memory 写命令。cpu就可以处理了。
整体如下:此处在调试时主要确认CPU采用中断号及d的基地址即可。
ITS
ITS的基本原理,上一张 arm官网文档中的图,
根据这张图,主要分为两个大的部分,红线左侧与红线右侧。这里划分的依据主要在于
--》左侧部分和硬件强相关
--》 右侧部分主要为软件对表配置的准确性
CPU 表侧
在实际调试过程中,ITS提供了模拟产生中断的机制,可以代替硬件来产生中断,我们可以借此来划分问题的所在。
模拟中断的ITS命令如下
我们在实战中发现msi中断通过its方式没有到CPU,因而编写代码进行通过int模拟产生中断以划分问题所在。
LOCAL struct its_collection *its_build_int_cmd(struct its_cmd_block *cmd,
struct its_cmd_desc *desc)
{
struct its_collection *col;
col = dev_event_to_col(desc->its_inv_cmd.dev,
desc->its_inv_cmd.event_id);
its_encode_cmd(cmd, GITS_CMD_INT);
its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
//这里我们打印出devid和eventid,以确认和采用和物理设备一样的ID信息。
printf("pending devid [0x%x] eventid[0x%x]\n",desc->its_inv_cmd.dev->device_id,desc->its_inv_cmd.event_id);
its_fixup_cmd(cmd);
return col;
}
通过上述代码,测试发现可以正常产生中断,那么问题就在物理设备端了。
物理设备侧
its采用的lpi中断,不同于其他三种中断。
基本原理: ITS收到 pcie endpoint的pcie报文信息,从中提前bus dev func作为devid索引,从配置表中索引出 event,进而查找到对应的中断ID,触发CPU。
通过上图:
在第2)步及之后,我们通过INT命令已经验证是正常的了。
因而设备侧 出问题的地方:
1)cpu抓取的request id和表里面的不一致,这个只能PCIE分析仪跟踪。
2) msi地址和msi data不对。
经过再次走读手册及代码,我们发现我们用的这款endpoint器件,其在生成msi memory 写的时候,pcie报文中封装的地址和data字段并不是从标准的msi 寄存器获取的,而是自己又定义了一套,也就是说这个设备即有标准msi寄存器,又有自定义的类msi寄存器。导致我们在配置及调试时走了一些偏差。
路由信息
通过上面这张图,可以看到its不经过distributor,那么这种的路由配置应该在ITS里面做的。
针对走distributor的中断路由
32-1019的中断向量,每个中断向量对应一个此64位大小的寄存器,如果想将某个向量路由到某个cpu上,则
*(volatile u64 *)(GICD_IROUTERn + int_id * 8) = core_id;
page 6736
优先级的确定
下图有个很大的隐含意思:即PPI和SGI离PE更近,他们的优先级的设定通过RD进行控制。
GICR_IPRIORITYR<n> is used instead of GICD_IPRIORITYR<n>
where n = 0 to 7 SGI的优先级更高。
以上两种类型的中断优先级比spi更高
ARMv8 Virtualization Overview · kernelgo
LPI寄存器说明