我正在尝试查找当本地计时器到时且 CPU 引发中断时,Linux 内核中的哪个 ISR 会被执行?
我首先检查“cat /proc/interrupts”的输出,但它没有为 NMI 提供任何函数名称(包括 LOC 或本地定时器中断)。
一旦找到 ISR(或为本地计时器设置下一个值的函数),我希望将特定本地计时器的计时器值更改为自定义值,而不是内核指定的值。
任何帮助将不胜感激。
到目前为止,我已经尝试使用“cat /proc/interrupts”和“ftrace”来查找函数名称。
假设您正在谈论 x86 架构,如果您的 CPU 有一个 APIC(当然是的,除非您有一个非常旧的 CPU),本地计时器中断由
asm_sysvec_apic_timer_interrupt
提供服务,在此处使用宏定义。 这是定义 IDT 条目的表,向量编号是 0xEC。
本地 APIC 计时器间隔在启动时在 calibrate_APIC_clock()
函数中计算,并由
lapic_timer_set_periodic_oneshot()
设置,它调用
__setup_APIC_LVTT()
,这是设置必要 APIC 寄存器的实际函数。以上所有信息均自 Linux v6.4 起。
为了帮助您完成任务,您可能首先需要了解 APIC 计时器的工作原理。您可以在《英特尔® 64 和 IA-32 架构软件开发人员手册》第 3A 卷第 11.5.4 节“APIC 计时器”中找到此信息。摘录如下:
如果 CPUID.06H:EAX.ARAT[位 2] = 1,则处理器的 APIC 定时器以恒定速率运行,无论 P 状态转换如何 并且它在深度 C 状态中继续以相同的速度运行。
如果 CPUID.06H:EAX.ARAT[bit 2] = 0 或不支持 CPUID 06H,则 APIC 定时器可能会暂时停止,同时 处理器处于深度 C 状态或由增强型 Intel SpeedStep® 技术引起的转换期间。
APIC 定时器频率将是处理器的总线时钟或核心晶振时钟频率(当 TSC/核心晶振 时钟比在 CPUID 叶 0x15) 中枚举,除以除法配置寄存器中指定的值。
定时器可以通过定时器LVT条目配置为一次性或周期性操作。在单次模式下, 定时器通过对其初始计数寄存器进行编程来启动。然后将初始计数值复制到当前计数中 注册并开始倒计时。定时器到零后,产生定时器中断,定时器 在重新编程之前保持其 0 值。
在周期模式下,定时器通过写入初始计数寄存器(与一次性模式一样)来启动,并且值 write 被复制到当前计数寄存器中,该寄存器进行递减计数。当前计数寄存器自动 当计数达到 0 并产生定时器中断时,从初始计数寄存器重新加载,并且倒计时 被重复。如果在倒计数过程中设置了初始计数寄存器,则计数将重新开始,使用 新的初始计数值。初始计数寄存器为可读写寄存器;当前计数寄存器是只读的。
在一次性和周期模式下,向初始计数寄存器写入 0 可有效停止本地 APIC 定时器。
LVT 定时器寄存器确定通过定时器中断传送到处理器的向量号 当定时器计数达到零时生成。 LVT定时器寄存器中的屏蔽标志可用于屏蔽 定时器中断。