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 + -
显示快捷键?