setup.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,161 行 · 第 1/2 页

C
1,161
字号
/* *  linux/arch/x86-64/kernel/setup.c * *  Copyright (C) 1995  Linus Torvalds * *  Nov 2001 Dave Jones <davej@suse.de> *  Forked from i386 setup code. * *  $Id$ *//* * 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/tty.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/config.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/root_dev.h>#include <linux/pci.h>#include <linux/acpi.h>#include <linux/kallsyms.h>#include <linux/edd.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/bootsetup.h>#include <asm/smp.h>#include <asm/proto.h>#include <asm/setup.h>/* * Machine setup.. */struct cpuinfo_x86 boot_cpu_data;unsigned long mmu_cr4_features;EXPORT_SYMBOL_GPL(mmu_cr4_features);int acpi_disabled;EXPORT_SYMBOL(acpi_disabled);#ifdef	CONFIG_ACPI_BOOTextern int __initdata acpi_ht;extern acpi_interrupt_flags	acpi_sci_flags;/* int __initdata acpi_force = 0; */#endif/* For PCI or other memory-mapped resources */unsigned long pci_mem_start = 0x10000000;unsigned long saved_video_mode;int swiotlb;EXPORT_SYMBOL(swiotlb);/* * Setup options */struct drive_info_struct { char dummy[32]; } drive_info;struct screen_info screen_info;struct sys_desc_table_struct {	unsigned short length;	unsigned char table[0];};struct edid_info edid_info;struct e820map e820;unsigned char aux_device_present;extern int root_mountflags;extern char _text, _etext, _edata, _end;char command_line[COMMAND_LINE_SIZE];struct resource standard_io_resources[] = {	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO },	{ "pic1", 0x20, 0x21, IORESOURCE_BUSY | IORESOURCE_IO },	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY | IORESOURCE_IO },	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY | IORESOURCE_IO },	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY | IORESOURCE_IO },	{ "pic2", 0xa0, 0xa1, IORESOURCE_BUSY | IORESOURCE_IO },	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY | IORESOURCE_IO },	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY | IORESOURCE_IO }};#define STANDARD_IO_RESOURCES \	(sizeof standard_io_resources / sizeof standard_io_resources[0])#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)struct resource data_resource = { "Kernel data", 0, 0, IORESOURCE_RAM };struct resource code_resource = { "Kernel code", 0, 0, IORESOURCE_RAM };#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)static struct resource system_rom_resource = { "System ROM", 0xf0000, 0xfffff, IORESOURCE_ROM };static struct resource extension_rom_resource = { "Extension ROM", 0xe0000, 0xeffff, IORESOURCE_ROM };static struct resource adapter_rom_resources[] = {	{ "Adapter ROM", 0xc8000, 0, IORESOURCE_ROM },	{ "Adapter ROM", 0, 0, IORESOURCE_ROM },	{ "Adapter ROM", 0, 0, IORESOURCE_ROM },	{ "Adapter ROM", 0, 0, IORESOURCE_ROM },	{ "Adapter ROM", 0, 0, IORESOURCE_ROM },	{ "Adapter ROM", 0, 0, IORESOURCE_ROM }};#define ADAPTER_ROM_RESOURCES \	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])static struct resource video_rom_resource = { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_ROM };static struct resource video_ram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_RAM };#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)static int __init romchecksum(unsigned char *rom, unsigned long length){	unsigned char *p, sum = 0;	for (p = rom; p < rom + length; p++)		sum += *p;	return sum == 0;}static void __init probe_roms(void){	unsigned long start, length, upper;	unsigned char *rom;	int	      i;	/* video rom */	upper = adapter_rom_resources[0].start;	for (start = video_rom_resource.start; start < upper; start += 2048) {		rom = isa_bus_to_virt(start);		if (!romsignature(rom))			continue;		video_rom_resource.start = start;		/* 0 < length <= 0x7f * 512, historically */		length = rom[2] * 512;		/* if checksum okay, trust length byte */		if (length && romchecksum(rom, length))			video_rom_resource.end = start + length - 1;		request_resource(&iomem_resource, &video_rom_resource);		break;			}	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;	if (start < upper)		start = upper;	/* system rom */	request_resource(&iomem_resource, &system_rom_resource);	upper = system_rom_resource.start;	/* check for extension rom (ignore length byte!) */	rom = isa_bus_to_virt(extension_rom_resource.start);	if (romsignature(rom)) {		length = extension_rom_resource.end - extension_rom_resource.start + 1;		if (romchecksum(rom, length)) {			request_resource(&iomem_resource, &extension_rom_resource);			upper = extension_rom_resource.start;		}	}	/* check for adapter roms on 2k boundaries */	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {		rom = isa_bus_to_virt(start);		if (!romsignature(rom))			continue;		/* 0 < length <= 0x7f * 512, historically */		length = rom[2] * 512;		/* but accept any length that fits if checksum okay */		if (!length || start + length > upper || !romchecksum(rom, length))			continue;		adapter_rom_resources[i].start = start;		adapter_rom_resources[i].end = start + length - 1;		request_resource(&iomem_resource, &adapter_rom_resources[i]);		start = adapter_rom_resources[i++].end & ~2047UL;	}}static __init void parse_cmdline_early (char ** cmdline_p){	char c = ' ', *to = command_line, *from = COMMAND_LINE;	int len = 0;	/* Save unparsed command line copy for /proc/cmdline */	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';	for (;;) {		if (c != ' ') 			goto next_char; #ifdef  CONFIG_SMP		/*		 * If the BIOS enumerates physical processors before logical,		 * maxcpus=N at enumeration-time can be used to disable HT.		 */		else if (!memcmp(from, "maxcpus=", 8)) {			extern unsigned int maxcpus;			maxcpus = simple_strtoul(from + 8, NULL, 0);		}#endif#ifdef CONFIG_ACPI_BOOT		/* "acpi=off" disables both ACPI table parsing and interpreter init */		if (!memcmp(from, "acpi=off", 8))			disable_acpi();		if (!memcmp(from, "acpi=force", 10)) { 			/* add later when we do DMI horrors: */			/* acpi_force = 1; */				acpi_disabled = 0;		}		/* acpi=ht just means: do ACPI MADT parsing 		   at bootup, but don't enable the full ACPI interpreter */		if (!memcmp(from, "acpi=ht", 7)) { 			/* if (!acpi_force) */				disable_acpi();			acpi_ht = 1; 		}                else if (!memcmp(from, "pci=noacpi", 10)) 			acpi_disable_pci();		else if (!memcmp(from, "acpi=noirq", 10))			acpi_noirq_set();		else if (!memcmp(from, "acpi_sci=edge", 13))			acpi_sci_flags.trigger =  1;		else if (!memcmp(from, "acpi_sci=level", 14))			acpi_sci_flags.trigger = 3;		else if (!memcmp(from, "acpi_sci=high", 13))			acpi_sci_flags.polarity = 1;		else if (!memcmp(from, "acpi_sci=low", 12))			acpi_sci_flags.polarity = 3;		/* acpi=strict disables out-of-spec workarounds */		else if (!memcmp(from, "acpi=strict", 11)) {			acpi_strict = 1;		}#endif		if (!memcmp(from, "nolapic", 7) ||		    !memcmp(from, "disableapic", 11))			disable_apic = 1;		if (!memcmp(from, "noapic", 6)) 			skip_ioapic_setup = 1;		if (!memcmp(from, "apic", 4)) { 			skip_ioapic_setup = 0;			ioapic_force = 1;		}					if (!memcmp(from, "mem=", 4))			parse_memopt(from+4, &from); #ifdef CONFIG_DISCONTIGMEM		if (!memcmp(from, "numa=", 5))			numa_setup(from+5); #endif#ifdef CONFIG_GART_IOMMU 		if (!memcmp(from,"iommu=",6)) { 			iommu_setup(from+6); 		}#endif		if (!memcmp(from,"oops=panic", 10))			panic_on_oops = 1;	next_char:		c = *(from++);		if (!c)			break;		if (COMMAND_LINE_SIZE <= ++len)			break;		*(to++) = c;	}	*to = '\0';	*cmdline_p = command_line;}#ifndef CONFIG_DISCONTIGMEMstatic void __init contig_initmem_init(void){        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_bootmem_free(&contig_page_data, 0, end_pfn << PAGE_SHIFT);         reserve_bootmem(bootmap, bootmap_size);} #endif/* Use inline assembly to define this because the nops are defined    as inline assembly strings in the include files and we cannot    get them easily into strings. */asm("\t.data\nk8nops: "     K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6    K8_NOP7 K8_NOP8);     extern unsigned char k8nops[];static unsigned char *k8_nops[ASM_NOP_MAX+1] = {      NULL,     k8nops,     k8nops + 1,     k8nops + 1 + 2,     k8nops + 1 + 2 + 3,     k8nops + 1 + 2 + 3 + 4,     k8nops + 1 + 2 + 3 + 4 + 5,     k8nops + 1 + 2 + 3 + 4 + 5 + 6,     k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,}; /* Replace instructions with better alternatives for this CPU type.   This runs before SMP is initialized to avoid SMP problems with   self modifying code. This implies that assymetric systems where   APs have less capabilities than the boot processor are not handled.    In this case boot with "noreplacement". */ void apply_alternatives(void *start, void *end) { 	struct alt_instr *a; 	int diff, i, k;	for (a = start; (void *)a < end; a++) { 		if (!boot_cpu_has(a->cpuid))			continue;		BUG_ON(a->replacementlen > a->instrlen); 		__inline_memcpy(a->instr, a->replacement, a->replacementlen); 		diff = a->instrlen - a->replacementlen; 		/* Pad the rest with nops */		for (i = a->replacementlen; diff > 0; diff -= k, i += k) {			k = diff;			if (k > ASM_NOP_MAX)				k = ASM_NOP_MAX;			__inline_memcpy(a->instr + i, k8_nops[k], k); 		} 	}} static int no_replacement __initdata = 0;  void __init alternative_instructions(void){	extern struct alt_instr __alt_instructions[], __alt_instructions_end[];	if (no_replacement) 		return;	apply_alternatives(__alt_instructions, __alt_instructions_end);}static int __init noreplacement_setup(char *s){      no_replacement = 1;      return 0; } __setup("noreplacement", noreplacement_setup); #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, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));     edd.mbr_signature_nr = EDD_MBR_SIG_NR;     edd.edd_info_nr = EDD_NR;}#elsestatic inline void copy_edd(void){}#endifvoid __init setup_arch(char **cmdline_p){	unsigned long low_mem_size;	unsigned long kernel_end; 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); 	drive_info = DRIVE_INFO; 	screen_info = SCREEN_INFO;	edid_info = EDID_INFO;	aux_device_present = AUX_DEVICE_INFO;	saved_video_mode = SAVED_VIDEO_MODE;#ifdef CONFIG_BLK_DEV_RAM	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);#endif	setup_memory_region();	copy_edd();	if (!MOUNT_ROOT_RDONLY)		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;	parse_cmdline_early(cmdline_p);	/*	 * partially used pages are not usable - thus	 * we are rounding upwards:	 */	end_pfn = e820_end_of_ram();	check_efer();	init_memory_mapping(); #ifdef CONFIG_DISCONTIGMEM	numa_initmem_init(0, end_pfn); #else	contig_initmem_init(); #endif	/* Reserve direct mapping */	reserve_bootmem_generic(table_start << PAGE_SHIFT, 				(table_end - table_start) << PAGE_SHIFT);	/* reserve kernel */	kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);	reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);	/*	 * 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);#ifdef CONFIG_SMP	/*	 * But first pinch a few for the stack/trampoline stuff	 * FIXME: Don't need the extra page at 4K, but need to fix	 * trampoline before removing it. (see the GDT stuff)	 */	reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);	/* Reserve SMP trampoline */	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);#endif#ifdef CONFIG_ACPI_SLEEP       /*        * Reserve low memory region for sleep support.        */       acpi_reserve_bootmem();#endif#ifdef CONFIG_X86_LOCAL_APIC	/*	 * Find and reserve possible boot-time SMP configuration:	 */	find_smp_config();#endif#ifdef CONFIG_BLK_DEV_INITRD	if (LOADER_TYPE && INITRD_START) {		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {			reserve_bootmem_generic(INITRD_START, INITRD_SIZE);			initrd_start =				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;			initrd_end = initrd_start+INITRD_SIZE;		}		else {			printk(KERN_ERR "initrd extends beyond end of memory "			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",			    (unsigned long)(INITRD_START + INITRD_SIZE),			    (unsigned long)(end_pfn << PAGE_SHIFT));			initrd_start = 0;		}	}#endif	paging_init();		check_ioapic();#ifdef CONFIG_ACPI_BOOT       /*        * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).        * Must do this after paging_init (due to reliance on fixmap, and thus        * the bootmem allocator) but before get_smp_config (to allow parsing        * of MADT).        */	acpi_boot_init();#endif#ifdef CONFIG_X86_LOCAL_APIC	/*	 * get boot-time SMP configuration:	 */	if (smp_found_config)		get_smp_config();	init_apic_mappings();#endif	/*	 * Request address space for all standard RAM and ROM resources	 * and also for regions reported as reserved by the e820.	 */	probe_roms();	e820_reserve_resources(); 	request_resource(&iomem_resource, &video_ram_resource);	{	unsigned i;	/* request I/O space for devices used on all i[345]86 PCs */	for (i = 0; i < STANDARD_IO_RESOURCES; i++)		request_resource(&ioport_resource, &standard_io_resources[i]);	}	/* Will likely break when you have unassigned resources with more	   than 4GB memory and bridges that don't support more than 4GB. 	   Doing it properly would require to use pci_alloc_consistent	   in this case. */	low_mem_size = ((end_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;	if (low_mem_size > pci_mem_start)		pci_mem_start = low_mem_size;#ifdef CONFIG_GART_IOMMU       iommu_hole_init();#endif#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)

⌨️ 快捷键说明

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