setup.c

来自「linux2.6.16版本」· C语言 代码 · 共 1,413 行 · 第 1/3 页

C
1,413
字号
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,}; extern char __vsyscall_0;/* 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++) { 		u8 *instr;		if (!boot_cpu_has(a->cpuid))			continue;		BUG_ON(a->replacementlen > a->instrlen); 		instr = a->instr;		/* vsyscall code is not mapped yet. resolve it manually. */		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END)			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));		__inline_memcpy(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(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){}#endif#define EBDA_ADDR_POINTER 0x40Estatic void __init reserve_ebda_region(void){	unsigned int addr;	/** 	 * there is a real-mode segmented pointer pointing to the 	 * 4K EBDA area at 0x40E	 */	addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);	addr <<= 4;	if (addr)		reserve_bootmem_generic(addr, PAGE_SIZE);}void __init setup_arch(char **cmdline_p){	unsigned long kernel_end; 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); 	screen_info = SCREEN_INFO;	edid_info = EDID_INFO;	saved_video_mode = SAVED_VIDEO_MODE;	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	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);	early_identify_cpu(&boot_cpu_data);	/*	 * partially used pages are not usable - thus	 * we are rounding upwards:	 */	end_pfn = e820_end_of_ram();	check_efer();	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));	zap_low_mappings(0);#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#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 */	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);	/* reserve ebda region */	reserve_ebda_region();#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#ifdef CONFIG_KEXEC	if (crashk_res.start != crashk_res.end) {		reserve_bootmem(crashk_res.start,			crashk_res.end - crashk_res.start + 1);	}#endif	paging_init();	check_ioapic();#ifdef CONFIG_ACPI	/*	 * Read APIC and some other early information from ACPI tables.	 */	acpi_boot_init();#endif	init_cpu_to_node();#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]);	}	e820_setup_gap();#ifdef CONFIG_GART_IOMMU	iommu_hole_init();#endif#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)	conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)	conswitchp = &dummy_con;#endif#endif}static int __cpuinit get_model_name(struct cpuinfo_x86 *c){	unsigned int *v;	if (c->extended_cpuid_level < 0x80000004)		return 0;	v = (unsigned int *) c->x86_model_id;	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);	c->x86_model_id[48] = 0;	return 1;}static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c){	unsigned int n, dummy, eax, ebx, ecx, edx;	n = c->extended_cpuid_level;	if (n >= 0x80000005) {		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);		c->x86_cache_size=(ecx>>24)+(edx>>24);		/* On K8 L1 TLB is inclusive, so don't count it */		c->x86_tlbsize = 0;	}	if (n >= 0x80000006) {		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);		ecx = cpuid_ecx(0x80000006);		c->x86_cache_size = ecx >> 16;		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",		c->x86_cache_size, ecx & 0xFF);	}	if (n >= 0x80000007)		cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power); 	if (n >= 0x80000008) {		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); 		c->x86_virt_bits = (eax >> 8) & 0xff;		c->x86_phys_bits = eax & 0xff;	}}#ifdef CONFIG_NUMAstatic int nearby_node(int apicid){	int i;	for (i = apicid - 1; i >= 0; i--) {		int node = apicid_to_node[i];		if (node != NUMA_NO_NODE && node_online(node))			return node;	}	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {		int node = apicid_to_node[i];		if (node != NUMA_NO_NODE && node_online(node))			return node;	}	return first_node(node_online_map); /* Shouldn't happen */}#endif/* * On a AMD dual core setup the lower bits of the APIC id distingush the cores. * Assumes number of cores is a power of two. */static void __init amd_detect_cmp(struct cpuinfo_x86 *c){#ifdef CONFIG_SMP	int cpu = smp_processor_id();	unsigned bits;#ifdef CONFIG_NUMA	int node = 0;	unsigned apicid = phys_proc_id[cpu];#endif	bits = 0;	while ((1 << bits) < c->x86_max_cores)		bits++;	/* Low order bits define the core id (index of core in socket) */	cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);	/* Convert the APIC ID into the socket ID */	phys_proc_id[cpu] >>= bits;#ifdef CONFIG_NUMA  	node = phys_proc_id[cpu]; 	if (apicid_to_node[apicid] != NUMA_NO_NODE) 		node = apicid_to_node[apicid]; 	if (!node_online(node)) { 		/* Two possibilities here: 		   - The CPU is missing memory and no node was created. 		   In that case try picking one from a nearby CPU 		   - The APIC IDs differ from the HyperTransport node IDs 		   which the K8 northbridge parsing fills in. 		   Assume they are all increased by a constant offset, 		   but in the same order as the HT nodeids. 		   If that doesn't result in a usable node fall back to the 		   path for the previous case.  */ 		int ht_nodeid = apicid - (phys_proc_id[0] << bits); 		if (ht_nodeid >= 0 && 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE) 			node = apicid_to_node[ht_nodeid]; 		/* Pick a nearby node */ 		if (!node_online(node)) 			node = nearby_node(apicid); 	}	numa_set_node(cpu, node);  	printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",  			cpu, c->x86_max_cores, node, cpu_core_id[cpu]);#endif#endif}static int __init init_amd(struct cpuinfo_x86 *c){	int r;	unsigned level;#ifdef CONFIG_SMP	unsigned long value;	/*	 * Disable TLB flush filter by setting HWCR.FFDIS on K8	 * bit 6 of msr C001_0015 	 *	 * Errata 63 for SH-B3 steppings	 * Errata 122 for all steppings (F+ have it disabled by default)	 */	if (c->x86 == 15) {		rdmsrl(MSR_K8_HWCR, value);		value |= 1 << 6;		wrmsrl(MSR_K8_HWCR, value);	}#endif	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */	clear_bit(0*32+31, &c->x86_capability);		/* On C+ stepping K8 rep microcode works well for copy/memset */	level = cpuid_eax(1);	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);	r = get_model_name(c);	if (!r) { 		switch (c->x86) { 		case 15:			/* Should distinguish Models here, but this is only			   a fallback anyways. */			strcpy(c->x86_model_id, "Hammer");			break; 		} 	} 	display_cacheinfo(c);	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */	if (c->x86_power & (1<<8))		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);	if (c->extended_cpuid_level >= 0x80000008) {		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;		if (c->x86_max_cores & (c->x86_max_cores - 1))			c->x86_max_cores = 1;		amd_detect_cmp(c);	}	return r;}static void __cpuinit detect_ht(struct cpuinfo_x86 *c){#ifdef CONFIG_SMP	u32 	eax, ebx, ecx, edx;

⌨️ 快捷键说明

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