📄 common.c
字号:
#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 <asm/semaphore.h>#include <asm/processor.h>#include <asm/i387.h>#include <asm/msr.h>#include <asm/io.h>#include <asm/mmu_context.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 desc_struct, cpu_gdt_table[GDT_ENTRIES]);EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);static int cachesize_override __devinitdata = -1;static int disable_x86_fxsr __devinitdata = 0;static int disable_x86_serial_nr __devinitdata = 1;struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};extern int disable_pse;static void 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 default_cpu = { .c_init = default_init,};static struct cpu_dev * this_cpu = &default_cpu;static int __init cachesize_setup(char *str){ get_option (&str, &cachesize_override); return 1;}__setup("cachesize=", cachesize_setup);int __devinit 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 __devinit 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 __devinit *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 __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early){ char *v = c->x86_vendor_id; int i; 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]; break; } } }}static int __init x86_fxsr_setup(char * s){ disable_x86_fxsr = 1; return 1;}__setup("nofxsr", x86_fxsr_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 __devinit have_cpuid_p(void){ return flag_is_changeable_p(X86_EFLAGS_ID);}/* 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; /* 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, 1); 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; }}void __devinit generic_identify(struct cpuinfo_x86 * c){ u32 tfms, xlvl; int junk; 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, &junk, &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; c->x86_model += ((tfms >> 16) & 0xF) << 4; } c->x86_mask = tfms & 15; } 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 */ } } early_intel_workaround(c);#ifdef CONFIG_X86_HT phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;#endif}static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c){ if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) { /* Disable processor serial number */ unsigned long lo,hi; rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi); lo |= 0x200000; wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi); printk(KERN_NOTICE "CPU serial number disabled.\n"); clear_bit(X86_FEATURE_PN, c->x86_capability); /* Disabling the serial number may affect the cpuid level */ c->cpuid_level = cpuid_eax(0); }}static int __init x86_serial_nr_setup(char *s){ disable_x86_serial_nr = 0; return 1;}__setup("serialnumber", x86_serial_nr_setup);/* * This does the hard work of actually picking apart the CPU stuff... */void __devinit identify_cpu(struct cpuinfo_x86 *c)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -