⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (last_pfn > max_low_pfn)			last_pfn = max_low_pfn;		/*		 * .. finally, did all the rounding and playing		 * around just make the area go away?		 */		if (last_pfn <= curr_pfn)			continue;		size = last_pfn - curr_pfn;		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));	}}/* * workaround for Dell systems that neglect to reserve EBDA */static void __init reserve_ebda_region(void){	unsigned int addr;	addr = get_bios_ebda();	if (addr)		reserve_bootmem(addr, PAGE_SIZE);	}#ifndef CONFIG_NEED_MULTIPLE_NODESvoid __init setup_bootmem_allocator(void);static unsigned long __init setup_memory(void){	/*	 * partially used pages are not usable - thus	 * we are rounding upwards:	 */	min_low_pfn = PFN_UP(init_pg_tables_end);	find_max_pfn();	max_low_pfn = find_max_low_pfn();#ifdef CONFIG_HIGHMEM	highstart_pfn = highend_pfn = max_pfn;	if (max_pfn > max_low_pfn) {		highstart_pfn = max_low_pfn;	}	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",		pages_to_mb(highend_pfn - highstart_pfn));#endif	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",			pages_to_mb(max_low_pfn));	setup_bootmem_allocator();	return max_low_pfn;}void __init zone_sizes_init(void){	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};	unsigned int max_dma, low;	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;	low = max_low_pfn;	if (low < max_dma)		zones_size[ZONE_DMA] = low;	else {		zones_size[ZONE_DMA] = max_dma;		zones_size[ZONE_NORMAL] = low - max_dma;#ifdef CONFIG_HIGHMEM		zones_size[ZONE_HIGHMEM] = highend_pfn - low;#endif	}	free_area_init(zones_size);}#elseextern unsigned long __init setup_memory(void);extern void zone_sizes_init(void);#endif /* !CONFIG_NEED_MULTIPLE_NODES */void __init setup_bootmem_allocator(void){	unsigned long bootmap_size;	/*	 * Initialize the boot-time allocator (with low memory only):	 */	bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);	register_bootmem_low_pages(max_low_pfn);	/*	 * Reserve the bootmem bitmap itself as well. We do this in two	 * steps (first step was init_bootmem()) because this catches	 * the (very unlikely) case of us accidentally initializing the	 * bootmem allocator with an invalid RAM area.	 */	reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +			 bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));	/*	 * reserve physical page 0 - it's a special BIOS page on many boxes,	 * enabling clean reboots, SMP operation, laptop functions.	 */	reserve_bootmem(0, PAGE_SIZE);	/* reserve EBDA region, it's a 4K region */	reserve_ebda_region();    /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent       PCI prefetch into it (errata #56). Usually the page is reserved anyways,       unless you have no PS/2 mouse plugged in. */	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&	    boot_cpu_data.x86 == 6)	     reserve_bootmem(0xa0000 - 4096, 4096);#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(PAGE_SIZE, PAGE_SIZE);#endif#ifdef CONFIG_ACPI_SLEEP	/*	 * Reserve low memory region for sleep support.	 */	acpi_reserve_bootmem();#endif#ifdef CONFIG_X86_FIND_SMP_CONFIG	/*	 * 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 <= (max_low_pfn << PAGE_SHIFT)) {			reserve_bootmem(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",			    INITRD_START + INITRD_SIZE,			    max_low_pfn << PAGE_SHIFT);			initrd_start = 0;		}	}#endif#ifdef CONFIG_KEXEC	if (crashk_res.start != crashk_res.end)		reserve_bootmem(crashk_res.start,			crashk_res.end - crashk_res.start + 1);#endif}/* * The node 0 pgdat is initialized before all of these because * it's needed for bootmem.  node>0 pgdats have their virtual * space allocated before the pagetables are in place to access * them, so they can't be cleared then. * * This should all compile down to nothing when NUMA is off. */void __init remapped_pgdat_init(void){	int nid;	for_each_online_node(nid) {		if (nid != 0)			memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));	}}/* * Request address space for all standard RAM and ROM resources * and also for regions reported as reserved by the e820. */static void __initlegacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource){	int i;	probe_roms();	for (i = 0; i < e820.nr_map; i++) {		struct resource *res;		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)			continue;		res = alloc_bootmem_low(sizeof(struct resource));		switch (e820.map[i].type) {		case E820_RAM:	res->name = "System RAM"; break;		case E820_ACPI:	res->name = "ACPI Tables"; break;		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;		default:	res->name = "reserved";		}		res->start = e820.map[i].addr;		res->end = res->start + e820.map[i].size - 1;		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;		request_resource(&iomem_resource, res);		if (e820.map[i].type == E820_RAM) {			/*			 *  We don't know which RAM region contains kernel data,			 *  so we try it repeatedly and let the resource manager			 *  test it.			 */			request_resource(res, code_resource);			request_resource(res, data_resource);#ifdef CONFIG_KEXEC			request_resource(res, &crashk_res);#endif		}	}}/* * Request address space for all standard resources */static void __init register_memory(void){	unsigned long gapstart, gapsize, round;	unsigned long long last;	int	      i;	if (efi_enabled)		efi_initialize_iomem_resources(&code_resource, &data_resource);	else		legacy_init_iomem_resources(&code_resource, &data_resource);	/* EFI systems may still have VGA */	request_resource(&iomem_resource, &video_ram_resource);	/* 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]);	/*	 * Search for the bigest gap in the low 32 bits of the e820	 * memory space.	 */	last = 0x100000000ull;	gapstart = 0x10000000;	gapsize = 0x400000;	i = e820.nr_map;	while (--i >= 0) {		unsigned long long start = e820.map[i].addr;		unsigned long long end = start + e820.map[i].size;		/*		 * Since "last" is at most 4GB, we know we'll		 * fit in 32 bits if this condition is true		 */		if (last > end) {			unsigned long gap = last - end;			if (gap > gapsize) {				gapsize = gap;				gapstart = end;			}		}		if (start < last)			last = start;	}	/*	 * See how much we want to round up: start off with	 * rounding to the next 1MB area.	 */	round = 0x100000;	while ((gapsize >> 4) > round)		round += round;	/* Fun with two's complement */	pci_mem_start = (gapstart + round) & -round;	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",		pci_mem_start, gapstart, gapsize);}/* 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\nintelnops: "     GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6    GENERIC_NOP7 GENERIC_NOP8); asm("\t.data\nk8nops: "     K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6    K8_NOP7 K8_NOP8); asm("\t.data\nk7nops: "     K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6    K7_NOP7 K7_NOP8);     extern unsigned char intelnops[], k8nops[], k7nops[];static unsigned char *intel_nops[ASM_NOP_MAX+1] = {      NULL,     intelnops,     intelnops + 1,     intelnops + 1 + 2,     intelnops + 1 + 2 + 3,     intelnops + 1 + 2 + 3 + 4,     intelnops + 1 + 2 + 3 + 4 + 5,     intelnops + 1 + 2 + 3 + 4 + 5 + 6,     intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,}; 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,}; static unsigned char *k7_nops[ASM_NOP_MAX+1] = {      NULL,     k7nops,     k7nops + 1,     k7nops + 1 + 2,     k7nops + 1 + 2 + 3,     k7nops + 1 + 2 + 3 + 4,     k7nops + 1 + 2 + 3 + 4 + 5,     k7nops + 1 + 2 + 3 + 4 + 5 + 6,     k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,}; static struct nop {      int cpuid;      unsigned char **noptable; } noptypes[] = {      { X86_FEATURE_K8, k8_nops },      { X86_FEATURE_K7, k7_nops },      { -1, NULL }}; /* 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.    Tough. Make sure you disable such features by hand. */ void apply_alternatives(void *start, void *end) { 	struct alt_instr *a; 	int diff, i, k;        unsigned char **noptable = intel_nops; 	for (i = 0; noptypes[i].cpuid >= 0; i++) { 		if (boot_cpu_has(noptypes[i].cpuid)) { 			noptable = noptypes[i].noptable;			break;		}	} 	for (a = start; (void *)a < end; a++) { 		if (!boot_cpu_has(a->cpuid))			continue;		BUG_ON(a->replacementlen > a->instrlen); 		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;			memcpy(a->instr + i, noptable[k], k); 		} 	}} void __init alternative_instructions(void){	extern struct alt_instr __alt_instructions[], __alt_instructions_end[];	apply_alternatives(__alt_instructions, __alt_instructions_end);}static char * __init machine_specific_memory_setup(void);#ifdef CONFIG_MCAstatic void set_mca_bus(int x){	MCA_bus = x;}#elsestatic void set_mca_bus(int x) { }#endif/* * Determine if we were loaded by an EFI loader.  If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures * for initialization.  Note, the efi init code path is determined by the * global efi_enabled. This allows the same kernel image to be used on existing * systems (with a traditional BIOS) as well as on EFI systems. */void __init setup_arch(char **cmdline_p){	unsigned long max_low_pfn;	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));	pre_setup_arch_hook();	early_cpu_init();	/*	 * FIXME: This isn't an official loader_type right	 * now but does currently work with elilo.	 * If we were configured as an EFI kernel, check to make	 * sure that we were loaded correctly from elilo and that	 * the system table is valid.  If not, then initialize normally.	 */#ifdef CONFIG_EFI	if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)		efi_enabled = 1;#endif 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); 	drive_info = DRIVE_INFO; 	screen_info = SCREEN_INFO;	edid_info = EDID_INFO;	apm_info.bios = APM_BIOS_INFO;	ist_info = IST_INFO;	saved_videomode = VIDEO_MODE;	if( SYS_DESC_TABLE.length != 0 ) {		set_mca_bus(SYS_DESC_TABLE.table[3] & 0x2);		machine_id = SYS_DESC_TABLE.table[0];		machine_submodel_id = SYS_DESC_TABLE.table[1];		BIOS_revision = SYS_DESC_TABLE.table[2];	}	bootloader_type = LOADER_TYPE;#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	ARCH_SETUP	if (efi_enabled)		efi_init();	else {		printk(KERN_INFO "BIOS-provided physical RAM map:\n");		print_memory_map(machine_specific_memory_setup());	}	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 = init_pg_tables_end + PAGE_OFFSET;	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);	max_low_pfn = setup_memory();	/*	 * NOTE: before this point _nobody_ is allowed to allocate	 * any memory using the bootmem allocator.  Although the	 * alloctor is now initialised only the first 8Mb of the kernel	 * virtual address space has been mapped.  All allocations before	 * paging_init() has completed must use the alloc_bootmem_low_pages()	 * variant (which allocates DMA'able memory) and care must be taken	 * not to exceed the 8Mb limit.	 */#ifdef CONFIG_SMP	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/#endif	paging_init();	remapped_pgdat_init();	sparse_init();	zone_sizes_init();	/*	 * NOTE: at this point the bootmem allocator is fully available.	 */#ifdef CONFIG_EARLY_PRINTK	{		char *s = strstr(*cmdline_p, "earlyprintk=");		if (s) {			extern void setup_early_printk(char *);			setup_early_printk(s);			printk("early console enabled\n");		}	}#endif	dmi_scan_machine();#ifdef CONFIG_X86_GENERICARCH	generic_apic_probe(*cmdline_p);#endif		if (efi_enabled)		efi_map_memmap();#ifdef CONFIG_ACPI	/*	 * Parse the ACPI tables for possible boot-time SMP configuration.	 */	acpi_boot_table_init();	acpi_boot_init();#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)	if (def_to_bigsmp)		printk(KERN_WARNING "More than 8 CPUs detected and "			"CONFIG_X86_PC cannot handle it.\nUse "			"CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");#endif#endif#ifdef CONFIG_X86_LOCAL_APIC	if (smp_found_config)		get_smp_config();#endif	register_memory();#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))		conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)	conswitchp = &dummy_con;#endif#endif}#include "setup_arch_post.h"/* * Local Variables: * mode:c * c-file-style:"k&r" * c-basic-offset:8 * End: */

⌨️ 快捷键说明

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