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