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

📄 common.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/init.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/smp.h>#include <linux/module.h>#include <linux/percpu.h>#include <linux/bootmem.h>#include <asm/semaphore.h>#include <asm/processor.h>#include <asm/i387.h>#include <asm/msr.h>#include <asm/io.h>#include <asm/mmu_context.h>#include <asm/mtrr.h>#include <asm/mce.h>#ifdef CONFIG_X86_LOCAL_APIC#include <asm/mpspec.h>#include <asm/apic.h>#include <mach_apic.h>#endif#include "cpu.h"DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {	[GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },	[GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },	[GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },	[GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },	/*	 * Segments used for calling PnP BIOS have byte granularity.	 * They code segments and data segments have fixed 64k limits,	 * the transfer segment sizes are set at run time.	 */	[GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */	[GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */	[GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */	[GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */	[GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */	/*	 * The APM segments have byte granularity and their bases	 * are set at run time.  All have 64k limits.	 */	[GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */	/* 16-bit code */	[GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },	[GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */	[GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },	[GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },} };EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);static int cachesize_override __cpuinitdata = -1;static int disable_x86_fxsr __cpuinitdata;static int disable_x86_serial_nr __cpuinitdata = 1;static int disable_x86_sep __cpuinitdata;struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};extern int disable_pse;static void __cpuinit default_init(struct cpuinfo_x86 * c){	/* Not much we can do here... */	/* Check if at least it has cpuid */	if (c->cpuid_level == -1) {		/* No cpuid. It must be an ancient CPU */		if (c->x86 == 4)			strcpy(c->x86_model_id, "486");		else if (c->x86 == 3)			strcpy(c->x86_model_id, "386");	}}static struct cpu_dev __cpuinitdata default_cpu = {	.c_init	= default_init,	.c_vendor = "Unknown",};static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;static int __init cachesize_setup(char *str){	get_option (&str, &cachesize_override);	return 1;}__setup("cachesize=", cachesize_setup);int __cpuinit get_model_name(struct cpuinfo_x86 *c){	unsigned int *v;	char *p, *q;	if (cpuid_eax(0x80000000) < 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;	/* Intel chips right-justify this string for some dumb reason;	   undo that brain damage */	p = q = &c->x86_model_id[0];	while ( *p == ' ' )	     p++;	if ( p != q ) {	     while ( *p )		  *q++ = *p++;	     while ( q <= &c->x86_model_id[48] )		  *q++ = '\0';	/* Zero-pad the rest */	}	return 1;}void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c){	unsigned int n, dummy, ecx, edx, l2size;	n = cpuid_eax(0x80000000);	if (n >= 0x80000005) {		cpuid(0x80000005, &dummy, &dummy, &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);		}	if (n < 0x80000006)	/* Some chips just has a large L1. */		return;	ecx = cpuid_ecx(0x80000006);	l2size = ecx >> 16;		/* do processor-specific cache resizing */	if (this_cpu->c_size_cache)		l2size = this_cpu->c_size_cache(c,l2size);	/* Allow user to override all this if necessary. */	if (cachesize_override != -1)		l2size = cachesize_override;	if ( l2size == 0 )		return;		/* Again, no L2 cache is possible */	c->x86_cache_size = l2size;	printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",	       l2size, ecx & 0xFF);}/* Naming convention should be: <Name> [(<Codename>)] *//* This table only is used unless init_<vendor>() below doesn't set it; *//* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used *//* Look up CPU names by table lookup. */static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c){	struct cpu_model_info *info;	if ( c->x86_model >= 16 )		return NULL;	/* Range check */	if (!this_cpu)		return NULL;	info = this_cpu->c_models;	while (info && info->family) {		if (info->family == c->x86)			return info->model_names[c->x86_model];		info++;	}	return NULL;		/* Not found */}static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early){	char *v = c->x86_vendor_id;	int i;	static int printed;	for (i = 0; i < X86_VENDOR_NUM; i++) {		if (cpu_devs[i]) {			if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||			    (cpu_devs[i]->c_ident[1] && 			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {				c->x86_vendor = i;				if (!early)					this_cpu = cpu_devs[i];				return;			}		}	}	if (!printed) {		printed++;		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");		printk(KERN_ERR "CPU: Your system may be unstable.\n");	}	c->x86_vendor = X86_VENDOR_UNKNOWN;	this_cpu = &default_cpu;}static int __init x86_fxsr_setup(char * s){	/* Tell all the other CPUs to not use it... */	disable_x86_fxsr = 1;	/*	 * ... and clear the bits early in the boot_cpu_data	 * so that the bootup process doesn't try to do this	 * either.	 */	clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability);	clear_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability);	return 1;}__setup("nofxsr", x86_fxsr_setup);static int __init x86_sep_setup(char * s){	disable_x86_sep = 1;	return 1;}__setup("nosep", x86_sep_setup);/* Standard macro to see if a specific flag is changeable */static inline int flag_is_changeable_p(u32 flag){	u32 f1, f2;	asm("pushfl\n\t"	    "pushfl\n\t"	    "popl %0\n\t"	    "movl %0,%1\n\t"	    "xorl %2,%0\n\t"	    "pushl %0\n\t"	    "popfl\n\t"	    "pushfl\n\t"	    "popl %0\n\t"	    "popfl\n\t"	    : "=&r" (f1), "=&r" (f2)	    : "ir" (flag));	return ((f1^f2) & flag) != 0;}/* Probe for the CPUID instruction */static int __cpuinit have_cpuid_p(void){	return flag_is_changeable_p(X86_EFLAGS_ID);}void __init cpu_detect(struct cpuinfo_x86 *c){	/* Get vendor name */	cpuid(0x00000000, &c->cpuid_level,	      (int *)&c->x86_vendor_id[0],	      (int *)&c->x86_vendor_id[8],	      (int *)&c->x86_vendor_id[4]);	c->x86 = 4;	if (c->cpuid_level >= 0x00000001) {		u32 junk, tfms, cap0, misc;		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);		c->x86 = (tfms >> 8) & 15;		c->x86_model = (tfms >> 4) & 15;		if (c->x86 == 0xf)			c->x86 += (tfms >> 20) & 0xff;		if (c->x86 >= 0x6)			c->x86_model += ((tfms >> 16) & 0xF) << 4;		c->x86_mask = tfms & 15;		if (cap0 & (1<<19))			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;	}}/* Do minimum CPU detection early.   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.   The others are not touched to avoid unwanted side effects.   WARNING: this function is only called on the BP.  Don't add code here   that is supposed to run on all CPUs. */static void __init early_cpu_detect(void){	struct cpuinfo_x86 *c = &boot_cpu_data;	c->x86_cache_alignment = 32;	if (!have_cpuid_p())		return;	cpu_detect(c);	get_cpu_vendor(c, 1);}static void __cpuinit generic_identify(struct cpuinfo_x86 * c){	u32 tfms, xlvl;	int ebx;	if (have_cpuid_p()) {		/* Get vendor name */		cpuid(0x00000000, &c->cpuid_level,		      (int *)&c->x86_vendor_id[0],		      (int *)&c->x86_vendor_id[8],		      (int *)&c->x86_vendor_id[4]);				get_cpu_vendor(c, 0);		/* Initialize the standard set of capabilities */		/* Note that the vendor-specific code below might override */			/* Intel-defined flags: level 0x00000001 */		if ( c->cpuid_level >= 0x00000001 ) {			u32 capability, excap;			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);			c->x86_capability[0] = capability;			c->x86_capability[4] = excap;			c->x86 = (tfms >> 8) & 15;			c->x86_model = (tfms >> 4) & 15;			if (c->x86 == 0xf)				c->x86 += (tfms >> 20) & 0xff;			if (c->x86 >= 0x6)				c->x86_model += ((tfms >> 16) & 0xF) << 4;			c->x86_mask = tfms & 15;#ifdef CONFIG_X86_HT			c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);#else			c->apicid = (ebx >> 24) & 0xFF;#endif			if (c->x86_capability[0] & (1<<19))				c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;		} else {			/* Have CPUID level 0 only - unheard of */			c->x86 = 4;		}		/* AMD-defined flags: level 0x80000001 */		xlvl = cpuid_eax(0x80000000);		if ( (xlvl & 0xffff0000) == 0x80000000 ) {			if ( xlvl >= 0x80000001 ) {				c->x86_capability[1] = cpuid_edx(0x80000001);				c->x86_capability[6] = cpuid_ecx(0x80000001);			}			if ( xlvl >= 0x80000004 )				get_model_name(c); /* Default name */		}		init_scattered_cpuid_features(c);	}	early_intel_workaround(c);#ifdef CONFIG_X86_HT	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;#endif}static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)

⌨️ 快捷键说明

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