快速连接
👉👉👉【精选】ARMv8/ARMv9架构入门到精通-目录 👈👈👈
先说答案:NO,或者说定义了FIQ向量,但底层实现就是调用了panic。也就是说在Linux Kernel是无法注册和处理FIQ中断的
在Linux Kernel的异常向量表中定义了FIQ的入口,那么看下FIQ进行了哪些处理呢?我们从el1_fiq开始分析.
el1_fiq其实就是调用handle_arch_fiq指向的函数
(linux/arch/arm64/kernel/entry.S)
SYM_CODE_START_LOCAL_NOALIGN(el1_fiq)
kernel_entry 1
el1_interrupt_handler handle_arch_fiq
kernel_exit 1
SYM_CODE_END(el1_fiq)
(linux/arch/arm64/kernel/entry.S)
.macro el1_interrupt_handler, handler:req
enable_da
mov x0, sp
bl enter_el1_irq_or_nmi
irq_handler \handler // 这里跳转到 handle_arch_fiq
......
如果系统没有调用set_handle_fiq()重新设置FIQ handler,那么handle_arch_irq将指向默认值default_handle_fiq
(注:其实在Linux Kernel中,在我们一般的配置中,不会调用set_handle_fiq,所以handle_arch_irq将指向的是默认值default_handle_fiq,即只要进入了FIQ向量入口,那么将会调用panic()函数)
(linux/arch/arm64/kernel/irq.c)
void (*handle_arch_irq)(struct pt_regs *) __ro_after_init = default_handle_irq;
void (*handle_arch_fiq)(struct pt_regs *) __ro_after_init = default_handle_fiq; // 这里定义了FIQ的默认值
int __init set_handle_fiq(void (*handle_fiq)(struct pt_regs *))
{
if (handle_arch_fiq != default_handle_fiq)
return -EBUSY;
handle_arch_fiq = handle_fiq; // 这里重新定义FIQ handler
pr_info("Root FIQ handler: %ps\n", handle_fiq);
return 0;
}
default_handle_fiq的实现,就是调用panic函数
(linux/arch/arm64/kernel/irq.c)
static void default_handle_fiq(struct pt_regs *regs)
{
panic("FIQ taken without a root FIQ handler\n");
}
为何会说"在Linux Kernel中,在我们一般的配置中,不会调用set_handle_fiq" 呢?
因为我们看到在Apple Interrupt Controller (AIC)控制的驱动程序中,是调用了set_handle_fiq的,也就是重新设置了FIQ Handler。
(linux/drivers/irqchip/irq-apple-aic.c)
set_handle_irq(aic_handle_irq);
set_handle_fiq(aic_handle_fiq);
关注"Arm精选"公众号,备注进ARM交流讨论区。