📄 setup.c
字号:
printk(KERN_INFO "CPU: %s\n", cpu_info); } /* Unhide possibly hidden capability flags */ rdmsr(0x80860004, cap_mask, uk); wrmsr(0x80860004, ~0, uk); c->x86_capability[0] = cpuid_edx(0x00000001); wrmsr(0x80860004, cap_mask, uk);}static void __init init_rise(struct cpuinfo_x86 *c){ printk("CPU: Rise iDragon"); if (c->x86_model > 2) printk(" II"); printk("\n"); /* Unhide possibly hidden capability flags The mp6 iDragon family don't have MSRs. We switch on extra features with this cpuid weirdness: */ __asm__ ( "movl $0x6363452a, %%eax\n\t" "movl $0x3231206c, %%ecx\n\t" "movl $0x2a32313a, %%edx\n\t" "cpuid\n\t" "movl $0x63634523, %%eax\n\t" "movl $0x32315f6c, %%ecx\n\t" "movl $0x2333313a, %%edx\n\t" "cpuid\n\t" : : : "eax", "ebx", "ecx", "edx" ); set_bit(X86_FEATURE_CX8, &c->x86_capability);}extern void trap_init_f00f_bug(void);static void __init init_intel(struct cpuinfo_x86 *c){#ifndef CONFIG_M686 static int f00f_workaround_enabled = 0;#endif char *p = NULL; unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */#ifndef CONFIG_M686 /* * All current models of Pentium and Pentium with MMX technology CPUs * have the F0 0F bug, which lets nonpriviledged users lock up the system. * Note that the workaround only should be initialized once... */ c->f00f_bug = 0; if ( c->x86 == 5 ) { c->f00f_bug = 1; if ( !f00f_workaround_enabled ) { trap_init_f00f_bug(); printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); f00f_workaround_enabled = 1; } }#endif if (c->cpuid_level > 1) { /* supports eax=2 call */ int i, j, n; int regs[4]; unsigned char *dp = (unsigned char *)regs; /* Number of times to iterate */ n = cpuid_eax(2) & 0xFF; for ( i = 0 ; i < n ; i++ ) { cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); /* If bit 31 is set, this is an unknown format */ for ( j = 0 ; j < 3 ; j++ ) { if ( regs[j] < 0 ) regs[j] = 0; } /* Byte 0 is level count, not a descriptor */ for ( j = 1 ; j < 16 ; j++ ) { unsigned char des = dp[j]; unsigned char dl, dh; unsigned int cs; dh = des >> 4; dl = des & 0x0F; /* Black magic... */ switch ( dh ) { case 0: switch ( dl ) { case 6: /* L1 I cache */ l1i += 8; break; case 8: /* L1 I cache */ l1i += 16; break; case 10: /* L1 D cache */ l1d += 8; break; case 12: /* L1 D cache */ l1d += 16; break; default:; /* TLB, or unknown */ } break; case 2: if ( dl ) { /* L3 cache */ cs = (dl-1) << 9; l3 += cs; } break; case 4: if ( c->x86 > 6 && dl ) { /* P4 family */ /* L3 cache */ cs = 128 << (dl-1); l3 += cs; break; } /* else same as 8 - fall through */ case 8: if ( dl ) { /* L2 cache */ cs = 128 << (dl-1); l2 += cs; } break; case 6: if (dl > 5) { /* L1 D cache */ cs = 8<<(dl-6); l1d += cs; } break; case 7: if ( dl >= 8 ) { /* L2 cache */ cs = 64<<(dl-8); l2 += cs; } else { /* L0 I cache, count as L1 */ cs = dl ? (16 << (dl-1)) : 12; l1i += cs; } break; default: /* TLB, or something else we don't know about */ break; } } } if ( l1i || l1d ) printk(KERN_INFO "CPU: L1 I cache: %dK, L1 D cache: %dK\n", l1i, l1d); if ( l2 ) printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); if ( l3 ) printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); /* * This assumes the L3 cache is shared; it typically lives in * the northbridge. The L1 caches are included by the L2 * cache, and so should not be included for the purpose of * SMP switching weights. */ c->x86_cache_size = l2 ? l2 : (l1i+l1d); } /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */ if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 ) clear_bit(X86_FEATURE_SEP, &c->x86_capability); /* Names for the Pentium II/Celeron processors detectable only by also checking the cache size. Dixon is NOT a Celeron. */ if (c->x86 == 6) { switch (c->x86_model) { case 5: if (l2 == 0) p = "Celeron (Covington)"; if (l2 == 256) p = "Mobile Pentium II (Dixon)"; break; case 6: if (l2 == 128) p = "Celeron (Mendocino)"; break; case 8: if (l2 == 128) p = "Celeron (Coppermine)"; break; } } if ( p ) strcpy(c->x86_model_id, p); #ifdef CONFIG_SMP if (test_bit(X86_FEATURE_HT, &c->x86_capability)) { extern int phys_proc_id[NR_CPUS]; u32 eax, ebx, ecx, edx; int index_lsb, index_msb, tmp; int initial_apic_id; int cpu = smp_processor_id(); cpuid(1, &eax, &ebx, &ecx, &edx); smp_num_siblings = (ebx & 0xff0000) >> 16; if (smp_num_siblings == 1) { printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); } else if (smp_num_siblings > 1 ) { index_lsb = 0; index_msb = 31; /* * At this point we only support two siblings per * processor package. */#define NR_SIBLINGS 2 if (smp_num_siblings != NR_SIBLINGS) { printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); smp_num_siblings = 1; goto too_many_siblings; } tmp = smp_num_siblings; while ((tmp & 1) == 0) { tmp >>=1 ; index_lsb++; } tmp = smp_num_siblings; while ((tmp & 0x80000000 ) == 0) { tmp <<=1 ; index_msb--; } if (index_lsb != index_msb ) index_msb++; initial_apic_id = ebx >> 24 & 0xff; phys_proc_id[cpu] = initial_apic_id >> index_msb; printk(KERN_INFO "CPU: Physical Processor ID: %d\n", phys_proc_id[cpu]); } }too_many_siblings:#endif}void __init get_cpu_vendor(struct cpuinfo_x86 *c){ char *v = c->x86_vendor_id; if (!strcmp(v, "GenuineIntel")) c->x86_vendor = X86_VENDOR_INTEL; else if (!strcmp(v, "AuthenticAMD")) c->x86_vendor = X86_VENDOR_AMD; else if (!strcmp(v, "CyrixInstead")) c->x86_vendor = X86_VENDOR_CYRIX; else if (!strcmp(v, "UMC UMC UMC ")) c->x86_vendor = X86_VENDOR_UMC; else if (!strcmp(v, "CentaurHauls")) c->x86_vendor = X86_VENDOR_CENTAUR; else if (!strcmp(v, "NexGenDriven")) c->x86_vendor = X86_VENDOR_NEXGEN; else if (!strcmp(v, "RiseRiseRise")) c->x86_vendor = X86_VENDOR_RISE; else if (!strcmp(v, "GenuineTMx86") || !strcmp(v, "TransmetaCPU")) c->x86_vendor = X86_VENDOR_TRANSMETA; else c->x86_vendor = X86_VENDOR_UNKNOWN;}struct cpu_model_info { int vendor; int family; char *model_names[16];};/* 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 */static struct cpu_model_info cpu_models[] __initdata = { { X86_VENDOR_INTEL, 4, { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 5, { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75 - 200", "OverDrive PODP5V83", "Pentium MMX", NULL, NULL, "Mobile Pentium 75 - 200", "Mobile Pentium MMX", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 6, { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", NULL, "Pentium II (Deschutes)", "Mobile Pentium II", "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL, "Pentium III (Cascades)", NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 4, { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB" }}, { X86_VENDOR_AMD, 5, /* Is this this really necessary?? */ { "K5/SSA5", "K5", "K5", "K5", NULL, NULL, "K6", "K6", "K6-2", "K6-3", NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 6, /* Is this this really necessary?? */ { "Athlon", "Athlon", "Athlon", NULL, "Athlon", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_UMC, 4, { NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_NEXGEN, 5, { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_RISE, 5, { "iDragon", NULL, "iDragon", NULL, NULL, NULL, NULL, NULL, "iDragon II", "iDragon II", NULL, NULL, NULL, NULL, NULL, NULL }},};/* Look up CPU names by table lookup. */static char __init *table_lookup_model(struct cpuinfo_x86 *c){ struct cpu_model_info *info = cpu_models; int i; if ( c->x86_model >= 16 ) return NULL; /* Range check */ for ( i = 0 ; i < sizeof(cpu_models)/sizeof(struct cpu_model_info) ; i++ ) { if ( info->vendor == c->x86_vendor && info->family == c->x86 ) { return info->model_names[c->x86_model]; } info++; } return NULL; /* Not found */}/* * Detect a NexGen CPU running without BIOS hypercode new enough * to have CPUID. (Thanks to Herbert Oppmann) */ static int __init deep_magic_nexgen_probe(void){ int ret; __asm__ __volatile__ ( " movw $0x5555, %%ax\n" " xorw %%dx,%%dx\n" " movw $2, %%cx\n" " divw %%cx\n" " movl $0, %%eax\n" " jnz 1f\n" " movl $1, %%eax\n" "1:\n" : "=a" (ret) : : "cx", "dx" ); return ret;}static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c){ if( test_bit(X86_FEATURE_PN, &c->x86_capability) && 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);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 __init have_cpuid_p(void){ return flag_is_changeable_p(X86_EFLAGS_ID);}/* * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected * by the fact that they preserve the flags across the division of 5/2. * PII and PPro exhibit this behavior too, but they have cpuid available. */ /* * Perform the Cyrix 5/2 test. A Cyrix won't change * the flags, while other 486 chips will. */static inline int test_cyrix_52div(void){ unsigned int test; __asm__ __volatile__( "sahf\n\t" /* clear flags (%eax = 0x0005) */ "div %b2\n\t" /* divide 5 by 2 */ "lahf" /* store flags into %ah */ : "=a" (test) : "0" (5), "q" (2) : "cc"); /* AH is 0x02 on Cyrix after the divide.. */ return (unsigned char) (test >> 8) == 0x02;}/* Try to detect a CPU with disabled CPUID, and if so, enable. This routine may also be used to detect non-CPUID processors and fill in some of the information manually. */static int __init id_and_try_enable_cpuid(struct cpuinfo_x86 *c){ /* First of all, decide if this is a 486 or higher */ /* It's a 486 if we can modify the AC flag */ if ( flag_is_changeable_p(X86_EFLAGS_AC) ) c->x86 = 4; else c->x86 = 3; /* Detect Cyrix with disabled CPUID */ if ( c->x86 == 4 && test_cyrix_52div() ) { unsigned char dir0, dir1; strcpy(c->x86_vendor_id, "CyrixInstead"); c->x86_vendor = X86_VENDOR_CYRIX; /* Actually enable cpuid on the older cyrix */ /* Retrieve CPU revisions */ do_cyrix_devid(&dir0, &dir1); dir0>>=4; /* Check it is an affected model */ if (dir0 == 5 || dir0 == 3) { uns
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -