解释PCIe MSI 中断要求中断向量连续?PCIe 规范里并没有明确指出

MSI 向量必须连续?

前言

MSI 物理条件,MSI 中断产生的逻辑是RC初始化的时候,由软件将配置写入到 EP 的 2 个寄存器中,这两个寄存器一个指示的是地址 Message Address,一个指示的是数据 Message Data。当 EP 试图触发中断的时候,将会发起一个 MW 事务,往对应的 Message Address 写入 Message Data 的值。

引入问题

MSI 可以配置多达 32 个中断,那么如果是一个相同的 MW 事务,往对应的 Message Address 写入 Message Data 的值,而 Message Data 的值一直是 RC 初始化时配置的值,那么 RC 怎么可以区分不同的中断呢?

分析问题

上面的问题,写入同样的 Message Data 肯定是不能解决的。所以 EP 写的 Data 肯定是变化的,这样 RC 才能区分不同的中断。所以修改代码进行验证。

验证步骤

  1. 硬件 CPU: FT E2000 PCIe: NVME 硬盘 (CPU 使用的 ITS 的中断方式来处理 MSI 中断)
  2. 修改代码逻辑
    在这里插入图片描述
    __pci_write_msi_msg 为最后的将 msi_msg 写入 EP 配置空间的操作函数。
  • 修改1:struct msi_msg *msg 传入的数据结构里面 Message Address 是 ITS 的某个寄存器的地址,Message Data 是 its_get_event_id 获取的 id 。申请一个非缓存的内存空间 __phys_addr 来冒充这个 Message Address。随机选取了 Message Data 为 0xF0 来观察变化。
// 分配非缓存空间
    noncache_memory = kmalloc(ALLOC_SIZE, GFP_KERNEL | __GFP_HIGHMEM);

    if (!noncache_memory) {
        printk(KERN_ERR "Failed to allocate non-cacheable memory\n");
        return -ENOMEM;
    }    
	__phys_addr = virt_to_phys(noncache_memory);
    printk(KERN_INFO "Non-cacheable memory allocated. Physical Address: %pa\n", &__phys_addr);
 
  • 修改 2:创建一个定时器,来定时查询这个 __phys_addr 的值有没有被修改
#define ALLOC_SIZE 128
static void* noncache_memory;
static phys_addr_t __phys_addr;
static void __iomem *its_virtual_address;

#include <linux/timer.h>
struct irq_data * irq_data_save[128] = {0};

//irq_chip_retrigger_hierarchy
// 内核线程函数
static struct timer_list my_timer;

#define DATA_MSI   0xF0

static void my_kernel_thread(struct timer_list *timer) {
	int *paddr = noncache_memory;
		if (*paddr != 0) {
			printk("msi data change :0x%x irq_data:%px", *paddr, (void*)irq_data_save[97 + (*paddr-(DATA_MSI))]);
			irq_chip_retrigger_hierarchy(irq_data_save[97 + (*paddr-DATA_MSI)]);
			
			*paddr = 0;
		}
    // 重新设置定时器,以实现循环定时
    mod_timer(timer, jiffies + msecs_to_jiffies(1)); 
}

代码中使用 irq_chip_retrigger_hierarchy 来触发 ITS 的中断。97 是写死了,是人为查看系统中 MSI 中断的号起始。

实验结果

nvme 可以正常使用,CPU 是 2 核心,系统中创建了 3 个 MSI 的中断号,97 98 99 一共 3 个中断。
通过观察打印,可以分析得出,EP试图触发中断时,会往刚刚修改的 __phys_addr 的这个内存地址写入数据,有 0xF0, 0xF1, 0xF2 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值