📄 setup_64.c
字号:
/* * Copyright (C) 1995 Linus Torvalds *//* * This file handles the architecture-dependent parts of initialization */#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/screen_info.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/initrd.h>#include <linux/highmem.h>#include <linux/bootmem.h>#include <linux/module.h>#include <asm/processor.h>#include <linux/console.h>#include <linux/seq_file.h>#include <linux/crash_dump.h>#include <linux/root_dev.h>#include <linux/pci.h>#include <linux/acpi.h>#include <linux/kallsyms.h>#include <linux/edd.h>#include <linux/mmzone.h>#include <linux/kexec.h>#include <linux/cpufreq.h>#include <linux/dmi.h>#include <linux/dma-mapping.h>#include <linux/ctype.h>#include <asm/mtrr.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/msr.h>#include <asm/desc.h>#include <video/edid.h>#include <asm/e820.h>#include <asm/dma.h>#include <asm/mpspec.h>#include <asm/mmu_context.h>#include <asm/proto.h>#include <asm/setup.h>#include <asm/mach_apic.h>#include <asm/numa.h>#include <asm/sections.h>#include <asm/dmi.h>#include <asm/cacheflush.h>/* * Machine setup.. */struct cpuinfo_x86 boot_cpu_data __read_mostly;EXPORT_SYMBOL(boot_cpu_data);unsigned long mmu_cr4_features;/* Boot loader ID as an integer, for the benefit of proc_dointvec */int bootloader_type;unsigned long saved_video_mode;int force_mwait __cpuinitdata;/* * Early DMI memory */int dmi_alloc_index;char dmi_alloc_data[DMI_MAX_DATA];/* * Setup options */struct screen_info screen_info;EXPORT_SYMBOL(screen_info);struct sys_desc_table_struct { unsigned short length; unsigned char table[0];};struct edid_info edid_info;EXPORT_SYMBOL_GPL(edid_info);extern int root_mountflags;char __initdata command_line[COMMAND_LINE_SIZE];struct resource standard_io_resources[] = { { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer0", .start = 0x40, .end = 0x43, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer1", .start = 0x50, .end = 0x53, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "fpu", .start = 0xf0, .end = 0xff, .flags = IORESOURCE_BUSY | IORESOURCE_IO }};#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, .flags = IORESOURCE_RAM,};struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, .flags = IORESOURCE_RAM,};struct resource bss_resource = { .name = "Kernel bss", .start = 0, .end = 0, .flags = IORESOURCE_RAM,};#ifdef CONFIG_PROC_VMCORE/* elfcorehdr= specifies the location of elf core header * stored by the crashed kernel. This option will be passed * by kexec loader to the capture kernel. */static int __init setup_elfcorehdr(char *arg){ char *end; if (!arg) return -EINVAL; elfcorehdr_addr = memparse(arg, &end); return end > arg ? 0 : -EINVAL;}early_param("elfcorehdr", setup_elfcorehdr);#endif#ifndef CONFIG_NUMAstatic void __initcontig_initmem_init(unsigned long start_pfn, unsigned long end_pfn){ unsigned long bootmap_size, bootmap; bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); if (bootmap == -1L) panic("Cannot find bootmem map of size %ld\n",bootmap_size); bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn); e820_register_active_regions(0, start_pfn, end_pfn); free_bootmem_with_active_regions(0, end_pfn); reserve_bootmem(bootmap, bootmap_size);} #endif#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)struct edd edd;#ifdef CONFIG_EDD_MODULEEXPORT_SYMBOL(edd);#endif/** * copy_edd() - Copy the BIOS EDD information * from boot_params into a safe place. * */static inline void copy_edd(void){ memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer, sizeof(edd.mbr_signature)); memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info)); edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries; edd.edd_info_nr = boot_params.eddbuf_entries;}#elsestatic inline void copy_edd(void){}#endif#ifdef CONFIG_KEXECstatic void __init reserve_crashkernel(void){ unsigned long long free_mem; unsigned long long crash_size, crash_base; int ret; free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT; ret = parse_crashkernel(boot_command_line, free_mem, &crash_size, &crash_base); if (ret == 0 && crash_size) { if (crash_base > 0) { printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " "for crashkernel (System RAM: %ldMB)\n", (unsigned long)(crash_size >> 20), (unsigned long)(crash_base >> 20), (unsigned long)(free_mem >> 20)); crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; reserve_bootmem(crash_base, crash_size); } else printk(KERN_INFO "crashkernel reservation failed - " "you have to specify a base address\n"); }}#elsestatic inline void __init reserve_crashkernel(void){}#endif#define EBDA_ADDR_POINTER 0x40Eunsigned __initdata ebda_addr;unsigned __initdata ebda_size;static void discover_ebda(void){ /* * there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E */ ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); ebda_addr <<= 4; ebda_size = *(unsigned short *)__va(ebda_addr); /* Round EBDA up to pages */ if (ebda_size == 0) ebda_size = 1; ebda_size <<= 10; ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE); if (ebda_size > 64*1024) ebda_size = 64*1024;}void __init setup_arch(char **cmdline_p){ printk(KERN_INFO "Command line: %s\n", boot_command_line); ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); screen_info = boot_params.screen_info; edid_info = boot_params.edid_info; saved_video_mode = boot_params.hdr.vid_mode; bootloader_type = boot_params.hdr.type_of_loader;#ifdef CONFIG_BLK_DEV_RAM rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK; rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);#endif setup_memory_region(); copy_edd(); if (!boot_params.hdr.root_flags) root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; code_resource.start = virt_to_phys(&_text); code_resource.end = virt_to_phys(&_etext)-1; data_resource.start = virt_to_phys(&_etext); data_resource.end = virt_to_phys(&_edata)-1; bss_resource.start = virt_to_phys(&__bss_start); bss_resource.end = virt_to_phys(&__bss_stop)-1; early_identify_cpu(&boot_cpu_data); strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; parse_early_param(); finish_e820_parsing(); e820_register_active_regions(0, 0, -1UL); /* * partially used pages are not usable - thus * we are rounding upwards: */ end_pfn = e820_end_of_ram(); num_physpages = end_pfn; check_efer(); discover_ebda(); init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); dmi_scan_machine();#ifdef CONFIG_SMP /* setup to use the static apicid table during kernel startup */ x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;#endif#ifdef CONFIG_ACPI /* * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). * Call this early for SRAT node setup. */ acpi_boot_table_init();#endif /* How many end-of-memory variables you have, grandma! */ max_low_pfn = end_pfn; max_pfn = end_pfn; high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1; /* Remove active ranges so rediscovery with NUMA-awareness happens */ remove_all_active_ranges();#ifdef CONFIG_ACPI_NUMA /* * Parse SRAT to discover nodes. */ acpi_numa_init();#endif#ifdef CONFIG_NUMA numa_initmem_init(0, end_pfn); #else contig_initmem_init(0, end_pfn);#endif /* Reserve direct mapping */ reserve_bootmem_generic(table_start << PAGE_SHIFT, (table_end - table_start) << PAGE_SHIFT); /* reserve kernel */ reserve_bootmem_generic(__pa_symbol(&_text), __pa_symbol(&_end) - __pa_symbol(&_text)); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ reserve_bootmem_generic(0, PAGE_SIZE); /* reserve ebda region */ if (ebda_addr) reserve_bootmem_generic(ebda_addr, ebda_size);#ifdef CONFIG_NUMA /* reserve nodemap region */ if (nodemap_addr) reserve_bootmem_generic(nodemap_addr, nodemap_size);#endif#ifdef CONFIG_SMP /* Reserve SMP trampoline */ reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);#endif#ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. */ acpi_reserve_bootmem();#endif /* * Find and reserve possible boot-time SMP configuration: */ find_smp_config();#ifdef CONFIG_BLK_DEV_INITRD if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) { unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; unsigned long ramdisk_end = ramdisk_image + ramdisk_size; unsigned long end_of_mem = end_pfn << PAGE_SHIFT; if (ramdisk_end <= end_of_mem) { reserve_bootmem_generic(ramdisk_image, ramdisk_size); initrd_start = ramdisk_image + PAGE_OFFSET; initrd_end = initrd_start+ramdisk_size; } else { printk(KERN_ERR "initrd extends beyond end of memory "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -