如何在QEMU中测试SHPC驱动的request_threaded_irq修改?
如何在QEMU中测试SHPC驱动的request_threaded_irq修改?
看起来你已经顺利完成了SHPC驱动的中断处理改造——把原来的request_irq()换成request_threaded_irq(),还把单函数拆成了中断上下文的shpc_isr()和线程上下文的shpc_ist(),这个思路完全符合内核中断处理的最佳实践!不过测试这个修改确实有点头疼,因为QEMU对SHPC的模拟支持确实有限。我先理下你当前的处境,再给你几个可行的测试方案:
你的修改回顾
先明确下你的核心改动(方便其他读者理解):你把原来的单中断处理函数拆成了两个职责明确的部分:
shpc_isr():在中断上下文快速执行,只做基础检查(比如判断是否忽略热插拔),然后返回IRQ_WAKE_THREAD唤醒处理线程shpc_ist():在线程上下文执行完整的热插拔逻辑,避免长时间占用中断上下文影响系统响应
你的完整diff如下:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 012b9e3fe5b0..b82d2bc4b777 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -166,6 +166,8 @@ #define SLOT_SERR_INT_MASK 0x3 static irqreturn_t shpc_isr(int irq, void *dev_id); +static irqreturn_t shpc_ist(int irq, void *dev_id); + static void start_int_poll_timer(struct controller *ctrl, int sec); static inline u8 shpc_readb(struct controller *ctrl, int reg) @@ -746,7 +748,7 @@ int shpchp_set_bus_speed_mode(struct slot *slot, enum pci_bus_speed value) return retval; } -static irqreturn_t shpc_isr(int irq, void *dev_id) +static irqreturn_t shpc_ist(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; u32 serr_int, slot_reg, intr_loc, intr_loc2; @@ -825,6 +827,21 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t shpc_isr(int irq, void *dev_id) +{ + pr_info("%s: isr for interrupt handler\n", __func__); + + struct controller *ctrl = dev_id; + struct pci_dev *pdev = ctrl->pci_dev; + + if (pdev->ignore_hotplug) { + pr_info("ignoring hotplug"); + return IRQ_HANDLED; + } + + return IRQ_WAKE_THREAD; +} + static int shpc_get_max_bus_speed(struct controller *ctrl) { int retval = 0; @@ -1001,8 +1018,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) pci_set_master(pdev); } - rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, - MY_NAME, (void *)ctrl); + rc = request_threaded_irq(ctrl->pci_dev->irq, shpc_isr, shpc_ist, + IRQF_SHARED, MY_NAME, (void *)ctrl); + ctrl_dbg(ctrl, "request_irq %d (returns %d)\n", ctrl->pci_dev->irq, rc); if (rc) {
要应用这个diff,你可以用:
git apply <path-to-diff-file>
你遇到的测试困境
你已经尝试了几乎所有常规的虚拟化测试路径:
- 用
-device pci-bridge,shpc=on创建SHPC桥,但它是根桥,不接管热插拔控制,没法触发中断 - 尝试在QEMU monitor里添加二级桥、e1000等设备,要么不支持SHPC,要么还是没法触发中断
- 物理机(Dell Latitude E7450)也没有SHPC兼容设备
- 其他虚拟化方案(Libvirt、VMware、VirtualBox)也没有合适的支持
可行的测试方案
1. 手动触发中断逻辑(最快验证)
既然没法用模拟设备触发,咱们可以直接在代码里或用户空间手动调用处理函数:
- 代码内强制触发:在
shpc_init()成功注册中断后,直接调用shpc_isr()和shpc_ist(),验证逻辑是否正常执行。比如:
启动内核后,你就能看到自己加的日志,确认两个函数都能正常运行,变量访问、逻辑分支都没有问题。// 在shpc_init()中request_threaded_irq成功后添加 if (!rc) { pr_emerg("Manually triggering SHPC ISR and IST for testing\n"); // 触发ISR shpc_isr(ctrl->pci_dev->irq, ctrl); // 直接调用IST验证逻辑 shpc_ist(ctrl->pci_dev->irq, ctrl); } - 用debugfs触发:给驱动加一个debugfs节点,用户空间写入命令时触发线程。比如:
启动内核后,执行// 在驱动初始化时注册debugfs文件 static struct dentry *shpc_debug_dir; static ssize_t shpc_trigger_ist(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct controller *ctrl = file->private_data; shpc_ist(ctrl->pci_dev->irq, ctrl); return count; } static const struct file_operations shpc_trigger_fops = { .write = shpc_trigger_ist, .open = simple_open, .llseek = default_llseek, }; // 在shpc_init()中添加 shpc_debug_dir = debugfs_create_dir("shpc", NULL); debugfs_create_file("trigger_ist", 0200, shpc_debug_dir, ctrl, &shpc_trigger_fops);echo 1 > /sys/kernel/debug/shpc/trigger_ist就能触发shpc_ist()。
2. 验证中断线程是否正确创建
即使没法触发真实中断,你可以先确认线程是否成功注册:
- 查看
/proc/interrupts:找到对应irq号的行,后面会显示线程名称(就是你用的MY_NAME) - 用
ps aux | grep shpchp:能看到对应的中断线程进程
3. 改造QEMU模拟SHPC中断(进阶)
如果想模拟真实的硬件触发,你可以修改QEMU的代码:
- 找到QEMU的
hw/pci-bridge/shpc.c文件,添加一个monitor命令(比如shpc-trigger-irq) - 在命令处理函数中,模拟SHPC控制器产生中断,这样内核就能收到中断并调用你的
shpc_isr()
4. 寻找真实SHPC硬件
如果有条件,老的服务器级机器(比如HP ProLiant、Dell PowerEdge的老型号)通常带SHPC兼容的PCI扩展槽,插/拔设备就能触发真实的热插拔中断,完美验证你的修改。
5. 用内核irq_sim框架(内核5.11+)
内核的irq_sim框架专门用于模拟中断,适合驱动测试:
- 初始化一个
irq_sim实例,申请模拟irq号 - 把模拟irq号传给
request_threaded_irq() - 用
irq_sim_fire()触发中断,就能完整模拟从硬件中断到线程处理的流程
备注:内容来源于stack exchange,提问作者Guilherme Giácomo Simoes
相关产品推荐
相关产品推荐

