[Linux] SMP Bootcpu代碼閱讀記錄

online	可以被調度的
active	可以被遷移的
present	內核已接管的
possible	系統存在的CPU,但沒有被內核接管
cpu_down
	\->_cpu_down(cpu, 0)
		\->take_cpu_down
			\->__cpu_disable()
				\->mp_ops->cpu_disable()
        \->__cpu_die(cpu)

cpu_up
	\->_cpu_up
		\->__cpu_up
			\->mp_ops->boot_secondary(cpu, tidle)
start_kernel
    setup_arch
    arch_call_rest_init()--rest_init
        kernel_thread(kernel_init)
            kernel_init
                kernel_init_freeable
                    smp_prepare_cpus
                            	init_cpu_topology();
	                            this_cpu = smp_processor_id
	                            store_cpu_topology(this_cpu);
                                numa_store_cpu_info(this_cpu);
	                            numa_add_cpu(this_cpu);
	                            set_cpu_present(cpu, true);
		                        numa_store_cpu_info(cpu);
                    smp_init
                                idle_threads_init();            /*初始化各個cpu上的idle thread*/
	                            cpuhp_threads_init();           /*初始化各個cpu上的hotplug thread*/
	                                    smpboot_register_percpu_thread  /*smp thread 即是 cpuhp_threads--> cpuhp_thread_fun?*/
	                            cpu_up(cpu);
	                                    do_cpu_up(CPUHP_ONLINE)
	                                        try_online_node
	                                        _cpu_up
	                                                cpus_write_lock
	                                                idle_thread_get
	                                                cpuhp_set_state
	                                                cpuhp_kick_ap_work
	                                                        cpuhp_kick_ap
	                                                            __cpuhp_kick_ap(st);
	                                                                            smp_mb
	                                                                            wake_up_process(st-thread)
	                                                                            wait_for_ap_thread(st, st->bringup);
                                                                if ((ret = st->result)) {
		                                                            cpuhp_reset_state
		                                                            __cpuhp_kick_ap
	                                                           }
	                                                cpuhp_up_callbacks
	                                                        cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
	                                                                cbm(cpu, node)
	                           smp_cpus_done(setup_max_cpus);   /*Total of %d processors activated*/
	                                setup_cpu_features();
	                                hyp_mode_check();
	                                apply_alternatives_all();
	                                mark_linear_text_alias_ro();
        cpu_startup_entry()
            do_idle(CPU_ONLINE)
st-thread---------->cpuhp_thread_fun
    smp_mb
    cpuhp_lock_acquire
    cpuhp_invoke_callback
            hlist_for_each(node, &step->list) 
                cbm(cpu, node);
                        ******************
                        .bringup_cpu
                                __cpu_up
                                        secondary_data.task = idle;         /*設置起來的第一個task idle, stack, 關閉其MMU, 將dcache flush掉*/
	                                    secondary_data.stack = task_stack_page(idle) + THREAD_SIZE;
	                                    update_cpu_boot_status(CPU_MMU_OFF);
	                                    __flush_dcache_area(&secondary_data, sizeof(secondary_data));
	                                   boot_secondary
	                                        cpu_ops[cpu]->cpu_boot(cpu);
	                                            psci_ops.cpu_on(cpu_logical_map(cpu), __pa_symbol(secondary_entry));  /*從這裏將回kernel的地址帶下去, ENDPROC(secondary_entry)
定義在head.S裏面*/
                                bringup_wait_for_ap
                                    wait_for_ap_thread  /*Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE*/
                                    cpuhp_kick_ap
    cpuhp_lock_release
    complete_ap_thread
static struct cpuhp_step cpuhp_hp_states[] = {
	[CPUHP_OFFLINE] = {
		.name			= "offline",
		.startup.single		= NULL,
		.teardown.single	= NULL,
	},
#ifdef CONFIG_SMP
	[CPUHP_CREATE_THREADS]= {
		.name			= "threads:prepare",
		.startup.single		= smpboot_create_threads,
		.teardown.single	= NULL,
		.cant_stop		= true,
	},
	[CPUHP_PERF_PREPARE] = {
		.name			= "perf:prepare",
		.startup.single		= perf_event_init_cpu,
		.teardown.single	= perf_event_exit_cpu,
	},
	[CPUHP_WORKQUEUE_PREP] = {
		.name			= "workqueue:prepare",
		.startup.single		= workqueue_prepare_cpu,
		.teardown.single	= NULL,
	},
	[CPUHP_HRTIMERS_PREPARE] = {
		.name			= "hrtimers:prepare",
		.startup.single		= hrtimers_prepare_cpu,
		.teardown.single	= hrtimers_dead_cpu,
	},
	[CPUHP_SMPCFD_PREPARE] = {
		.name			= "smpcfd:prepare",
		.startup.single		= smpcfd_prepare_cpu,
		.teardown.single	= smpcfd_dead_cpu,
	},
	[CPUHP_RELAY_PREPARE] = {
		.name			= "relay:prepare",
		.startup.single		= relay_prepare_cpu,
		.teardown.single	= NULL,
	},
	[CPUHP_SLAB_PREPARE] = {
		.name			= "slab:prepare",
		.startup.single		= slab_prepare_cpu,
		.teardown.single	= slab_dead_cpu,
	},
	[CPUHP_RCUTREE_PREP] = {
		.name			= "RCU/tree:prepare",
		.startup.single		= rcutree_prepare_cpu,
		.teardown.single	= rcutree_dead_cpu,
	},
	/*
	 * On the tear-down path, timers_dead_cpu() must be invoked
	 * before blk_mq_queue_reinit_notify() from notify_dead(),
	 * otherwise a RCU stall occurs.
	 */
	[CPUHP_TIMERS_PREPARE] = {
		.name			= "timers:prepare",
		.startup.single		= timers_prepare_cpu,
		.teardown.single	= timers_dead_cpu,
	},
	/* Kicks the plugged cpu into life */
	[CPUHP_BRINGUP_CPU] = {
		.name			= "cpu:bringup",
		.startup.single		= bringup_cpu,
		.teardown.single	= NULL,
		.cant_stop		= true,
	},
	/* Final state before CPU kills itself */
	[CPUHP_AP_IDLE_DEAD] = {
		.name			= "idle:dead",
	},
	/*
	 * Last state before CPU enters the idle loop to die. Transient state
	 * for synchronization.
	 */
	[CPUHP_AP_OFFLINE] = {
		.name			= "ap:offline",
		.cant_stop		= true,
	},
	/* First state is scheduler control. Interrupts are disabled */
	[CPUHP_AP_SCHED_STARTING] = {
		.name			= "sched:starting",
		.startup.single		= sched_cpu_starting,
		.teardown.single	= sched_cpu_dying,
	},
	[CPUHP_AP_RCUTREE_DYING] = {
		.name			= "RCU/tree:dying",
		.startup.single		= NULL,
		.teardown.single	= rcutree_dying_cpu,
	},
	[CPUHP_AP_SMPCFD_DYING] = {
		.name			= "smpcfd:dying",
		.startup.single		= NULL,
		.teardown.single	= smpcfd_dying_cpu,
	},
	/* Entry state on starting. Interrupts enabled from here on. Transient
	 * state for synchronsization */
	[CPUHP_AP_ONLINE] = {
		.name			= "ap:online",
	},
	/*
	 * Handled on controll processor until the plugged processor manages
	 * this itself.
	 */
	[CPUHP_TEARDOWN_CPU] = {
		.name			= "cpu:teardown",
		.startup.single		= NULL,
		.teardown.single	= takedown_cpu,
		.cant_stop		= true,
	},
	/* Handle smpboot threads park/unpark */
	[CPUHP_AP_SMPBOOT_THREADS] = {
		.name			= "smpboot/threads:online",
		.startup.single		= smpboot_unpark_threads,
		.teardown.single	= smpboot_park_threads,
	},
	[CPUHP_AP_IRQ_AFFINITY_ONLINE] = {
		.name			= "irq/affinity:online",
		.startup.single		= irq_affinity_online_cpu,
		.teardown.single	= NULL,
	},
	[CPUHP_AP_PERF_ONLINE] = {
		.name			= "perf:online",
		.startup.single		= perf_event_init_cpu,
		.teardown.single	= perf_event_exit_cpu,
	},
	[CPUHP_AP_WATCHDOG_ONLINE] = {
		.name			= "lockup_detector:online",
		.startup.single		= lockup_detector_online_cpu,
		.teardown.single	= lockup_detector_offline_cpu,
	},
	[CPUHP_AP_WORKQUEUE_ONLINE] = {
		.name			= "workqueue:online",
		.startup.single		= workqueue_online_cpu,
		.teardown.single	= workqueue_offline_cpu,
	},
	[CPUHP_AP_RCUTREE_ONLINE] = {
		.name			= "RCU/tree:online",
		.startup.single		= rcutree_online_cpu,
		.teardown.single	= rcutree_offline_cpu,
	},
#endif
	/*
	 * The dynamically registered state space is here
	 */

#ifdef CONFIG_SMP
	/* Last state is scheduler control setting the cpu active */
	[CPUHP_AP_ACTIVE] = {
		.name			= "sched:active",
		.startup.single		= sched_cpu_activate,
		.teardown.single	= sched_cpu_deactivate,
	},
#endif

	/* CPU is fully up and running. */
	[CPUHP_ONLINE] = {
		.name			= "online",
		.startup.single		= NULL,
		.teardown.single	= NULL,
	},
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章