implemented the get_cpuid() function in libroot and added a new kernel app 'cpuinfo'

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1583 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Daniel Reinhold
2002-10-20 05:28:35 +00:00
parent b52ed331f1
commit 98e3e1ff5d
3 changed files with 625 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
SubDir OBOS_TOP src kernel apps cpuinfo ;
KernelObjects <$(SOURCE_GRIST)>main.c : -fpic ;
+178
View File
@@ -0,0 +1,178 @@
static char *Intel_feature_flags[32] = {
"FPU Floating Point Unit",
"VME Virtual 8086 Mode Enhancements",
"DE Debugging Extensions",
"PSE Page Size Extensions",
"TSC Time Stamp Counter",
"MSR Model Specific Registers",
"PAE Physical Address Extension",
"MCE Machine Check Exception",
"CX8 COMPXCHG8B Instruction",
"APIC On-chip Advanced Programmable Interrupt Controller",
"10 Reserved",
"SEP Fast System Call",
"MTRR Memory Type Range Registers",
"PGE PTE Global Flag",
"MCA Machine Check Architecture",
"CMOV Conditional Move and Compare Instructions",
"FGPAT Page Attribute Table",
"PSE-36 36-bit Page Size Extension",
"PN Processor Serial Number present and enabled",
"CLFSH CFLUSH instruction",
"20 reserved",
"DS Debug store",
"ACPI Thermal Monitor and Clock Ctrl",
"MMX MMX instruction set",
"FXSR Fast FP/MMX Streaming SIMD Extensions save/restore",
"SSE Streaming SIMD Extensions instruction set",
"SSE2 SSE2 extensions",
"SS Self Snoop",
"HT Hyper Threading",
"TM Thermal monitor",
"30 reserved",
"31 reserved"
};
#if 0
static char *AMD_feature_flags[32] = {
"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"
};
static char *Cyrix_standard_feature_flags_5[32] = {
"FPU Floating Point Unit",
"V86 Virtual Mode Extensions",
"Debug Extension",
"4MB Page Size",
"Time Stamp Counter",
"RDMSR/WRMSR (Model Specific Registers)",
"PAE",
"Machine Check Exception",
"COMPXCHG8B Instruction",
"APIC - On-chip Advanced Programmable Interrupt Controller",
"10 - Reserved",
"11 - Reserved",
"MTRR Memory Type Range Registers",
"13 - reserved",
"Machine Check",
"CMOV Conditional Move Instruction",
"16 - reserved",
"17 - reserved",
"18 - reserved",
"19 - reserved",
"20 - reserved",
"21 - reserved",
"22 - reserved",
"MMX instructions",
"24 - reserved",
"25 - reserved",
"26 - reserved",
"27 - reserved",
"28 - reserved",
"29 - reserved",
"30 - reserved"
};
static char *Cyrix_standard_feature_flags_not5[32] = {
"FPU Floating Point Unit",
"V86 Virtual Mode Extensions",
"Debug Extension",
"4MB Page Size",
"Time Stamp Counter",
"RDMSR/WRMSR (Model Specific Registers)",
"PAE",
"Machine Check Exception",
"COMPXCHG8B Instruction",
"APIC - On-chip Advanced Programmable Interrupt Controller",
"10 - Reserved",
"11 - Reserved",
"MTRR Memory Type Range Registers",
"Global Paging Extension",
"Machine Check",
"CMOV Conditional Move Instruction",
"16 - reserved",
"17 - reserved",
"18 - reserved",
"19 - reserved",
"20 - reserved",
"21 - reserved",
"22 - reserved",
"MMX instructions",
"24 - reserved",
"25 - reserved",
"26 - reserved",
"27 - reserved",
"28 - reserved",
"29 - reserved",
"30 - reserved"
};
static char *Cyrix_extended_feature_flags[32] = {
"FPU Floating Point Unit",
"V86 Virtual Mode Extensions",
"Debug Extension",
"Page Size Extensions",
"Time Stamp Counter",
"Cyrix MSR",
"PAE",
"MC Exception",
"COMPXCHG8B",
"APIC on chip",
"SYSCALL/SYSRET",
"11 - reserved",
"MTRR",
"Global bit",
"Machine Check",
"CMOV",
"FPU CMOV",
"17 - reserved",
"18 - reserved",
"19 - reserved",
"20 - reserved",
"21 - reserved",
"22 - reserved",
"MMX",
"Extended MMX",
"25 - reserved",
"26 - reserved",
"27 - reserved",
"28 - reserved",
"29 - reserved",
"30 - reserved",
"3DNow instructions"
};
#endif
+444
View File
@@ -0,0 +1,444 @@
#include <OS.h>
#include <stdio.h>
//#include <stdlib.h> -- when exit() is implemented
#include <string.h>
#include "flag_arrays.c"
void AMD_identify (cpuid_info *);
void AMD_features (cpuid_info *);
void AMD_TLB_cache (cpuid_info *);
void Cyrix_identify (cpuid_info *);
void Cyrix_features (cpuid_info *);
void Cyrix_TLB_cache (cpuid_info *);
void Intel_identify (cpuid_info *);
void Intel_features (cpuid_info *);
void Intel_TLB_cache (cpuid_info *);
const char *Intel_brand_string (int, int);
void dump_regs (cpuid_info *, const char *, uint32, uint32);
char getoption (char *optstr);
void opt_identify (cpuid_info *, int);
void opt_features (cpuid_info *, int);
void opt_TLB_cache (cpuid_info *, int);
void opt_dump_calls (cpuid_info *, uint32);
void print_regs (cpuid_info *);
void usage (void);
static cpuid_info CPU_Data;
void
usage()
{
printf("usage: cpuinfo [-option]\n\n"
"Prints information about your CPU.\n"
" -i CPU identification\n"
" -f supported processor features\n"
" -t TLB and cache info\n"
" -d dump registers from CPUID calls\n");
//exit(0);
}
char
getoption(char *optstr)
{
if ((optstr[0] != '-')
|| (strlen(optstr) > 2)
|| (strchr("iftd", optstr[1]) == NULL))
// invalid option
return 0;
return optstr[1];
}
int
main(int argc, char *argv[])
{
// technical reference:
// "Intel Processor Identification and the CPUID Instruction"
// (ftp://download.intel.com/design/Xeon/applnots/24161821.pdf)
char option = 0;
int vendor_tag;
uint32 max_level;
cpuid_info *info = &CPU_Data;
if (argc == 2)
option = getoption(argv[1]);
if (option == 0) {
usage();
return 0;
}
// get initial info (max_level and vendor_tag)
get_cpuid(info, 0, 0);
max_level = info->eax_0.max_eax;
if (max_level < 1) {
printf("\nSorry, your computer does not seem to support the CPUID instruction\n");
return 1;
}
vendor_tag = info->regs.ebx;
switch (option) {
case 'i':
opt_identify(info, vendor_tag);
break;
case 'f':
opt_features(info, vendor_tag);
break;
case 't':
opt_TLB_cache(info, vendor_tag);
break;
case 'd':
opt_dump_calls(info, max_level);
break;
}
return 0;
}
void
opt_identify(cpuid_info *info, int vendor_tag)
{
char vendorID[12+1] = {0};
// the 'vendorid' field of the info struct is not null terminated,
// so it is copied into a properly terminated local string buffer
memcpy(vendorID, info->eax_0.vendorid, 12);
printf("\nCPU identification:\n");
printf("%12s '%s'\n", "Vendor ID:", vendorID);
switch (vendor_tag) {
case 'uneG': // "GenuineIntel"
Intel_identify(info);
break;
case 'htuA': // "AuthenticAMD"
AMD_identify(info);
break;
case 'iryC': // "CyrixInstead"
Cyrix_identify(info);
break;
}
}
void
opt_features(cpuid_info *info, int vendor_tag)
{
switch (vendor_tag) {
case 'uneG': // "GenuineIntel"
Intel_features(info);
break;
case 'htuA': // "AuthenticAMD"
AMD_features(info);
break;
case 'iryC': // "CyrixInstead"
Cyrix_features(info);
break;
}
}
void
opt_TLB_cache(cpuid_info *info, int vendor_tag)
{
switch (vendor_tag) {
case 'uneG': // "GenuineIntel"
Intel_TLB_cache(info);
break;
case 'htuA': // "AuthenticAMD"
AMD_TLB_cache(info);
break;
case 'iryC': // "CyrixInstead"
Cyrix_TLB_cache(info);
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Intel specs
void
Intel_identify(cpuid_info *info)
{
int type, family, model, sig;
get_cpuid(info, 1, 0);
type = info->eax_1.type;
family = info->eax_1.family;
model = info->eax_1.model;
sig = info->regs.eax;
printf("%12s 0x%08X\n", "Signature:", sig);
printf("%12s %2d '", "Type:", type);
if (type == 0) printf("Original OEM");
else if (type == 1) printf("Overdrive");
else if (type == 2) printf("Dual-capable");
else if (type == 3) printf("Reserved");
printf("'\n");
printf("%12s %2d '", "Family:", family);
if (family == 3) printf("i386");
else if (family == 4) printf("i486");
else if (family == 5) printf("Pentium");
else if (family == 6) printf("Pentium Pro");
else if (family == 15) printf("Pentium 4");
printf("'\n");
printf("%12s %2d '", "Model:", model);
switch (family) {
case 3:
break;
case 4:
if (model == 0) printf("DX");
else if (model == 1) printf("DX");
else if (model == 2) printf("SX");
else if (model == 3) printf("487/DX2");
else if (model == 4) printf("SL");
else if (model == 5) printf("SX2");
else if (model == 7) printf("write-back enhanced DX2");
else if (model == 8) printf("DX4");
break;
case 5:
if (model == 1) printf("60/66");
else if (model == 2) printf("75-200");
else if (model == 3) printf("for 486 system");
else if (model == 4) printf("MMX");
break;
case 6:
if (model == 1) printf("Pentium Pro");
else if (model == 3) printf("Pentium II Model 3");
else if (model == 5) printf("Pentium II Model 5/Xeon/Celeron");
else if (model == 6) printf("Celeron");
else if (model == 7) printf("Pentium III/Pentium III Xeon - external L2 cache");
else if (model == 8) printf("Pentium III/Pentium III Xeon - internal L2 cache");
break;
case 15:
break;
}
printf("'\n");
if (model == 15) {
int emodel = (info->regs.eax >> 16) & 0xf;
printf("Extended model: %d\n", emodel);
}
printf("%12s 0x%08lX\n", "Features:", info->eax_1.features);
{
int id = info->regs.ebx & 0xff;
printf("%12s %2d '%s'\n", "Brand ID:", id, Intel_brand_string(id, sig));
}
printf("%12s %2d\n", "Stepping:", info->eax_1.stepping);
printf("%12s %2d\n", "Reserved:", info->eax_1.reserved_0);
get_cpuid(info, 0x80000000, 0);
if (info->regs.eax & 0x80000000) {
// extended feature/signature bits supported
if (info->regs.eax >= 0x80000004) {
int i;
printf("\nExtended brand string:\n'");
for (i = 0x80000002; i <= 0x80000004; ++i) {
get_cpuid(info, i, 0);
print_regs(info);
}
printf("'\n");
}
}
}
const char *
Intel_brand_string(int id, int processor_signature)
{
int sig = processor_signature;
switch (id) {
case 0x0: return "Unsupported";
case 0x1: return "Intel(R) Celeron(R) processor";
case 0x2: return "Intel(R) Pentium(R) III processor";
case 0x3: return (sig == 0x6B1) ? "Intel(R) Celeron(R) processor" : "Intel(R) Pentium(R) III Xeon(TM) processor";
case 0x4: return "Intel(R) Pentium(R) III processor";
case 0x5: return "";
case 0x6: return "Mobile Intel(R) Pentium(R) III Processor-M";
case 0x7: return "Mobile Intel(R) Celeron(R) processor";
case 0x8: return (sig >= 0xF13) ? "Intel(R) Genuine processor" : "Intel(R) Pentium(R) 4 processor";
case 0x9: return "Intel(R) Pentium(R) 4 processor";
case 0xA: return "Intel(R) Celeron(R) processor";
case 0xB: return (sig < 0xF13) ? "Intel(R) Xeon(TM) processor MP" : "Intel(R) Xeon(TM) processor";
case 0xC: return "Intel(R) Xeon(TM) processor MP";
case 0xD: return "";
case 0xE: return (sig < 0xF13) ? "Intel(R) Xeon(TM) processor" : "Mobile Intel(R) Pentium(R) 4 Processor-M";
case 0xF: return "Mobile Intel(R) Celeron(R) processor";
default:
return "";
}
}
void
Intel_features(cpuid_info *info)
{
//
int i;
int fflags;
get_cpuid(info, 1, 0);
fflags = info->eax_1.features;
printf("\nSupported processor features:\n");
for (i = 0; i < 32; ++i)
if (fflags & (1<<i))
printf(" %s\n", Intel_feature_flags[i]);
printf("\n");
}
void
Intel_TLB_cache(cpuid_info *info)
{
//get_cpuid(info, 2, 0);
printf("\nnot just yet...\n");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// AMD specs
void
AMD_identify(cpuid_info *info)
{
printf("Sorry! Info about AMD cpu's not implemented yet :(\n");
}
void
AMD_features(cpuid_info *info)
{
printf("Sorry! Info about AMD cpu's not implemented yet :(\n");
}
void
AMD_TLB_cache(cpuid_info *info)
{
printf("Sorry! Info about AMD cpu's not implemented yet :(\n");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Cyrix specs
void
Cyrix_identify(cpuid_info *info)
{
printf("Sorry! Info about Cyrix cpu's not implemented yet :(\n");
}
void
Cyrix_features(cpuid_info *info)
{
printf("Sorry! Info about Cyrix cpu's not implemented yet :(\n");
}
void
Cyrix_TLB_cache(cpuid_info *info)
{
printf("Sorry! Info about Cyrix cpu's not implemented yet :(\n");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// dumps
void
opt_dump_calls(cpuid_info *info, uint32 max_level)
{
uint32 max_extended;
printf("CPUID instruction call dump:\n");
dump_regs(info, "Standard Calls", 0, max_level);
get_cpuid(info, 0x80000000, 0);
max_extended = info->regs.eax;
if (max_extended == 0)
printf("\nNo extended calls available for this CPU\n");
else
dump_regs(info, "Extended Calls", 0x80000000, max_extended);
}
void
dump_regs(cpuid_info *info, const char *heading, uint32 min_level, uint32 max_level)
{
uint32 i;
printf("\n%s (max eax level = %lx)\n", heading, max_level);
printf("----------------------------------------------\n");
printf(" Input | Output\n");
printf("----------------------------------------------\n");
printf(" eax | eax ebx ecx edx\n");
for (i = min_level; i <= max_level; ++i) {
get_cpuid(info, i, 0);
printf("%08lx | %08lx %08lx %08lx %08lx\n",
i,
info->regs.eax,
info->regs.ebx,
info->regs.ecx,
info->regs.edx);
}
}
void
print_regs(cpuid_info *info)
{
int i;
char s[17] = {0};
for (i = 0; i < 4; ++i)
s[i] = info->regs.eax >> (8*i),
s[i+4] = info->regs.ebx >> (8*i),
s[i+8] = info->regs.ecx >> (8*i),
s[i+12] = info->regs.edx >> (8*i);
printf("%s", s);
}