📄 setup.c
字号:
cli(); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ ccr5 = getCx86(CX86_CCR5); if (ccr5 & 2) setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */ setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ sti(); if (ccr5 & 2) { /* possible wrong calibration done */ printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n"); calibrate_delay(); c->loops_per_jiffy = loops_per_jiffy; } }}static void __init init_cyrix(struct cpuinfo_x86 *c){ unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; char *buf = c->x86_model_id; const char *p = NULL; /* 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); /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */ if ( test_bit(1*32+24, &c->x86_capability) ) { clear_bit(1*32+24, &c->x86_capability); set_bit(X86_FEATURE_CXMMX, &c->x86_capability); } do_cyrix_devid(&dir0, &dir1); check_cx686_slop(c); Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */ dir0_lsn = dir0 & 0xf; /* model or clock multiplier */ /* common case step number/rev -- exceptions handled below */ c->x86_model = (dir1 >> 4) + 1; c->x86_mask = dir1 & 0xf; /* Now cook; the original recipe is by Channing Corn, from Cyrix. * We do the same thing for each generation: we work out * the model, multiplier and stepping. Black magic included, * to make the silicon step/rev numbers match the printed ones. */ switch (dir0_msn) { unsigned char tmp; case 0: /* Cx486SLC/DLC/SRx/DRx */ p = Cx486_name[dir0_lsn & 7]; break; case 1: /* Cx486S/DX/DX2/DX4 */ p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5] : Cx486S_name[dir0_lsn & 3]; break; case 2: /* 5x86 */ Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5]; p = Cx86_cb+2; break; case 3: /* 6x86/6x86L */ Cx86_cb[1] = ' '; Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5]; if (dir1 > 0x21) { /* 686L */ Cx86_cb[0] = 'L'; p = Cx86_cb; (c->x86_model)++; } else /* 686 */ p = Cx86_cb+1; /* Emulate MTRRs using Cyrix's ARRs. */ set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability); /* 6x86's contain this bug */ c->coma_bug = 1; break; case 4: /* MediaGX/GXm */ /* * Life sometimes gets weiiiiiiiird if we use this * on the MediaGX. So we turn it off for now. */ #ifdef CONFIG_PCI /* It isnt really a PCI quirk directly, but the cure is the same. The MediaGX has deep magic SMM stuff that handles the SB emulation. It thows away the fifo on disable_dma() which is wrong and ruins the audio. Bug2: VSA1 has a wrap bug so that using maximum sized DMA causes bad things. According to NatSemi VSA2 has another bug to do with 'hlt'. I've not seen any boards using VSA2 and X doesn't seem to support it either so who cares 8). VSA1 we work around however. */ printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n"); isa_dma_bridge_buggy = 2;#endif c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { get_model_name(c); /* get CPU marketing name */ clear_bit(X86_FEATURE_TSC, c->x86_capability); return; } else { /* MediaGX */ Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4'; p = Cx86_cb+2; c->x86_model = (dir1 & 0x20) ? 1 : 2; clear_bit(X86_FEATURE_TSC, &c->x86_capability); } break; case 5: /* 6x86MX/M II */ if (dir1 > 7) dir0_msn++; /* M II */ else c->coma_bug = 1; /* 6x86MX, it has the bug. */ tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0; Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7]; p = Cx86_cb+tmp; if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20)) (c->x86_model)++; /* Emulate MTRRs using Cyrix's ARRs. */ set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability); break; case 0xf: /* Cyrix 486 without DEVID registers */ switch (dir0_lsn) { case 0xd: /* either a 486SLC or DLC w/o DEVID */ dir0_msn = 0; p = Cx486_name[(c->hard_math) ? 1 : 0]; break; case 0xe: /* a 486S A step */ dir0_msn = 0; p = Cx486S_name[0]; break; } break; default: /* unknown (shouldn't happen, we know everyone ;-) */ dir0_msn = 7; break; } strcpy(buf, Cx86_model[dir0_msn & 7]); if (p) strcat(buf, p); return;}static void __init init_centaur(struct cpuinfo_x86 *c){ enum { ECX8=1<<1, EIERRINT=1<<2, DPM=1<<3, DMCE=1<<4, DSTPCLK=1<<5, ELINEAR=1<<6, DSMC=1<<7, DTLOCK=1<<8, EDCTLB=1<<8, EMMX=1<<9, DPDC=1<<11, EBRPRED=1<<12, DIC=1<<13, DDC=1<<14, DNA=1<<15, ERETSTK=1<<16, E2MMX=1<<19, EAMD3D=1<<20, }; char *name; u32 fcr_set=0; u32 fcr_clr=0; u32 lo,hi,newlo; u32 aa,bb,cc,dd; /* 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); switch (c->x86) { case 5: switch(c->x86_model) { case 4: name="C6"; fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK; fcr_clr=DPDC; printk("Disabling bugged TSC.\n"); clear_bit(X86_FEATURE_TSC, &c->x86_capability); break; case 8: switch(c->x86_mask) { default: name="2"; break; case 7 ... 9: name="2A"; break; case 10 ... 15: name="2B"; break; } fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D; fcr_clr=DPDC; break; case 9: name="3"; fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D; fcr_clr=DPDC; break; case 10: name="4"; /* no info on the WC4 yet */ break; default: name="??"; } /* get FCR */ rdmsr(0x107, lo, hi); newlo=(lo|fcr_set) & (~fcr_clr); if (newlo!=lo) { printk("Centaur FCR was 0x%X now 0x%X\n", lo, newlo ); wrmsr(0x107, newlo, hi ); } else { printk("Centaur FCR is 0x%X\n",lo); } /* Emulate MTRRs using Centaur's MCR. */ set_bit(X86_FEATURE_CENTAUR_MCR, &c->x86_capability); /* Report CX8 */ set_bit(X86_FEATURE_CX8, &c->x86_capability); /* Set 3DNow! on Winchip 2 and above. */ if (c->x86_model >=8) set_bit(X86_FEATURE_3DNOW, &c->x86_capability); /* See if we can find out some more. */ if ( cpuid_eax(0x80000000) >= 0x80000005 ) { /* Yes, we can. */ cpuid(0x80000005,&aa,&bb,&cc,&dd); /* Add L1 data and code cache sizes. */ c->x86_cache_size = (cc>>24)+(dd>>24); } sprintf( c->x86_model_id, "WinChip %s", name ); break; case 6: switch (c->x86_model) { case 6: /* Cyrix III */ rdmsr (0x1107, lo, hi); lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ wrmsr (0x1107, lo, hi); set_bit(X86_FEATURE_CX8, &c->x86_capability); rdmsr (0x80000001, lo, hi); if (hi & (1<<31)) set_bit(X86_FEATURE_3DNOW, &c->x86_capability); get_model_name(c); display_cacheinfo(c); break; } break; }}static void __init init_transmeta(struct cpuinfo_x86 *c){ unsigned int cap_mask, uk, max, dummy; unsigned int cms_rev1, cms_rev2; unsigned int cpu_rev, cpu_freq, cpu_flags; char cpu_info[65]; get_model_name(c); /* Same as AMD/Cyrix */ display_cacheinfo(c); /* Print CMS and CPU revision */ max = cpuid_eax(0x80860000); if ( max >= 0x80860001 ) { cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); printk("CPU: Processor revision %u.%u.%u.%u, %u MHz\n", (cpu_rev >> 24) & 0xff, (cpu_rev >> 16) & 0xff, (cpu_rev >> 8) & 0xff, cpu_rev & 0xff, cpu_freq); } if ( max >= 0x80860002 ) { cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy); printk("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n", (cms_rev1 >> 24) & 0xff, (cms_rev1 >> 16) & 0xff, (cms_rev1 >> 8) & 0xff, cms_rev1 & 0xff, cms_rev2); } if ( max >= 0x80860006 ) { cpuid(0x80860003, (void *)&cpu_info[0], (void *)&cpu_info[4], (void *)&cpu_info[8], (void *)&cpu_info[12]); cpuid(0x80860004, (void *)&cpu_info[16], (void *)&cpu_info[20], (void *)&cpu_info[24], (void *)&cpu_info[28]); cpuid(0x80860005, (void *)&cpu_info[32], (void *)&cpu_info[36], (void *)&cpu_info[40], (void *)&cpu_info[44]); cpuid(0x80860006, (void *)&cpu_info[48], (void *)&cpu_info[52], (void *)&cpu_info[56], (void *)&cpu_info[60]); cpu_info[64] = '\0'; printk("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);}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 extern void mcheck_init(struct cpuinfo_x86 *c); 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_INFO "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 */ if ( dl ) { /* 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("CPU: L1 I cache: %dK, L1 D cache: %dK\n", l1i, l1d); if ( l2 ) printk("CPU: L2 cache: %dK\n", l2); if ( l3 ) printk("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); /* Enable MCA if available */ mcheck_init(c);}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)",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -