基于GIC v3 + ARM64CPU的中断入口

学习Linux系统中的子系统的一些思考 【gic driver 篇】

最近“兴趣来潮”,哈哈,就想来拆一下Linux 内核中断子系统的黑盒子。些有摸索,也算曲折;但收获颇丰。等你找到答案的时候,就像我一样,原来在这里。
蓦然回首,那人却在灯火阑珊处。
好废话不多讲,进入主题,要梳理清楚中断子系统有哪些模块,怎样关联起来。首先,你得有硬件吧,这是基础,其次有硬件,你应该就有驱动吧,有了驱动就会有应用接口吧。这些部分怎么一步步过来,听我马上道来。
我这里选的是GIC V3 + ARM64 【kernel5.10】的平台,具体的板级随便,大体的框架都是一样的。这里也提一下,刚开始的时候,你一定要掌握架构,点到为止,一旦入坑,可能难以回头,更甚找不到自己想要的答案。因为你会发现,所需背景知识太多太多,作为过来人的忠告。
我喜欢从底层硬件往上来看,那就先看CPU相关的文件,找到启动文件,找到中断向量入口,别问我为什么是这样,问就是这是定律。无论你是单片机,RTOS嵌入式系统,Linux系统都是一样的,记住就行。

//linux-5.10.223\arch\arm64\kernel entry.S
#找到这几个关键字
.macro el1_interrupt_handler, handler:req

/*
 * EL1 mode handlers.
 */
    .align    6
SYM_CODE_START_LOCAL_NOALIGN(el1_sync)
    kernel_entry 1
    mov    x0, sp
    bl    el1_sync_handler
    kernel_exit 1
SYM_CODE_END(el1_sync)

    .align    6
SYM_CODE_START_LOCAL_NOALIGN(el1_irq)
    kernel_entry 1
    el1_interrupt_handler handle_arch_irq
    kernel_exit 1
SYM_CODE_END(el1_irq)

好,到这里,汇编代码到此为止,前期你千万别先沉迷于此文件中。重点是el1_irq 的处理函数,
handle_arch_irq,这个函数在哪里了?那就需要看irq-gic-v3.c 文件了,路径是linux-5.10.223\drivers\irqchip。
找到handle_arch_irq 就好说了,它是一个函数指针(地址),它是怎么获取的了,如下图,
在这里插入图片描述

IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
    ->gic_of_init(struct device_node *node, struct device_node *parent)
        ->gic_enable_of_quirks(node, gic_quirks, &gic_data);
        ->gic_init_bases
            ->init gic_data 
            ->set_handle_irq(gic_handle_irq)
                ->handle_arch_irq =gic_handle_irq;
            ->gic_update_rdist_properties
            ->gic_dist_init
            ->gic_cpu_init
            ->gic_smp_init
            ->gic_cpu_pm_init
        ->gic_populate_ppi_partitions

上图是这段代码的一个调用关系图。从这里可以得到handle_arch_irq 函数指针的来源。
也就是以后有外设中断来,第一入口就是这里,下面再来看看handle_arch_irq 所指向的真正函数gic_handle_irq,它有哪些动作了,先上code,

gic_handle_irq
    ->irqnr = do_read_iar
    ->gic_pmr_mask_irqs
    ->gic_arch_enable_irqs
    ->isb
    ->handle_domain_irq(gic_data.domain, irqnr, regs)
        ->__handle_domain_irq(domain, hwirq, true, regs)  
            ->old_regs = set_irq_regs(regs)
            ->irq_enter
            ->irq_find_mapping
            ->generic_handle_irq
            ->irq_exit
            ->set_irq_regs(old_regs)
    
generic_handle_irq  //EXPORT_SYMBOL_GPL(generic_handle_irq)
    ->struct irq_desc *desc = irq_to_desc(irq)
    ->data = irq_desc_get_irq_data(desc)
    ->generic_handle_irq_desc(desc)
        ->desc->handle_irq(desc)

再上调用关系图,
在这里插入图片描述
详细的自行阅读代码,推荐大家一个好网址,在线看linux 源码。https://elixir.bootlin.com/linux/v6.10.3/source
至于基础的知识,比如GIC V3 spec, ARMV8 arch spec,我都有发文档在CSDN文库中。
GIC 的组件,Distributor,CPU interface,Redistributorb,我这里不做过多介绍,就贴出它们在spec的原文解释。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至于ARMv8的E0,E1,E2这些等级,也不做过多介绍,感兴趣同学可以自行了解。好了,今天就到此为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝晨若溪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值