The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/init/main.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/init/main.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  *
    6  *  GK 2/5/95  -  Changed to support mounting root fs via NFS
    7  *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
    8  *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
    9  *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
   10  */
   11 
   12 #define __KERNEL_SYSCALLS__
   13 
   14 #include <linux/config.h>
   15 #include <linux/proc_fs.h>
   16 #include <linux/devfs_fs_kernel.h>
   17 #include <linux/unistd.h>
   18 #include <linux/string.h>
   19 #include <linux/ctype.h>
   20 #include <linux/delay.h>
   21 #include <linux/utsname.h>
   22 #include <linux/ioport.h>
   23 #include <linux/init.h>
   24 #include <linux/smp_lock.h>
   25 #include <linux/blk.h>
   26 #include <linux/hdreg.h>
   27 #include <linux/iobuf.h>
   28 #include <linux/bootmem.h>
   29 #include <linux/tty.h>
   30 
   31 #include <asm/io.h>
   32 #include <asm/bugs.h>
   33 
   34 #if defined(CONFIG_ARCH_S390)
   35 #include <asm/s390mach.h>
   36 #include <asm/ccwcache.h>
   37 #endif
   38 
   39 #ifdef CONFIG_ACPI
   40 #include <linux/acpi.h>
   41 #endif
   42 
   43 #ifdef CONFIG_PCI
   44 #include <linux/pci.h>
   45 #endif
   46 
   47 #ifdef CONFIG_DIO
   48 #include <linux/dio.h>
   49 #endif
   50 
   51 #ifdef CONFIG_ZORRO
   52 #include <linux/zorro.h>
   53 #endif
   54 
   55 #ifdef CONFIG_MTRR
   56 #  include <asm/mtrr.h>
   57 #endif
   58 
   59 #ifdef CONFIG_NUBUS
   60 #include <linux/nubus.h>
   61 #endif
   62 
   63 #ifdef CONFIG_ISAPNP
   64 #include <linux/isapnp.h>
   65 #endif
   66 
   67 #ifdef CONFIG_IRDA
   68 extern int irda_proto_init(void);
   69 extern int irda_device_init(void);
   70 #endif
   71 
   72 #ifdef CONFIG_X86_LOCAL_APIC
   73 #include <asm/smp.h>
   74 #endif
   75 
   76 /*
   77  * Versions of gcc older than that listed below may actually compile
   78  * and link okay, but the end product can have subtle run time bugs.
   79  * To avoid associated bogus bug reports, we flatly refuse to compile
   80  * with a gcc that is known to be too old from the very beginning.
   81  */
   82 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
   83 #error Sorry, your GCC is too old. It builds incorrect kernels.
   84 #endif
   85 
   86 extern char _stext, _etext;
   87 extern char *linux_banner;
   88 
   89 static int init(void *);
   90 
   91 extern void init_IRQ(void);
   92 extern void init_modules(void);
   93 extern void sock_init(void);
   94 extern void fork_init(unsigned long);
   95 extern void mca_init(void);
   96 extern void sbus_init(void);
   97 extern void ppc_init(void);
   98 extern void sysctl_init(void);
   99 extern void signals_init(void);
  100 extern int init_pcmcia_ds(void);
  101 
  102 extern void free_initmem(void);
  103 
  104 #ifdef CONFIG_TC
  105 extern void tc_init(void);
  106 #endif
  107 
  108 extern void ecard_init(void);
  109 
  110 #if defined(CONFIG_SYSVIPC)
  111 extern void ipc_init(void);
  112 #endif
  113 
  114 /*
  115  * Boot command-line arguments
  116  */
  117 #define MAX_INIT_ARGS 8
  118 #define MAX_INIT_ENVS 8
  119 
  120 extern void time_init(void);
  121 extern void softirq_init(void);
  122 
  123 int rows, cols;
  124 
  125 char *execute_command;
  126 
  127 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
  128 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
  129 
  130 static int __init profile_setup(char *str)
  131 {
  132     int par;
  133     if (get_option(&str,&par)) prof_shift = par;
  134         return 1;
  135 }
  136 
  137 __setup("profile=", profile_setup);
  138 
  139 static int __init checksetup(char *line)
  140 {
  141         struct kernel_param *p;
  142 
  143         p = &__setup_start;
  144         do {
  145                 int n = strlen(p->str);
  146                 if (!strncmp(line,p->str,n)) {
  147                         if (p->setup_func(line+n))
  148                                 return 1;
  149                 }
  150                 p++;
  151         } while (p < &__setup_end);
  152         return 0;
  153 }
  154 
  155 /* this should be approx 2 Bo*oMips to start (note initial shift), and will
  156    still work even if initially too large, it will just take slightly longer */
  157 unsigned long loops_per_jiffy = (1<<12);
  158 
  159 /* This is the number of bits of precision for the loops_per_jiffy.  Each
  160    bit takes on average 1.5/HZ seconds.  This (like the original) is a little
  161    better than 1% */
  162 #define LPS_PREC 8
  163 
  164 void __init calibrate_delay(void)
  165 {
  166         unsigned long ticks, loopbit;
  167         int lps_precision = LPS_PREC;
  168 
  169         loops_per_jiffy = (1<<12);
  170 
  171         printk("Calibrating delay loop... ");
  172         while (loops_per_jiffy <<= 1) {
  173                 /* wait for "start of" clock tick */
  174                 ticks = jiffies;
  175                 while (ticks == jiffies)
  176                         /* nothing */;
  177                 /* Go .. */
  178                 ticks = jiffies;
  179                 __delay(loops_per_jiffy);
  180                 ticks = jiffies - ticks;
  181                 if (ticks)
  182                         break;
  183         }
  184 
  185 /* Do a binary approximation to get loops_per_jiffy set to equal one clock
  186    (up to lps_precision bits) */
  187         loops_per_jiffy >>= 1;
  188         loopbit = loops_per_jiffy;
  189         while ( lps_precision-- && (loopbit >>= 1) ) {
  190                 loops_per_jiffy |= loopbit;
  191                 ticks = jiffies;
  192                 while (ticks == jiffies);
  193                 ticks = jiffies;
  194                 __delay(loops_per_jiffy);
  195                 if (jiffies != ticks)   /* longer than 1 tick */
  196                         loops_per_jiffy &= ~loopbit;
  197         }
  198 
  199 /* Round the value and print it */      
  200         printk("%lu.%02lu BogoMIPS\n",
  201                 loops_per_jiffy/(500000/HZ),
  202                 (loops_per_jiffy/(5000/HZ)) % 100);
  203 }
  204 
  205 static int __init debug_kernel(char *str)
  206 {
  207         if (*str)
  208                 return 0;
  209         console_loglevel = 10;
  210         return 1;
  211 }
  212 
  213 static int __init quiet_kernel(char *str)
  214 {
  215         if (*str)
  216                 return 0;
  217         console_loglevel = 4;
  218         return 1;
  219 }
  220 
  221 __setup("debug", debug_kernel);
  222 __setup("quiet", quiet_kernel);
  223 
  224 /*
  225  * This is a simple kernel command line parsing function: it parses
  226  * the command line, and fills in the arguments/environment to init
  227  * as appropriate. Any cmd-line option is taken to be an environment
  228  * variable if it contains the character '='.
  229  *
  230  * This routine also checks for options meant for the kernel.
  231  * These options are not given to init - they are for internal kernel use only.
  232  */
  233 static void __init parse_options(char *line)
  234 {
  235         char *next,*quote;
  236         int args, envs;
  237 
  238         if (!*line)
  239                 return;
  240         args = 0;
  241         envs = 1;       /* TERM is set to 'linux' by default */
  242         next = line;
  243         while ((line = next) != NULL) {
  244                 quote = strchr(line,'"');
  245                 next = strchr(line, ' ');
  246                 while (next != NULL && quote != NULL && quote < next) {
  247                         /* we found a left quote before the next blank
  248                          * now we have to find the matching right quote
  249                          */
  250                         next = strchr(quote+1, '"');
  251                         if (next != NULL) {
  252                                 quote = strchr(next+1, '"');
  253                                 next = strchr(next+1, ' ');
  254                         }
  255                 }
  256                 if (next != NULL)
  257                         *next++ = 0;
  258                 if (!strncmp(line,"init=",5)) {
  259                         line += 5;
  260                         execute_command = line;
  261                         /* In case LILO is going to boot us with default command line,
  262                          * it prepends "auto" before the whole cmdline which makes
  263                          * the shell think it should execute a script with such name.
  264                          * So we ignore all arguments entered _before_ init=... [MJ]
  265                          */
  266                         args = 0;
  267                         continue;
  268                 }
  269                 if (checksetup(line))
  270                         continue;
  271                 
  272                 /*
  273                  * Then check if it's an environment variable or
  274                  * an option.
  275                  */
  276                 if (strchr(line,'=')) {
  277                         if (envs >= MAX_INIT_ENVS)
  278                                 break;
  279                         envp_init[++envs] = line;
  280                 } else {
  281                         if (args >= MAX_INIT_ARGS)
  282                                 break;
  283                         if (*line)
  284                                 argv_init[++args] = line;
  285                 }
  286         }
  287         argv_init[args+1] = NULL;
  288         envp_init[envs+1] = NULL;
  289 }
  290 
  291 
  292 extern void setup_arch(char **);
  293 extern void cpu_idle(void);
  294 
  295 unsigned long wait_init_idle;
  296 
  297 #ifndef CONFIG_SMP
  298 
  299 #ifdef CONFIG_X86_LOCAL_APIC
  300 static void __init smp_init(void)
  301 {
  302         APIC_init_uniprocessor();
  303 }
  304 #else
  305 #define smp_init()      do { } while (0)
  306 #endif
  307 
  308 #else
  309 
  310 
  311 /* Called by boot processor to activate the rest. */
  312 static void __init smp_init(void)
  313 {
  314         /* Get other processors into their bootup holding patterns. */
  315         smp_boot_cpus();
  316         wait_init_idle = cpu_online_map;
  317         clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */
  318 
  319         smp_threads_ready=1;
  320         smp_commence();
  321 
  322         /* Wait for the other cpus to set up their idle processes */
  323         printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle);
  324         while (wait_init_idle) {
  325                 cpu_relax();
  326                 barrier();
  327         }
  328         printk("All processors have done init_idle\n");
  329 }
  330 
  331 #endif
  332 
  333 /*
  334  * We need to finalize in a non-__init function or else race conditions
  335  * between the root thread and the init thread may cause start_kernel to
  336  * be reaped by free_initmem before the root thread has proceeded to
  337  * cpu_idle.
  338  */
  339 
  340 static void rest_init(void)
  341 {
  342         kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
  343         unlock_kernel();
  344         current->need_resched = 1;
  345         cpu_idle();
  346 } 
  347 
  348 /*
  349  *      Activate the first processor.
  350  */
  351 
  352 asmlinkage void __init start_kernel(void)
  353 {
  354         char * command_line;
  355         extern char saved_command_line[];
  356 /*
  357  * Interrupts are still disabled. Do necessary setups, then
  358  * enable them
  359  */
  360         lock_kernel();
  361         printk(linux_banner);
  362         setup_arch(&command_line);
  363         printk("Kernel command line: %s\n", saved_command_line);
  364         parse_options(command_line);
  365         trap_init();
  366         init_IRQ();
  367         sched_init();
  368         softirq_init();
  369         time_init();
  370 
  371         /*
  372          * HACK ALERT! This is early. We're enabling the console before
  373          * we've done PCI setups etc, and console_init() must be aware of
  374          * this. But we do want output early, in case something goes wrong.
  375          */
  376         console_init();
  377 #ifdef CONFIG_MODULES
  378         init_modules();
  379 #endif
  380         if (prof_shift) {
  381                 unsigned int size;
  382                 /* only text is profiled */
  383                 prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
  384                 prof_len >>= prof_shift;
  385                 
  386                 size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
  387                 prof_buffer = (unsigned int *) alloc_bootmem(size);
  388         }
  389 
  390         kmem_cache_init();
  391         sti();
  392         calibrate_delay();
  393 #ifdef CONFIG_BLK_DEV_INITRD
  394         if (initrd_start && !initrd_below_start_ok &&
  395                         initrd_start < min_low_pfn << PAGE_SHIFT) {
  396                 printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
  397                     "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
  398                 initrd_start = 0;
  399         }
  400 #endif
  401         mem_init();
  402         kmem_cache_sizes_init();
  403         pgtable_cache_init();
  404 
  405         /*
  406          * For architectures that have highmem, num_mappedpages represents
  407          * the amount of memory the kernel can use.  For other architectures
  408          * it's the same as the total pages.  We need both numbers because
  409          * some subsystems need to initialize based on how much memory the
  410          * kernel can use.
  411          */
  412         if (num_mappedpages == 0)
  413                 num_mappedpages = num_physpages;
  414   
  415         fork_init(num_mappedpages);
  416         proc_caches_init();
  417         vfs_caches_init(num_physpages);
  418         buffer_init(num_physpages);
  419         page_cache_init(num_physpages);
  420 #if defined(CONFIG_ARCH_S390)
  421         ccwcache_init();
  422 #endif
  423         signals_init();
  424 #ifdef CONFIG_PROC_FS
  425         proc_root_init();
  426 #endif
  427 #if defined(CONFIG_SYSVIPC)
  428         ipc_init();
  429 #endif
  430         check_bugs();
  431         printk("POSIX conformance testing by UNIFIX\n");
  432 
  433         /* 
  434          *      We count on the initial thread going ok 
  435          *      Like idlers init is an unlocked kernel thread, which will
  436          *      make syscalls (and thus be locked).
  437          */
  438         smp_init();
  439         rest_init();
  440 }
  441 
  442 struct task_struct *child_reaper = &init_task;
  443 
  444 static void __init do_initcalls(void)
  445 {
  446         initcall_t *call;
  447 
  448         call = &__initcall_start;
  449         do {
  450                 (*call)();
  451                 call++;
  452         } while (call < &__initcall_end);
  453 
  454         /* Make sure there is no pending stuff from the initcall sequence */
  455         flush_scheduled_tasks();
  456 }
  457 
  458 /*
  459  * Ok, the machine is now initialized. None of the devices
  460  * have been touched yet, but the CPU subsystem is up and
  461  * running, and memory and process management works.
  462  *
  463  * Now we can finally start doing some real work..
  464  */
  465 static void __init do_basic_setup(void)
  466 {
  467 
  468         /*
  469          * Tell the world that we're going to be the grim
  470          * reaper of innocent orphaned children.
  471          *
  472          * We don't want people to have to make incorrect
  473          * assumptions about where in the task array this
  474          * can be found.
  475          */
  476         child_reaper = current;
  477 
  478 #if defined(CONFIG_MTRR)        /* Do this after SMP initialization */
  479 /*
  480  * We should probably create some architecture-dependent "fixup after
  481  * everything is up" style function where this would belong better
  482  * than in init/main.c..
  483  */
  484         mtrr_init();
  485 #endif
  486 
  487 #ifdef CONFIG_SYSCTL
  488         sysctl_init();
  489 #endif
  490 
  491         /*
  492          * Ok, at this point all CPU's should be initialized, so
  493          * we can start looking into devices..
  494          */
  495 #if defined(CONFIG_ARCH_S390)
  496         s390_init_machine_check();
  497 #endif
  498 #ifdef CONFIG_ACPI_INTERPRETER
  499         acpi_init();
  500 #endif
  501 #ifdef CONFIG_PCI
  502         pci_init();
  503 #endif
  504 #ifdef CONFIG_SBUS
  505         sbus_init();
  506 #endif
  507 #if defined(CONFIG_PPC)
  508         ppc_init();
  509 #endif
  510 #ifdef CONFIG_MCA
  511         mca_init();
  512 #endif
  513 #ifdef CONFIG_ARCH_ACORN
  514         ecard_init();
  515 #endif
  516 #ifdef CONFIG_ZORRO
  517         zorro_init();
  518 #endif
  519 #ifdef CONFIG_DIO
  520         dio_init();
  521 #endif
  522 #ifdef CONFIG_NUBUS
  523         nubus_init();
  524 #endif
  525 #ifdef CONFIG_ISAPNP
  526         isapnp_init();
  527 #endif
  528 #ifdef CONFIG_TC
  529         tc_init();
  530 #endif
  531 
  532         /* Networking initialization needs a process context */ 
  533         sock_init();
  534 
  535         start_context_thread();
  536         do_initcalls();
  537 
  538 #ifdef CONFIG_IRDA
  539         irda_proto_init();
  540         irda_device_init(); /* Must be done after protocol initialization */
  541 #endif
  542 #ifdef CONFIG_PCMCIA
  543         init_pcmcia_ds();               /* Do this last */
  544 #endif
  545 }
  546 
  547 extern void prepare_namespace(void);
  548 
  549 static int init(void * unused)
  550 {
  551         lock_kernel();
  552         do_basic_setup();
  553 
  554         prepare_namespace();
  555 
  556         /*
  557          * Ok, we have completed the initial bootup, and
  558          * we're essentially up and running. Get rid of the
  559          * initmem segments and start the user-mode stuff..
  560          */
  561         free_initmem();
  562         unlock_kernel();
  563 
  564         if (open("/dev/console", O_RDWR, 0) < 0)
  565                 printk("Warning: unable to open an initial console.\n");
  566 
  567         (void) dup(0);
  568         (void) dup(0);
  569         
  570         /*
  571          * We try each of these until one succeeds.
  572          *
  573          * The Bourne shell can be used instead of init if we are 
  574          * trying to recover a really broken machine.
  575          */
  576 
  577         if (execute_command)
  578                 execve(execute_command,argv_init,envp_init);
  579         execve("/sbin/init",argv_init,envp_init);
  580         execve("/etc/init",argv_init,envp_init);
  581         execve("/bin/init",argv_init,envp_init);
  582         execve("/bin/sh",argv_init,envp_init);
  583         panic("No init found.  Try passing init= option to kernel.");
  584 }

Cache object: f790ed8dc6d5d816a7102e95cfd161b9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.