smp启动-init_IRQ-gic-CPUHP_AP_IRQ_GIC_STARTING

上一篇:boot_cpu_hotplug_init

https://www.cnblogs.com/zhangzhiwei122/p/16092269.html

参考-总流程:https://www.cnblogs.com/pengdonglin137/p/11925299.html

 

9、init_IRQ():设置中断栈,调用of_irq_init初始化中断控制器,其中会注册CPUHP_AP_IRQ_GIC_STARTING的回调函数gic_starting_cpu

 

init_IRQ

848asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
849{

951        init_IRQ();

linux/arch/arm64/kernel/irq.c

  54void __init init_IRQ(void)
  55{
  56        init_irq_stacks();
  57        irqchip_init();
  58        if (!handle_arch_irq)
  59                panic("No interrupt controller found.");

  69}
  70

56  - 设置 irq stacks ; per cpu 数组  irq_stack , 然后 per cpu 指针, irq_stack_ptr , 给每个指针赋值,指向 对应的 irq_stack 数组

 

57 调用irqchip_init,在 drivers/irqchip/irqchip.c

  27extern struct of_device_id __irqchip_of_table[];
  28
  29void __init irqchip_init(void)
  30{
  31        of_irq_init(__irqchip_of_table);
  32        acpi_probe_device_table(irqchip);
  33}

 

27 - __irqchip_of_table 指向 kernel image 里面特殊的节  __irqchip_of_table, 这个节里面存放  struct of_device_id  对象 数组。

举例: v5.10/drivers/irqchip/irq-gic-v3.c

1933
1934IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
1935

这样就会在  __irqchip_of_table 这个节里面生成一个  struct of_device_id  对象 。

 

of_irq_init

函数在  linux/drivers/of/irq.c 中

 472/**
 473 * of_irq_init - Scan and init matching interrupt controllers in DT
 474 * @matches: 0 terminated array of nodes to match and init function to call
 475 *
 476 * This function scans the device tree for matching interrupt controller nodes,
 477 * and calls their initialization functions in order with parents first.
 478 */
 479void __init of_irq_init(const struct of_device_id *matches)
 480{


 489        for_each_matching_node_and_match(np, matches, &match) {
 490                if (!of_property_read_bool(np, "interrupt-controller") ||
 491                                !of_device_is_available(np))
 492                        continue;
 493

 508                desc->irq_init_cb = match->data; 
 514        }


 516        /*
 517         * The root irq controller is the one without an interrupt-parent.
 518         * That one goes first, followed by the controllers that reference it,
 519         * followed by the ones that reference the 2nd level controllers, etc.
 520         */
 521        while (!list_empty(&intc_desc_list)) {
 522                /*
 523                 * Process all controllers with the current 'parent'.
 524                 * First pass will be looking for NULL as the parent.
 525                 * The assumption is that NULL parent means a root controller.
 526                 */
 527                list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {


 540                        ret = desc->irq_init_cb(desc->dev,
 541                                                desc->interrupt_parent);

从 dtb 中找到,  名称匹配(比如,arm,gic-v3 )的 节点,  检查它属性  interrupt-controller 为真,就认为匹配到了。

508  -  记录  struct of_device_id  对象  的 data 到 desc->iqr_init_cb ( 其实就是  drivers/irqchip/irq-gic-v3.c 中的  gic_of_init 函数地址 )

540 ~ 541  调用 desc->iqr_init_cb 函数,就是调用 drivers/irqchip/irq-gic-v3.c 中的  gic_of_init 函数 。

gic_of_init

v5.10/drivers/irqchip/irq-gic-v3.c

1864 - gic_of_init 函数,在 1913 调用 gic_init_bases 函数

1640 - gic_init_bases 函数 在 1711 调用 gic_smp_init 函数

1152 - gic_smp_init 函数,cpuhp_setup_state_nocalls 设置 CPUHP_AP_IQR_GIC_STARTING 回调 gic_starting_cpu

1152static void __init gic_smp_init(void)
1153{

1160        cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
1161                                  "irqchip/arm/gicv3:starting",
1162                                  gic_starting_cpu, NULL);

1172}


1640static int __init gic_init_bases(void __iomem *dist_base,
1641                                 struct redist_region *rdist_regs,
1642                                 u32 nr_redist_regions,
1643                                 u64 redist_stride,
1644                                 struct fwnode_handle *handle)
1645{

1711        gic_smp_init();
1731}

1864static int __init gic_of_init(struct device_node *node, struct device_node *parent)
1865{

1913        err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
1914                             redist_stride, &node->fwnode);


1932}

 

cpuhp_setup_state_nocalls

又回到  include/linux/cpuhotplug.h 模块里面了。 设置状态回到函数,但是在设置时不回调。

 235/**
 236 * cpuhp_setup_state_nocalls - Setup hotplug state callbacks without calling the
 237 *                             callbacks
 238 * @state:      The state for which the calls are installed
 239 * @name:       Name of the callback.
 240 * @startup:    startup callback function
 241 * @teardown:   teardown callback function
 242 *
 243 * Same as @cpuhp_setup_state except that no calls are executed are invoked
 244 * during installation of this callback. NOP if SMP=n or HOTPLUG_CPU=n.
 245 */
 246static inline int cpuhp_setup_state_nocalls(enum cpuhp_state state,
 247                                            const char *name,
 248                                            int (*startup)(unsigned int cpu),
 249                                            int (*teardown)(unsigned int cpu))
 250{
 251        return __cpuhp_setup_state(state, name, false, startup, teardown,
 252                                   false);
 253}

下一篇: time_init() 调用到drivers\clocksource\arm_arch_timer.c中的arch_timer_of_init,注册CPUHP_AP_ARM_ARCH_TIMER_STARTING的回调函数

https://www.cnblogs.com/zhangzhiwei122/p/16092867.html

 

posted @ 2022-04-02 16:12  张志伟122  阅读(155)  评论(0编辑  收藏  举报