/* * amd.c * * Reference documents: * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/20734.pdf * */ #include "cpuid.h" char *AMDfeature_flags[] = { "Floating Point Unit", "Virtual Mode Extensions", "Debugging Extensions", "Page Size Extensions", "Time Stamp Counter (with RDTSC and CR4 disable bit)", "Model Specific Registers with RDMSR & WRMSR", "PAE - Page Address Extensions", "Machine Check Exception", "COMPXCHG8B Instruction", "APIC", "10 - Reserved", "SYSCALL/SYSRET or SYSENTER/SYSEXIT instructions", "MTRR - Memory Type Range Registers", "Global paging extension", "Machine Check Architecture", "Conditional Move Instruction", "PAT - Page Attribute Table", "PSE-36 - Page Size Extensions", "18 - reserved", "19 - reserved", "20 - reserved", "21 - reserved", "AMD MMX Instruction Extensions", "MMX instructions", "FXSAVE/FXRSTOR", "25 - reserved", "26 - reserved", "27 - reserved", "28 - reserved", "29 - reserved", "3DNow! Instruction Extensions", "3DNow instructions", }; char *Assoc[] = { "L2 off", "Direct mapped", "2-way", "reserved", "4-way", "reserved", "8-way", "reserved", "16-way", "reserved", "reserved", "reserved", "reserved", "reserved", "reserved", "full", }; /* AMD-specific information */ void doamd(int maxi){ uint32_t maxei, xcpuid[4]; int family = 0; printf("AMD-specific functions\n"); /* Do standard stuff */ if(maxi >= 1){ uint32_t xcpuid[4]; int stepping,model,reserved; do_cpuid(1,xcpuid); stepping = xcpuid[0] & 0xf; model = (xcpuid[0] >> 4) & 0xf; family = (xcpuid[0] >> 8) & 0xf; reserved = xcpuid[0] >> 12; printf("Version %08x:\n",xcpuid[0]); printf("Family: %d Model: %d [",family,model); switch(family){ case 4: printf("486 model %d",model); break; case 5: switch(model){ case 0: case 1: case 2: case 3: case 6: case 7: printf("K6 Model %d",model); break; case 8: printf("K6-2 Model 8"); break; case 9: printf("K6-III Model 9"); break; default: printf("K5/K6 model %d",model); break; } break; case 6: switch(model){ case 1: case 2: case 4: printf("Athlon model %d",model); break; case 3: printf("Duron model 3"); break; case 6: printf("Athlon MP/Mobile Athlon model 6"); break; case 7: printf("Mobile Duron Model 7"); break; default: printf("Duron/Athlon model %d",model); break; } break; } printf("]\n\n"); { int i; printf("Standard feature flags %08x:\n",xcpuid[3]); for(i=0;i<32;i++){ if(family == 5 && model == 0){ if(i == 9) printf("Global Paging Extensions\n"); else if(i == 13) printf("13 - reserved\n"); } else { if(xcpuid[3] & (1<= 0x80000001){ uint32_t xcpuid[4]; int stepping,model,generation,reserved; int i; do_cpuid(0x80000001,xcpuid); stepping = xcpuid[0] & 0xf; model = (xcpuid[0] >> 4) & 0xf; generation = (xcpuid[0] >> 8) & 0xf; reserved = xcpuid[0] >> 12; printf("Generation: %d Model: %d\n",generation,model); printf("Extended feature flags %08x:\n",xcpuid[3]); for(i=0;i<32;i++){ if(family == 5 && model == 0 && i == 9){ printf("Global Paging Extensions\n"); } else { if(xcpuid[3] & (1<= 0x80000002){ /* Processor identification string */ int j; printf("Processor name string: "); for(j=0x80000002;j<=0x80000004;j++){ uint32_t xcpuid[4]; do_cpuid(j,xcpuid); printregs(xcpuid); } printf("\n"); } if(maxei >= 0x80000005){ /* TLB and cache info */ uint32_t xcpuid[4]; do_cpuid(0x80000005,xcpuid); printf("L1 Cache Information:\n"); if(family >= 6){ printf("2/4-MB Pages:\n"); printf(" Data TLB: associativity %d-way #entries %d\n", (xcpuid[0] >> 24) & 0xff,(xcpuid[0] >> 16) & 0xff); printf(" Instruction TLB: associativity %d-way #entries %d\n", (xcpuid[0] >> 8) & 0xff,xcpuid[0] & 0xff); } printf("4-KB Pages:\n"); printf(" Data TLB: associativity %d-way #entries %d\n", (xcpuid[1] >> 24) & 0xff,(xcpuid[1] >> 16) & 0xff); printf(" Instruction TLB: associativity %d-way #entries %d\n", (xcpuid[1] >> 8) & 0xff,xcpuid[1] & 0xff); printf("L1 Data cache:\n"); printf(" size %d KB associativity %x-way lines per tag %d line size %d\n", xcpuid[2] >> 24,(xcpuid[2]>>16) & 0xff,(xcpuid[2] >> 8)&0xff,xcpuid[2]&0xff); printf("L1 Instruction cache:\n"); printf(" size %d KB associativity %x-way lines per tag %d line size %d\n", xcpuid[3] >> 24,(xcpuid[3]>>16) & 0xff,(xcpuid[3] >> 8)&0xff,xcpuid[3]&0xff); printf("\n"); } /* check K6-III (and later?) on-chip L2 cache size */ if (maxei >= 0x80000006) { uint32_t xcpuid[4]; int assoc; do_cpuid(0x80000006,xcpuid); printf("L2 Cache Information:\n"); if(family >= 6){ printf("2/4-MB Pages:\n"); assoc = (xcpuid[0] >> 24) & 0xff; if(assoc == 6) assoc = 8; printf(" Data TLB: associativity %s #entries %d\n", Assoc[(xcpuid[0] >> 24) & 0xf],(xcpuid[0] >> 16) & 0xff); assoc = (xcpuid[0] >> 16) & 0xff; printf(" Instruction TLB: associativity %s #entries %d\n", Assoc[(xcpuid[0] >> 8) & 0xf],xcpuid[0] & 0xff); printf("4-KB Pages:\n"); printf(" Data TLB: associativity %s #entries %d\n", Assoc[(xcpuid[1] >> 24) & 0xf],(xcpuid[1] >> 16) & 0xff); printf(" Instruction TLB: associativity %s #entries %d\n", Assoc[(xcpuid[1] >> 8) & 0xf],xcpuid[1] & 0xff); } printf(" size %d KB associativity %s lines per tag %d line size %d\n", xcpuid[2] >> 24,Assoc[(xcpuid[2]>>16) & 0xf],(xcpuid[2] >> 8)&0xff,xcpuid[2]&0xff); printf("\n"); } /* Check power management feature flags */ if(maxei >= 0x80000007){ uint32_t xcpuid[4]; printf("Advanced Power Management Feature Flags\n"); do_cpuid(0x80000007,xcpuid); if(xcpuid[3] & 1) printf("Has temperature sensing diode\n"); if(xcpuid[3] & 2) printf("Supports Frequency ID control\n"); if(xcpuid[3] & 4) printf("Supports Voltage ID control\n"); } /* Check phys address & linear address size */ if(maxei >= 0x80000008){ uint32_t xcpuid[4]; do_cpuid(0x80000008,xcpuid); printf("Maximum linear address: %d; maximum phys address %d\n", (xcpuid[0]>>8) & 0xff,xcpuid[0]&0xff); } }