使用内联 asm 将中断 11 提升到内核模块时出错

Error while raising interrupt 11 with inline asm into kernel module

我正在尝试使用内核模块 LKM 中的内联 asm 引发中断 11

asm("int [=10=]x3B");

但是在这一行之后,我读到了 dmesg

do_IRQ: 1.59 No irq handler for vector

这是我从网站上获取的驱动程序代码 https://embetronicx.com/tutorials/linux/device-drivers/linux-device-driver-tutorial-part-13-interrupt-example-program-in-linux-kernel/ 当我尝试执行 "cat /dev/etx_device" 时,我得到了 dmesg

do_IRQ: 1.59 No irq handler for vector

我的内核版本是5.1.20-200.fc29。x86_64 AMD处理器。有什么问题?

  cat /proc/interrupts: 
      CPU0       CPU1       
  0:        110          0   IO-APIC   2-edge      timer
  8:          1          0   IO-APIC   8-edge      rtc0
  9:          0          0   IO-APIC   9-fasteoi   acpi
 11:          0          0   IO-APIC  11-edge      etx_device

这曾经适用于旧内核版本,但在更高版本上失败。原因是通用 IRQ 处理程序 do_IRQ() 已更改以获得更好的 IRQ 处理性能。它不是使用 irq_to_desc() 函数来获取 IRQ 描述符,而是从每个 CPU 数据中读取它。描述符在物理设备初始化期间被放置在那里。由于这个伪设备驱动程序没有物理设备,do_IRQ() 在那里找不到它并且 returns 出现错误。 如果我们要用软件中断来模拟IRQ,首先要将IRQ描述符写入per-CPU数据中。不幸的是,per-CPU 数据中的 IRQ 描述符数组符号 vector_irq 在内核编译期间不会导出到内核模块。改变它的唯一方法是重新编译整个内核。如果您认为值得付出努力,可以添加以下行:

EXPORT_SYMBOL (vector_irq);

在文件中:arch/x86/kernel/irq.c

在所有包含行之后。 从新编译的内核编译并启动后,按如下方式更改您的驱动程序:

添加包含行:

    #include <asm/hw_irq.h>

将读取函数更改为:

static ssize_t etx_read(struct file *filp,
                char __user *buf, size_t len, loff_t *off)
{
        struct irq_desc *desc;

        printk(KERN_INFO "Read function\n");
        desc = irq_to_desc(11);
        if (!desc) return -EINVAL;
        __this_cpu_write(vector_irq[59], desc);
        asm("int [=12=]x3B");  // Corresponding to irq 11
        return 0;
}