setup.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,123 行 · 第 1/3 页

C
1,123
字号
}void init_done(void){    extern char __init_begin[], __init_end[];    /* Free (or page-protect) the init areas. */#ifndef MEMORY_GUARD    init_xenheap_pages(__pa(__init_begin), __pa(__init_end));#endif    memguard_guard_range(__init_begin, __init_end - __init_begin);#if defined(CONFIG_X86_64)    /* Also zap the mapping in the 1:1 area. */    memguard_guard_range(__va(__pa(__init_begin)), __init_end - __init_begin);#endif    printk("Freed %ldkB init memory.\n", (long)(__init_end-__init_begin)>>10);    startup_cpu_idle_loop();}static char * __init cmdline_cook(char *p){    p = p ? : "";    while ( *p == ' ' )        p++;    while ( (*p != ' ') && (*p != '\0') )        p++;    while ( *p == ' ' )        p++;    return p;}void __init __start_xen(unsigned long mbi_p){    char *memmap_type = NULL;    char *cmdline, *kextra;    unsigned long _initrd_start = 0, _initrd_len = 0;    unsigned int initrdidx = 1;    multiboot_info_t *mbi = __va(mbi_p);    module_t *mod = (module_t *)__va(mbi->mods_addr);    unsigned long nr_pages, modules_length;    int i, e820_warn = 0, bytes = 0;    struct ns16550_defaults ns16550 = {        .data_bits = 8,        .parity    = 'n',        .stop_bits = 1    };    extern void early_page_fault(void);    set_intr_gate(TRAP_page_fault, &early_page_fault);    /* Parse the command-line options. */    cmdline = cmdline_cook((mbi->flags & MBI_CMDLINE) ?                           __va(mbi->cmdline) : NULL);    if ( (kextra = strstr(cmdline, " -- ")) != NULL )    {        /*         * Options after ' -- ' separator belong to dom0.         *  1. Orphan dom0's options from Xen's command line.         *  2. Skip all but final leading space from dom0's options.         */        *kextra = '\0';        kextra += 3;        while ( kextra[1] == ' ' ) kextra++;    }    cmdline_parse(cmdline);    parse_video_info();    set_current((struct vcpu *)0xfffff000); /* debug sanity */    idle_vcpu[0] = current;    set_processor_id(0); /* needed early, for smp_processor_id() */    if ( cpu_has_efer )        rdmsrl(MSR_EFER, this_cpu(efer));    asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) );    smp_prepare_boot_cpu();    /* We initialise the serial devices very early so we can get debugging. */    ns16550.io_base = 0x3f8;    ns16550.irq     = 4;    ns16550_init(0, &ns16550);    ns16550.io_base = 0x2f8;    ns16550.irq     = 3;    ns16550_init(1, &ns16550);    serial_init_preirq();    init_console();    printk("Command line: %s\n", cmdline);    printk("Video information:\n");    /* Print VGA display mode information. */    switch ( vga_console_info.video_type )    {    case XEN_VGATYPE_TEXT_MODE_3:        printk(" VGA is text mode %dx%d, font 8x%d\n",               vga_console_info.u.text_mode_3.columns,               vga_console_info.u.text_mode_3.rows,               vga_console_info.u.text_mode_3.font_height);        break;    case XEN_VGATYPE_VESA_LFB:        printk(" VGA is graphics mode %dx%d, %d bpp\n",               vga_console_info.u.vesa_lfb.width,               vga_console_info.u.vesa_lfb.height,               vga_console_info.u.vesa_lfb.bits_per_pixel);        break;    default:        printk(" No VGA detected\n");        break;    }    /* Print VBE/DDC EDID information. */    if ( bootsym(boot_edid_caps) != 0x1313 )    {        u16 caps = bootsym(boot_edid_caps);        printk(" VBE/DDC methods:%s%s%s; ",               (caps & 1) ? " V1" : "",               (caps & 2) ? " V2" : "",               !(caps & 3) ? " none" : "");        printk("EDID transfer time: %d seconds\n", caps >> 8);        if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )        {            printk(" EDID info not retrieved because ");            if ( !(caps & 3) )                printk("no DDC retrieval method detected\n");            else if ( (caps >> 8) > 5 )                printk("takes longer than 5 seconds\n");            else                printk("of reasons unknown\n");        }    }    printk("Disc information:\n");    printk(" Found %d MBR signatures\n",           bootsym(boot_mbr_signature_nr));    printk(" Found %d EDD information structures\n",           bootsym(boot_edd_info_nr));    /* Check that we have at least one Multiboot module. */    if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )        EARLY_FAIL("dom0 kernel not specified. "                   "Check bootloader configuration.\n");    if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 )        EARLY_FAIL("Misaligned CPU0 stack.\n");    if ( e820_raw_nr != 0 )    {        memmap_type = "Xen-e820";    }    else if ( bootsym(lowmem_kb) )    {        memmap_type = "Xen-e801";        e820_raw[0].addr = 0;        e820_raw[0].size = bootsym(lowmem_kb) << 10;        e820_raw[0].type = E820_RAM;        e820_raw[1].addr = 0x100000;        e820_raw[1].size = bootsym(highmem_kb) << 10;        e820_raw[1].type = E820_RAM;        e820_raw_nr = 2;    }    else if ( mbi->flags & MBI_MEMMAP )    {        memmap_type = "Multiboot-e820";        while ( (bytes < mbi->mmap_length) && (e820_raw_nr < E820MAX) )        {            memory_map_t *map = __va(mbi->mmap_addr + bytes);            /*             * This is a gross workaround for a BIOS bug. Some bootloaders do             * not write e820 map entries into pre-zeroed memory. This is             * okay if the BIOS fills in all fields of the map entry, but             * some broken BIOSes do not bother to write the high word of             * the length field if the length is smaller than 4GB. We             * detect and fix this by flagging sections below 4GB that             * appear to be larger than 4GB in size.             */            if ( (map->base_addr_high == 0) && (map->length_high != 0) )            {                if ( !e820_warn )                {                    printk("WARNING: Buggy e820 map detected and fixed "                           "(truncated length fields).\n");                    e820_warn = 1;                }                map->length_high = 0;            }            e820_raw[e820_raw_nr].addr =                 ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;            e820_raw[e820_raw_nr].size =                 ((u64)map->length_high << 32) | (u64)map->length_low;            e820_raw[e820_raw_nr].type = map->type;            e820_raw_nr++;            bytes += map->size + 4;        }    }    else if ( mbi->flags & MBI_MEMLIMITS )    {        memmap_type = "Multiboot-e801";        e820_raw[0].addr = 0;        e820_raw[0].size = mbi->mem_lower << 10;        e820_raw[0].type = E820_RAM;        e820_raw[1].addr = 0x100000;        e820_raw[1].size = mbi->mem_upper << 10;        e820_raw[1].type = E820_RAM;        e820_raw_nr = 2;    }    else    {        EARLY_FAIL("Bootloader provided no memory information.\n");    }    /* Sanitise the raw E820 map to produce a final clean version. */    max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);#ifdef CONFIG_X86_64    /*     * On x86/64 we are able to account for the allocation bitmap     * (allocated in common/page_alloc.c:init_boot_allocator()) stealing     * from the Xen heap. Here we make the Xen heap appropriately larger.     */    opt_xenheap_megabytes += (max_page / 8) >> 20;#endif    /*     * Since there are some stubs getting built on the stacks which use     * direct calls/jumps, the heap must be confined to the lower 2G so     * that those branches can reach their targets.     */    if ( opt_xenheap_megabytes > 2048 )        opt_xenheap_megabytes = 2048;    /* Create a temporary copy of the E820 map. */    memcpy(&boot_e820, &e820, sizeof(e820));    /* Early kexec reservation (explicit static start address). */    kexec_reserve_area(&boot_e820);    /*     * Iterate backwards over all superpage-aligned RAM regions.     *      * We require superpage alignment because the boot allocator is not yet     * initialised. Hence we can only map superpages in the address range     * 0 to BOOTSTRAP_DIRECTMAP_END, as this is guaranteed not to require     * dynamic allocation of pagetables.     *      * As well as mapping superpages in that range, in preparation for     * initialising the boot allocator, we also look for a region to which     * we can relocate the dom0 kernel and other multiboot modules. Also, on     * x86/64, we relocate Xen to higher memory.     */    modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;    for ( i = boot_e820.nr_map-1; i >= 0; i-- )    {        uint64_t s, e, mask = (1UL << L2_PAGETABLE_SHIFT) - 1;        /* Superpage-aligned chunks from 16MB to BOOTSTRAP_DIRECTMAP_END. */        s = (boot_e820.map[i].addr + mask) & ~mask;        e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;        s = max_t(uint64_t, s, 16 << 20);        e = min_t(uint64_t, e, BOOTSTRAP_DIRECTMAP_END);        if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )            continue;        /* Map the chunk. No memory will need to be allocated to do this. */        map_pages_to_xen(            (unsigned long)maddr_to_bootstrap_virt(s),            s >> PAGE_SHIFT, (e-s) >> PAGE_SHIFT, PAGE_HYPERVISOR);#if defined(CONFIG_X86_64)        /* Is the region suitable for relocating Xen? */        if ( !xen_phys_start && (((e-s) >> 20) >= opt_xenheap_megabytes) )        {            extern l2_pgentry_t l2_xenmap[];            l4_pgentry_t *pl4e;            l3_pgentry_t *pl3e;            l2_pgentry_t *pl2e;            int i, j, k;            /* Select relocation address. */            e = (e - (opt_xenheap_megabytes << 20)) & ~mask;            xen_phys_start = e;            bootsym(trampoline_xen_phys_start) = e;            /*             * Perform relocation to new physical address.             * Before doing so we must sync static/global data with main memory             * with a barrier(). After this we must *not* modify static/global             * data until after we have switched to the relocated pagetables!             */            barrier();            move_memory(e, 0, __pa(&_end) - xen_phys_start);            /* Poison low 1MB to detect stray pointers to physical 0-1MB. */            memset(maddr_to_bootstrap_virt(e), 0x55, 1U<<20);            /* Walk initial pagetables, relocating page directory entries. */            pl4e = __va(__pa(idle_pg_table));            for ( i = 0 ; i < L4_PAGETABLE_ENTRIES; i++, pl4e++ )            {                if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )                    continue;                *pl4e = l4e_from_intpte(l4e_get_intpte(*pl4e) +                                        xen_phys_start);                pl3e = l4e_to_l3e(*pl4e);                for ( j = 0; j < L3_PAGETABLE_ENTRIES; j++, pl3e++ )                {                    /* Not present, 1GB mapping, or already relocated? */                    if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ||                         (l3e_get_flags(*pl3e) & _PAGE_PSE) ||                         (l3e_get_pfn(*pl3e) > 0x1000) )                        continue;                    *pl3e = l3e_from_intpte(l3e_get_intpte(*pl3e) +                                            xen_phys_start);                    pl2e = l3e_to_l2e(*pl3e);                    for ( k = 0; k < L2_PAGETABLE_ENTRIES; k++, pl2e++ )                    {                        /* Not present, PSE, or already relocated? */                        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ||                             (l2e_get_flags(*pl2e) & _PAGE_PSE) ||                             (l2e_get_pfn(*pl2e) > 0x1000) )                            continue;                        *pl2e = l2e_from_intpte(l2e_get_intpte(*pl2e) +                                                xen_phys_start);                    }                }            }            /* The only data mappings to be relocated are in the Xen area. */            pl2e = __va(__pa(l2_xenmap));            *pl2e++ = l2e_from_pfn(xen_phys_start >> PAGE_SHIFT,                                   PAGE_HYPERVISOR | _PAGE_PSE);            for ( i = 1; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ )            {                if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )                    continue;                *pl2e = l2e_from_intpte(l2e_get_intpte(*pl2e) +                                        xen_phys_start);            }            /* Re-sync the stack and then switch to relocated pagetables. */            asm volatile (                "rep movsb        ; " /* re-sync the stack */                "movq %%cr4,%%rsi ; "                "andb $0x7f,%%sil ; "                "movq %%rsi,%%cr4 ; " /* CR4.PGE == 0 */                "movq %0,%%cr3    ; " /* CR3 == new pagetables */                "orb $0x80,%%sil  ; "                "movq %%rsi,%%cr4   " /* CR4.PGE == 1 */                : : "r" (__pa(idle_pg_table)), "S" (cpu0_stack),                "D" (__va(__pa(cpu0_stack))), "c" (STACK_SIZE) : "memory" );        }#endif        /* Is the region suitable for relocating the multiboot modules? */        if ( !initial_images_start && (s < e) && ((e-s) >= modules_length) )        {            initial_images_end = e;            e = (e - modules_length) & PAGE_MASK;            initial_images_start = e;            move_memory(initial_images_start,                         mod[0].mod_start, mod[mbi->mods_count-1].mod_end);        }        if ( !kexec_crash_area.start && (s < e) &&             ((e-s) >= kexec_crash_area.size) )        {            e = (e - kexec_crash_area.size) & PAGE_MASK;            kexec_crash_area.start = e;        }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?