start_kernel

来源:互联网 发布:小蚁科技 知乎 编辑:程序博客网 时间:2024/05/17 08:11
01.void __init x86_64_start_kernel(char * real_mode_data)  02.{  03.    int i;  04.  05.    /* 内核映像和模块区域映射的完整性检查 */  06.    ...  07.  08.    /* clear bss before set_intr_gate with early_idt_handler */  09.    clear_bss();  10.  11.    /* Make NULL pointers segfault */  12.    zap_identity_mappings();  13.  14.    /* KERNEL_IMAGE_START = 0xffffffff80000000UL    KERNEL_IMAGE_SIZE = 512M 15.     * PAGE_OFFSET =    0xffff880000000000UL    PAGE_SHIFT =        12 16.     */  17.    max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;  18.  19.    for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)  // segment.h中定义NUM_EXCEPTION_VECTORS = 32   20.        set_intr_gate(i, early_idt_handler);    // 往idt_table[i]数组中写入一个门描述符,处理函数是early_idt_handler   21.  22.    /* struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table }; 23.     * lidt汇编指令利用idt_descr变量初始化idtr寄存器,NR_VECTORS = 256 */  24.    load_idt((const struct desc_ptr *)&idt_descr);  25.  26.    x86_64_start_reservations(real_mode_data);  27.}  28.  29.static void __init zap_identity_mappings(void)  30.{  31.    /* (pgd_t *)(init_mm.pgd + pgd_index(addr)) = (pgd_t)0 */  32.    pgd_t *pgd = pgd_offset_k(0UL);  33.    pgd_clear(pgd);  34.  35.    /* Read-Modify-Write to CR4 */  36.    __flush_tlb_all();  37.}  38.  39.static void __init clear_bss(void)  40.{ memset(__bss_start, 0, (unsigned long) __bss_stop - (unsigned long) __bss_start); }  41.  42.static void __init copy_bootdata(char *real_mode_data)  43.{  44.    char * command_line;  45.  46.    memcpy(&boot_params, real_mode_data, sizeof boot_params);  47.    if (boot_params.hdr.cmd_line_ptr) {  48.        command_line = __va(boot_params.hdr.cmd_line_ptr);  49.        memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);  50.    }  51.}  52.void __init x86_64_start_reservations(char *real_mode_data)  53.{  54.    copy_bootdata(__va(real_mode_data));  55.    memblock_init();  56.    memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");  57.  58.#ifdef CONFIG_BLK_DEV_INITRD   59.    /* Reserve INITRD */  60.    if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {  61.        /* Assume only end is not page aligned */  62.        unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;  63.        unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;  64.        unsigned long ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);  65.        memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");  66.    }  67.#endif   68.  69.    reserve_ebda_region();  70.    /* At this point everything still needed from the boot loader or BIOS or kernel text  71.     * should be early reserved or marked not RAM in e820. All other memory is free game. */  72.    start_kernel();  73.}  74.  75.  76.asmlinkage void __init start_kernel(void)  77.{  78.    char * command_line;  79.    extern const struct kernel_param __start___param[], __stop___param[];  80.  81.    /* 当只有一个CPU的时候这个函数什么都不做,SMP时,返回在启动的时候的那个CPU号 */  82.    smp_setup_processor_id();  83.  84.    /* Need to run as early as possible, to initialize the lockdep hash: */  85.    lockdep_init();  86.    debug_objects_early_init();  87.  88.    /* Set up the the initial canary ASAP: */  89.    boot_init_stack_canary();  90.    cgroup_init_early();    /* 系统启动时的cgroup初始化,初始化那些要求early init的子系统 */  91.    local_irq_disable();  92.    early_boot_irqs_disabled = true;  93.    /* Interrupts are still disabled. Do necessary setups, then enable them */  94.    tick_init();  95.    boot_cpu_init();  96.    /* 初始化页地址,使用链表将其链接起来 */  97.    page_address_init();  98.    printk(KERN_NOTICE "%s", linux_banner);  99.  100.    /* 体系结构相关函数,由源码树顶层目录下的Makefile中的ARCH变量决定 */  101.    setup_arch(&command_line);  102.    mm_init_owner(&init_mm, &init_task);    /* init_mm.owner = &init_task */  103.    mm_init_cpumask(&init_mm);  104.    setup_command_line(command_line);  105.    setup_nr_cpu_ids();         /* nr_cpu_ids = NR_CPUS */  106.    setup_per_cpu_areas();  107.    smp_prepare_boot_cpu();         /* arch-specific boot-cpu hooks */  108.  109.    build_all_zonelists(NULL);  110.    page_alloc_init();  111.  112.    printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);  113.  114.    /* 对内核选项的两次解析 */  115.    parse_early_param();  116.    parse_args("Booting kernel", static_command_line, __start___param,  117.           __stop___param - __start___param, &unknown_bootoption);  118.  119.    /* These use large bootmem allocations and must precede kmem_cache_init() */  120.    setup_log_buf(0);  121.  122.    /* 初始化hash表,便于从进程的PID获得对应的进程描述符指针 */  123.    pidhash_init();  124.  125.    /* 虚拟文件系统初始化,包括dcache\inode\files\mnt\bdev_cache\chrdev_init() */  126.    vfs_caches_init_early();  127.    sort_main_extable();  128.  129.    /* trap_init函数完成对系统保留中断向量(异常、非屏蔽中断以及系统调用)的初始化 130.     * init_IRQ函数则完成其余中断向量的初始化 131.     */  132.    trap_init();  133.    mm_init();  134.  135.    /* Set up the scheduler prior starting any interrupts (such as the 136.     * timer interrupt). Full topology setup happens at smp_init() 137.     * time - but meanwhile we still have a functioning scheduler. 138.     */  139.    sched_init();  140.    /* 141.     * Disable preemption - early bootup scheduling is extremely 142.     * fragile until we cpu_idle() for the first time. 143.     */  144.    preempt_disable();  145.    if (!irqs_disabled()) {  146.        printk(KERN_WARNING "start_kernel(): bug: interrupts were "  147.                "enabled *very* early, fixing it\n");  148.        local_irq_disable();  149.    }  150.    idr_init_cache();  151.  152.    /* NOTE: */  153.    perf_event_init();  154.  155.    rcu_init();  156.    radix_tree_init();  157.    /* init some links before init_ISA_irqs() */  158.    early_irq_init();  159.    init_IRQ();  160.    prio_tree_init();  161.  162.    /* 初始化定时器相关的数据结构*/  163.    init_timers();  164.  165.    /* 对高精度时钟进行初始化 */  166.    hrtimers_init();  167.  168.    softirq_init();  169.    timekeeping_init();  170.  171.    /* 初始化系统时钟源 */  172.    time_init();  173.  174.    /* 对内核的profile功能(一个内核性能调试工具)进行初始化 */  175.    profile_init();  176.    call_function_init();  177.    if (!irqs_disabled())  178.        printk(KERN_CRIT "start_kernel(): bug: interrupts were "  179.                 "enabled early\n");  180.    early_boot_irqs_disabled = false;  181.    local_irq_enable();  182.  183.    /* Interrupts are enabled now so all GFP allocations are safe. */  184.    gfp_allowed_mask = __GFP_BITS_MASK;  185.  186.    /* slab初始化 */  187.    kmem_cache_init_late();  188.  189.    /* 190.     * HACK ALERT! This is early. We're enabling the console before 191.     * we've done PCI setups etc, and console_init() must be aware of 192.     * this. But we do want output early, in case something goes wrong. 193.     */  194.    /* 控制台初始化以显示printk的内容,在此之前调用的printk只是把数据存到缓冲区里 */  195.    console_init();  196.    if (panic_later)  197.        panic(panic_later, panic_param);  198.  199.    /* 如果定义了CONFIG_LOCKDEP宏,则打印锁依赖信息,否则什么也不做 */  200.    lockdep_info();  201.  202.    /* 203.     * Need to run this when irqs are enabled, because it wants 204.     * to self-test [hard/soft]-irqs on/off lock inversion bugs 205.     * too: 206.     */  207.    locking_selftest();  208.  209.#ifdef CONFIG_BLK_DEV_INITRD   210.    if (initrd_start && !initrd_below_start_ok &&  211.        page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {  212.        printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "  213.            "disabling it.\n",  214.            page_to_pfn(virt_to_page((void *)initrd_start)),  215.            min_low_pfn);  216.        initrd_start = 0;  217.    }  218.#endif   219.    page_cgroup_init();  220.    enable_debug_pagealloc();  221.    debug_objects_mem_init();  222.    kmemleak_init();  223.    setup_per_cpu_pageset();  224.    numa_policy_init();  225.    if (late_time_init)  226.        late_time_init();  227.    sched_clock_init();  228.  229.    /* 根据CPU在1s内执行极短循环的次数,得到BogoMIPS值 */  230.    calibrate_delay();  231.    pidmap_init();  232.    anon_vma_init();  233.#ifdef CONFIG_X86   234.    if (efi_enabled)  235.        efi_enter_virtual_mode();  236.#endif   237.    thread_info_cache_init();  238.    cred_init();  239.  240.    /* 根据物理内存大小计算允许创建进程数量 */  241.    fork_init(totalram_pages);  242.    proc_caches_init();  243.    buffer_init();  244.    key_init();  245.    security_init();  246.    dbg_late_init();  247.    vfs_caches_init(totalram_pages);  248.    signals_init();  249.    /* rootfs populating might need page-writeback */  250.    page_writeback_init();  251.#ifdef CONFIG_PROC_FS   252.    proc_root_init();  253.#endif   254.    cgroup_init();      /* 注册cgroup文件系统并创建/proc/cgroup文件,初始化所有在cgroup_init_early中没有初始化的子系统 */  255.    cpuset_init();  256.    taskstats_init_early();  257.    delayacct_init();  258.  259.    /* 测试CPU的各种缺陷,记录检测到的缺陷,以便于内核的其他部分可以使用它们的工作 260.     * check_bugs=>identify_boot_cpu=>identify_cpu会做很多工作,包括select_idle_routine以及intel_init_thermal  261.     */  262.    check_bugs();  263.  264.    acpi_early_init(); /* before LAPIC and SMP init */  265.    sfi_init_late();  266.  267.    ftrace_init();  268.  269.    /* Do the rest non-__init'ed, we're now alive */  270.    /* 创建init进程 */  271.    rest_init();  272.}  


 

转自:http://blog.csdn.net/wlp600/article/details/6935731

原创粉丝点击