chapter5: network device initialization.
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern char saved_command_line[];
extern struct kernel_param __start___param[], __stop___param[];
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
lock_kernel();
printk(linux_banner);
setup_arch(&command_line);
setup_per_zone_pages_min();
setup_per_cpu_areas();
/*
* Mark the boot cpu "online" so that it can call console drivers in
* printk() and can access its per-cpu storage.
*/
smp_prepare_boot_cpu();
build_all_zonelists();
page_alloc_init();
printk("Kernel command line: %s\n", saved_command_line);
parse_args("Booting kernel", command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
trap_init();
rcu_init();
init_IRQ();
pidhash_init();
sched_init();
softirq_init();
time_init();
/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
console_init();
profile_init();
local_irq_enable();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
initrd_start < min_low_pfn << PAGE_SHIFT) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
"disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
initrd_start = 0;
}
#endif
page_address_init();
mem_init();
kmem_cache_init();
if (late_time_init)
late_time_init();
calibrate_delay();
pidmap_init();
pgtable_cache_init();
pte_chain_init();
fork_init(num_physpages);
proc_caches_init();
buffer_init();
security_scaffolding_startup();
vfs_caches_init(num_physpages);
radix_tree_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
populate_rootfs();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
check_bugs();
printk("POSIX conformance testing by UNIFIX\n");
/*
* We count on the initial thread going ok
* Like idlers init is an unlocked kernel thread, which will
* make syscalls (and thus be locked).
*/
init_idle(current, smp_processor_id());
/* Do the rest non-__init'ed, we're now alive */
rest_init();
}
static void rest_init(void)
{
kernel_thread(init, NULL, CLONE_KERNEL);
unlock_kernel();
cpu_idle();
}
static int init(void * unused)
{
lock_kernel();
/*
* Tell the world that we're going to be the grim
* reaper of innocent orphaned children.
*
* We don't want people to have to make incorrect
* assumptions about where in the task array this
* can be found.
*/
child_reaper = current;
/* Sets up cpus_possible() */
smp_prepare_cpus(max_cpus);
do_pre_smp_initcalls();
smp_init();
do_basic_setup();
prepare_namespace();
/*
* Ok, we have completed the initial bootup, and
* we're essentially up and running. Get rid of the
* initmem segments and start the user-mode stuff..
*/
free_initmem();
unlock_kernel();
system_running = 1;
if (open("/dev/console", O_RDWR, 0) < 0)
printk("Warning: unable to open an initial console.\n");
(void) dup(0);
(void) dup(0);
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command)
run_init_process(execute_command);
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel.");
}
static void __init do_basic_setup(void)
{
driver_init();
#ifdef CONFIG_SYSCTL
sysctl_init();
#endif
/* Networking initialization needs a process context */
sock_init();
init_workqueues();
do_initcalls();
}
static void __init do_initcalls(void)
{
initcall_t *call;
int count = preempt_count();
for (call = &__initcall_start; call < &__initcall_end; call++) {
char *msg;
if (initcall_debug)
printk("calling initcall 0x%p\n", *call);
(*call)();
msg = NULL;
if (preempt_count() != count) {
msg = "preemption imbalance";
preempt_count() = count;
}
if (irqs_disabled()) {
msg = "disabled interrupts";
local_irq_enable();
}
if (msg) {
printk("error in initcall at 0x%p: "
"returned with %s\n", *call, msg);
510,4-16 82%
static void __init do_initcalls(void)
{
initcall_t *call;
int count = preempt_count();
for (call = &__initcall_start; call < &__initcall_end; call++) {
char *msg;
if (initcall_debug)
printk("calling initcall 0x%p\n", *call);
(*call)();
msg = NULL;
if (preempt_count() != count) {
msg = "preemption imbalance";
preempt_count() = count;
}
if (irqs_disabled()) {
msg = "disabled interrupts";
local_irq_enable();
}
if (msg) {
printk("error in initcall at 0x%p: "
"returned with %s\n", *call, msg);
}
}
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}