rendered paste body/*
* 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<<i)){
printf("%s\n",AMDfeature_flags[i]);
}
}
}
}
}
/* Check for presence of extended info */
do_cpuid(0x80000000,xcpuid);
maxei = xcpuid[0];
if(maxei == 0)
return;
if(maxei >= 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<<i)){
printf("%s\n",AMDfeature_flags[i]);
}
}
}
}
printf("\n");
if(maxei >= 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);
}
}