使用内联 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;
}
我正在尝试使用内核模块 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;
}