From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Tue, 28 Apr 1998 22:56:14 -0400 From: jim mckie jmk@plan9.bell-labs.com Subject: [9fans] AMD cpu detection Topicbox-Message-UUID: 78323626-eac8-11e9-9e20-41e7f4b1d025 Message-ID: <19980429025614.Wh-YfF9UyqmZFkdXAfhur0-MG48a4L31OG6oFtnKGEk@z> I looked on the AMD web site and the following instructions are a stab at detecting the AMD chips. I can't try this myself (no AMD chips, no easy way to make a Plan 9 kernel) and there are no instruction timings available so I'd appreciate it if anyone who has an AMD chip could try this and report back. Once the chnages are installed the aalcycles table entries (commented with /* guesswork */) should be altered until the value printed by printcpufreq approximates the MHz of the processor. Thanks, Jim. 1) fns.h change int x86cpuid(int*, int*); to void cpuid(char*, int*, int*); 2) l.s replace x86cpuid by /* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruciton can be used * to determine CPU identity and features. First have to check if it's * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be * toggled then it's an older 486 of some kind. * * cpuid(id[], &ax, &dx); */ TEXT cpuid(SB), $0 MOVL $0x240000, AX PUSHL AX POPFL /* set Id|Ac */ PUSHFL POPL BX /* retrieve value */ MOVL $0, AX PUSHL AX POPFL /* clear Id|Ac, EFLAGS initialised */ PUSHFL POPL AX /* retrieve value */ XORL BX, AX TESTL $0x040000, AX /* Ac */ JZ _cpu386 /* can't set this bit on 386 */ TESTL $0x200000, AX /* Id */ JZ _cpu486 /* can't toggle this bit on some 486 */ MOVL $0, AX CPUID MOVL id+0(FP), BP MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */ MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */ MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */ MOVL $1, AX CPUID JMP _cpuid _cpu486: MOVL $0x400, AX MOVL $0, DX JMP _cpuid _cpu386: MOVL $0x300, AX MOVL $0, DX _cpuid: MOVL ax+4(FP), BP MOVL AX, 0(BP) MOVL dx+8(FP), BP MOVL DX, 0(BP) RET 3) clock.c a) add static char cpuidid[16]; after static int loopconst = 100; b) replace the x86type array with static X86type x86intel[] = { { 4, 0, 22, "486DX", }, /* known chips */ { 4, 1, 22, "486DX50", }, { 4, 2, 22, "486SX", }, { 4, 3, 22, "486DX2", }, { 4, 4, 22, "486SL", }, { 4, 5, 22, "486SX2", }, { 4, 7, 22, "DX2WB", }, /* P24D */ { 4, 8, 22, "DX4", }, /* P24C */ { 4, 9, 22, "DX4WB", }, /* P24CT */ { 5, 0, 23, "P5", }, { 5, 1, 23, "P5", }, { 5, 2, 23, "P54C", }, { 5, 3, 23, "P24T", }, { 5, 4, 23, "P55C MMX", }, { 5, 7, 23, "P54C VRT", }, { 6, 1, 16, "PentiumPro", },/* determined by trial and error */ { 6, 3, 16, "PentiumII", }, /* determined by trial and error */ { 6, 5, 16, "PentiumII", }, /* determined by trial and error */ { 3, -1, 32, "386", }, /* family defaults */ { 4, -1, 22, "486", }, { 5, -1, 23, "Pentium", }, { 6, -1, 16, "PentiumPro", }, { -1, -1, 23, "unknown", }, /* total default */ }; /* * The AMD processors all implement the CPUID instruction. * The later ones also return the processor name via functions * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX * and DX: * K5 "AMD-K5(tm) Processor" * K6 "AMD-K6tm w/ multimedia extensions" * K6 3D "AMD-K6(tm) 3D processor" * K6 3D+ ? */ static X86type x86amd[] = { { 5, 0, 23, "AMD-K5", }, /* guesswork */ { 5, 1, 23, "AMD-K5", }, /* guesswork */ { 5, 2, 23, "AMD-K5", }, /* guesswork */ { 5, 3, 23, "AMD-K5", }, /* guesswork */ { 5, 6, 23, "AMD-K6", }, /* guesswork */ { 5, 7, 23, "AMD-K6", }, /* guesswork */ { 5, 8, 23, "AMD-K6 3D", }, /* guesswork */ { 5, 9, 23, "AMD-K6 3D+", },/* guesswork */ { 4, -1, 22, "Am486", }, /* guesswork */ { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */ { -1, -1, 23, "unknown", }, /* total default */ }; c) replace the printcpufreq function with void printcpufreq(void) { int i; char buf[128]; i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz); if(m->cpuidid[0]) i += sprint(buf+i, "%s ", m->cpuidid); sprint(buf+i, "%s (cpuid: AX 0x%4.4luX DX 0x%4.4luX)\n", m->cpuidtype, m->cpuidax, m->cpuiddx); print(buf); } d) in clockinit replace x86cpuid(&cpuidax, &cpuiddx); family = FAMILY(cpuidax); model = MODEL(cpuidax); for(t = x86type; t->name; t++) if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; with cpuid(cpuidid, &cpuidax, &cpuiddx); if(strncmp(cpuidid, "AuthenticAMD", 12) == 0) t = x86amd; else t = x86intel; family = X86FAMILY(cpuidax); model = X86MODEL(cpuidax); while(t->name){ if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; t++; }