Linux Platform bus Init

目录

Linux Platform bus Init

代码流程

1. start_kernel

2. rest_init

3. kernel_init

4. do_basic_setup

5. driver_init

6. platform_bus_init


Linux Platform bus Init


 

  • 在Linux启动的时候自动调用,注册platform总线,名字为platform,并初始化总线。

代码流程


基于kernel4.19

1. start_kernel

562asmlinkage __visible void __init start_kernel(void)
563{
564	char *command_line;
565	char *after_dashes;
566
567	set_task_stack_end_magic(&init_task);
568	smp_setup_processor_id();
569	debug_objects_early_init();
570
571	cgroup_init_early();
572
573	local_irq_disable();
574	early_boot_irqs_disabled = true;
575
576	/*
577	 * Interrupts are still disabled. Do necessary setups, then
578	 * enable them.
579	 */
580	boot_cpu_init();
581	page_address_init();
582	pr_notice("%s", linux_banner);
583	setup_arch(&command_line);
584	mm_init_cpumask(&init_mm);
585	setup_command_line(command_line);
586	setup_nr_cpu_ids();
587	setup_per_cpu_areas();
588	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
589	boot_cpu_hotplug_init();
590
591	build_all_zonelists(NULL);
592	page_alloc_init();
593
594	pr_notice("Kernel command line: %s\n", boot_command_line);
595	/* parameters may set static keys */
596	jump_label_init();
597	parse_early_param();
598	after_dashes = parse_args("Booting kernel",
599				  static_command_line, __start___param,
600				  __stop___param - __start___param,
601				  -1, -1, NULL, &unknown_bootoption);
602	if (!IS_ERR_OR_NULL(after_dashes))
603		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
604			   NULL, set_init_arg);
605
606	/*
607	 * These use large bootmem allocations and must precede
608	 * kmem_cache_init()
609	 */
610	setup_log_buf(0);
611	vfs_caches_init_early();
612	sort_main_extable();
613	trap_init();
614	mm_init();
615
616	ftrace_init();
617
618	/* trace_printk can be enabled here */
619	early_trace_init();
620
621	/*
622	 * Set up the scheduler prior starting any interrupts (such as the
623	 * timer interrupt). Full topology setup happens at smp_init()
624	 * time - but meanwhile we still have a functioning scheduler.
625	 */
626	sched_init();
627	/*
628	 * Disable preemption - early bootup scheduling is extremely
629	 * fragile until we cpu_idle() for the first time.
630	 */
631	preempt_disable();
632	if (WARN(!irqs_disabled(),
633		 "Interrupts were enabled *very* early, fixing it\n"))
634		local_irq_disable();
635	radix_tree_init();
636
637	/*
638	 * Set up housekeeping before setting up workqueues to allow the unbound
639	 * workqueue to take non-housekeeping into account.
640	 */
641	housekeeping_init();
642
643	/*
644	 * Allow workqueue creation and work item queueing/cancelling
645	 * early.  Work item execution depends on kthreads and starts after
646	 * workqueue_init().
647	 */
648	workqueue_init_early();
649
650	rcu_init();
651
652	/* Trace events are available after this */
653	trace_init();
654
655	if (initcall_debug)
656		initcall_debug_enable();
657
658	context_tracking_init();
659	/* init some links before init_ISA_irqs() */
660	early_irq_init();
661	init_IRQ();
662	tick_init();
663	rcu_init_nohz();
664	init_timers();
665	hrtimers_init();
666	softirq_init();
667	timekeeping_init();
668
669	/*
670	 * For best initial stack canary entropy, prepare it after:
671	 * - setup_arch() for any UEFI RNG entropy and boot cmdline access
672	 * - timekeeping_init() for ktime entropy used in rand_initialize()
673	 * - rand_initialize() to get any arch-specific entropy like RDRAND
674	 * - add_latent_entropy() to get any latent entropy
675	 * - adding command line entropy
676	 */
677	rand_initialize();
678	add_latent_entropy();
679	add_device_randomness(command_line, strlen(command_line));
680	boot_init_stack_canary();
681
682	time_init();
683	perf_event_init();
684	profile_init();
685	call_function_init();
686	WARN(!irqs_disabled(), "Interrupts were enabled early\n");
687
688	early_boot_irqs_disabled = false;
689	local_irq_enable();
690
691	kmem_cache_init_late();
692
693	/*
694	 * HACK ALERT! This is early. We're enabling the console before
695	 * we've done PCI setups etc, and console_init() must be aware of
696	 * this. But we do want output early, in case something goes wrong.
697	 */
698	console_init();
699	if (panic_later)
700		panic("Too many boot %s vars at `%s'", panic_later,
701		      panic_param);
702
703	lockdep_init();
704
705	/*
706	 * Need to run this when irqs are enabled, because it wants
707	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
708	 * too:
709	 */
710	locking_selftest();
711
712	/*
713	 * This needs to be called before any devices perform DMA
714	 * operations that might use the SWIOTLB bounce buffers. It will
715	 * mark the bounce buffers as decrypted so that their usage will
716	 * not cause "plain-text" data to be decrypted when accessed.
717	 */
718	mem_encrypt_init();
719
720#ifdef CONFIG_BLK_DEV_INITRD
721	if (initrd_start && !initrd_below_start_ok &&
722	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
723		pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
724		    page_to_pfn(virt_to_page((void *)initrd_start)),
725		    min_low_pfn);
726		initrd_start = 0;
727	}
728#endif
729	kmemleak_init();
730	debug_objects_mem_init();
731	setup_per_cpu_pageset();
732	numa_policy_init();
733	acpi_early_init();
734	if (late_time_init)
735		late_time_init();
736	sched_clock_init();
737	calibrate_delay();
738	pid_idr_init();
739	anon_vma_init();
740#ifdef CONFIG_X86
741	if (efi_enabled(EFI_RUNTIME_SERVICES))
742		efi_enter_virtual_mode();
743#endif
744	thread_stack_cache_init();
745	cred_init();
746	fork_init();
747	proc_caches_init();
748	uts_ns_init();
749	buffer_init();
750	key_init();
751	security_init();
752	dbg_late_init();
753	vfs_caches_init();
754	pagecache_init();
755	signals_init();
756	seq_file_init();
757	proc_root_init();
758	nsfs_init();
759	cpuset_init();
760	cgroup_init();
761	taskstats_init_early();
762	delayacct_init();
763
764	check_bugs();
765
766	acpi_subsystem_init();
767	arch_post_acpi_subsys_init();
768	sfi_init_late();
769
770	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
771		efi_free_boot_services();
772	}
773
774	/* Do the rest non-__init'ed, we're now alive */
775	rest_init();
776
777	prevent_tail_call_optimization();
778}

2. rest_init

402static noinline void __ref rest_init(void)
403{
404	struct task_struct *tsk;
405	int pid;
406
407	rcu_scheduler_starting();
408	/*
409	 * We need to spawn init first so that it obtains pid 1, however
410	 * the init task will end up wanting to create kthreads, which, if
411	 * we schedule it before we create kthreadd, will OOPS.
412	 */
413	pid = kernel_thread(kernel_init, NULL, CLONE_FS);
414	/*
415	 * Pin init on the boot CPU. Task migration is not properly working
416	 * until sched_init_smp() has been run. It will set the allowed
417	 * CPUs for init to the non isolated CPUs.
418	 */
419	rcu_read_lock();
420	tsk = find_task_by_pid_ns(pid, &init_pid_ns);
421	set_cpus_allowed_ptr(tsk, cpumask_of(smp_processor_id()));
422	rcu_read_unlock();
423
424	numa_default_policy();
425	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
426	rcu_read_lock();
427	kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
428	rcu_read_unlock();
429
430	/*
431	 * Enable might_sleep() and smp_processor_id() checks.
432	 * They cannot be enabled earlier because with CONFIG_PREEMPT=y
433	 * kernel_thread() would trigger might_sleep() splats. With
434	 * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled
435	 * already, but it's stuck on the kthreadd_done completion.
436	 */
437	system_state = SYSTEM_SCHEDULING;
438
439	complete(&kthreadd_done);
440
441	/*
442	 * The boot idle thread must execute schedule()
443	 * at least once to get things moving:
444	 */
445	schedule_preempt_disabled();
446	/* Call into cpu_idle with preempt disabled */
447	cpu_startup_entry(CPUHP_ONLINE);
448}

3. kernel_init

1110static int __ref kernel_init(void *unused)
1111{
1112	int ret;
1113
1114	kernel_init_freeable();
1115	/* need to finish all async __init code before freeing the memory */
1116	async_synchronize_full();
1117	ftrace_free_init_mem();
1118	jump_label_invalidate_initmem();
1119	free_initmem();
1120	mark_readonly();
1121
1122	/*
1123	 * Kernel mappings are now finalized - update the userspace page-table
1124	 * to finalize PTI.
1125	 */
1126	pti_finalize();
1127
1128	system_state = SYSTEM_RUNNING;
1129	numa_default_policy();
1130
1131	rcu_end_inkernel_boot();
1132
1133	if (ramdisk_execute_command) {
1134		ret = run_init_process(ramdisk_execute_command);
1135		if (!ret)
1136			return 0;
1137		pr_err("Failed to execute %s (error %d)\n",
1138		       ramdisk_execute_command, ret);
1139	}
1140
1141	/*
1142	 * We try each of these until one succeeds.
1143	 *
1144	 * The Bourne shell can be used instead of init if we are
1145	 * trying to recover a really broken machine.
1146	 */
1147	if (execute_command) {
1148		ret = run_init_process(execute_command);
1149		if (!ret)
1150			return 0;
1151		panic("Requested init %s failed (error %d).",
1152		      execute_command, ret);
1153	}
1154	if (!try_to_run_init_process("/sbin/init") ||
1155	    !try_to_run_init_process("/etc/init") ||
1156	    !try_to_run_init_process("/bin/init") ||
1157	    !try_to_run_init_process("/bin/sh"))
1158		return 0;
1159
1160	panic("No working init found.  Try passing init= option to kernel. "
1161	      "See Linux Documentation/admin-guide/init.rst for guidance.");
1162}

# kernel_init_freeable
1164static noinline void __init kernel_init_freeable(void)
1165{
1166	/*
1167	 * Wait until kthreadd is all set-up.
1168	 */
1169	wait_for_completion(&kthreadd_done);
1170
1171	/* Now the scheduler is fully set up and can do blocking allocations */
1172	gfp_allowed_mask = __GFP_BITS_MASK;
1173
1174	/*
1175	 * init can allocate pages on any node
1176	 */
1177	set_mems_allowed(node_states[N_MEMORY]);
1178
1179	cad_pid = task_pid(current);
1180
1181	smp_prepare_cpus(setup_max_cpus);
1182
1183	workqueue_init();
1184
1185	init_mm_internals();
1186
1187	do_pre_smp_initcalls();
1188	lockup_detector_init();
1189
1190	smp_init();
1191	sched_init_smp();
1192
1193	page_alloc_init_late();
1194	/* Initialize page ext after all struct pages are initialized. */
1195	page_ext_init();
1196
1197	do_basic_setup();
1198
1199	/* Open the /dev/console on the rootfs, this should never fail */
1200	if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
1201		pr_err("Warning: unable to open an initial console.\n");
1202
1203	(void) ksys_dup(0);
1204	(void) ksys_dup(0);
1205	/*
1206	 * check if there is an early userspace init.  If yes, let it do all
1207	 * the work
1208	 */
1209
1210	if (!ramdisk_execute_command)
1211		ramdisk_execute_command = "/init";
1212
1213	if (ksys_access((const char __user *)
1214			ramdisk_execute_command, 0) != 0) {
1215		ramdisk_execute_command = NULL;
1216		prepare_namespace();
1217	}
1218
1219	/*
1220	 * Ok, we have completed the initial bootup, and
1221	 * we're essentially up and running. Get rid of the
1222	 * initmem segments and start the user-mode stuff..
1223	 *
1224	 * rootfs is available now, try loading the public keys
1225	 * and default modules
1226	 */
1227
1228	integrity_load_keys();
1229	load_default_modules();
1230}
1231

4. do_basic_setup

1015/*
1016 * Ok, the machine is now initialized. None of the devices
1017 * have been touched yet, but the CPU subsystem is up and
1018 * running, and memory and process management works.
1019 *
1020 * Now we can finally start doing some real work..
1021 */
1022static void __init do_basic_setup(void)
1023{
1024	cpuset_init_smp();
1025	shmem_init();
1026	driver_init();
1027	init_irq_proc();
1028	do_ctors();
1029	usermodehelper_enable();
1030	do_initcalls();
1031}
1032

5. driver_init

14/**
15 * driver_init - initialize driver model.
16 *
17 * Call the driver model init functions to initialize their
18 * subsystems. Called early from init/main.c.
19 */
20void __init driver_init(void)
21{
22	/* These are the core pieces */
23	devtmpfs_init();
24	devices_init();
25	buses_init();
26	classes_init();
27	firmware_init();
28	hypervisor_init();
29
30	/* These are also core pieces, but must come after the
31	 * core core pieces.
32	 */
33	of_core_init();
34	platform_bus_init();
35	cpu_dev_init();
36	memory_dev_init();
37	container_dev_init();
38}

6. platform_bus_init

1188int __init platform_bus_init(void)
1189{
1190	int error;
1191
1192	early_platform_cleanup();
1193
1194	error = device_register(&platform_bus);
1195	if (error) {
1196		put_device(&platform_bus);
1197		return error;
1198	}
1199	error =  bus_register(&platform_bus_type);
1200	if (error)
1201		device_unregister(&platform_bus);
1202	of_platform_register_reconfig_notifier();
1203	return error;
1204}
1205
  •  进行一些早期的平台清理 
  • 注册设备 (在/sys/devices/目录下建立 platform目录对应的设备对象  /sys/devices/platform/) 
  • 将Platform bus总线注册进系统
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

打个工而已

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

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

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

打赏作者

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

抵扣说明:

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

余额充值