📄 cpu.c
字号:
/***************************************************************************
** File name : cpu.c
** Author :
** Create date :
**
** Comment:
** Intel & AMD CPU features...
**
** Revisions:
** $Log: cpu.c,v $
** Revision 1.2 2005/08/09 16:11:40 x.cheng
** new function for easy show cpu info added
**
** Revision 1.1 2005/08/05 15:04:04 x.cheng
** add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdlib.h"
#include "string.h"
#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\io.h"
#include "..\..\Inc\i386\cpu.h"
#include "..\..\inc\i386\bitops.h"
#include "..\..\Inc\tui.h"
#include "..\..\Inc\debug.h"
ts_CpuInfo g_stCpuInfo;
//! All the string names for Intel CPU models.
static ts_CpuName g_astIntelCpuNames[] =
{
{
.iFamily = 4, .aszModelNames =
{
[ 0 ] = "486 DX-25/33",
[ 1 ] = "486 DX-50",
[ 2 ] = "486 SX",
[ 3 ] = "486 DX/2",
[ 4 ] = "486 SL",
[ 5 ] = "486 SX/2",
[ 7 ] = "486 DX/2-WB",
[ 8 ] = "486 DX/4",
[ 9 ] = "486 DX/4-WB",
}
},
{
.iFamily = 5, .aszModelNames =
{
[ 0 ] = "Pentium 60/66 A-step",
[ 1 ] = "Pentium 60/66",
[ 2 ] = "Pentium 75-200",
[ 3 ] = "Overdrive PODP5V83",
[ 4 ] = "Pentium MMX",
[ 7 ] = "Mobile Pentium 75-200",
[ 8 ] = "Mobile Pentium MMX",
}
},
{
.iFamily = 6, .aszModelNames =
{
[ 0 ] = "Pentium Pro A-step",
[ 1 ] = "Pentium Pro",
[ 3 ] = "Pentium II (Klamath)",
[ 4 ] = "Pentium II (Deschutes)",
[ 5 ] = "Pentium II (Deschutes)",
[ 6 ] = "Mobile Pentium II",
[ 7 ] = "Pentium III (Katmai)",
[ 8 ] = "Pentium III (Coppermine)",
[ 10 ] = "Pentium III (Cascades)",
[ 11 ] = "Pentium III (Tualatin)",
}
},
{
.iFamily = 15, .aszModelNames =
{
[ 0 ] = "Pentium 4 (Unknown)",
[ 1 ] = "Pentium 4 (Willamette)",
[ 2 ] = "Pentium 4 (Northwood)",
[ 4 ] = "Pentium 4 (Foster)",
[ 5 ] = "Pentium 4 (Foster)",
}
},
};
//! All the string names for AMD CPU models.
static ts_CpuName g_astAmdCpuNames[] =
{
{
.iFamily = 4, .aszModelNames =
{
[ 3 ] = "486 DX/2",
[ 7 ] = "486 DX/2-WB",
[ 8 ] = "486 DX/4",
[ 9 ] = "486 DX/4-WB",
[ 14 ] = "Am5x86-WT",
[ 15 ] = "Am5x86-WB",
}
},
{
.iFamily = 5, .aszModelNames =
{
[ 0 ] = "K5/SSA5",
[ 1 ] = "K5",
[ 2 ] = "K5",
[ 3 ] = "K5",
[ 6 ] = "K6",
[ 7 ] = "K6",
[ 8 ] = "K6-2",
[ 9 ] = "K6-3",
}
},
{
.iFamily = 6, .aszModelNames =
{
[ 0 ] = "Athlon",
[ 1 ] = "Athlon",
[ 2 ] = "Athlon",
[ 4 ] = "Athlon",
}
},
};
//! Feature flags for Intel CPUs (edx register).
static char *g_aszIntelFlagsEdx[] =
{
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse36", "pn", "clflush", NULL, "ds", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss", "htt", "tm", "ia64", "sbf",
};
//! Feature flags for Intel CPUs (exc register).
static char *g_aszIntelFlagsEcx[] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "tm2",
"est", NULL, "cid", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
//! Feature flags for AMD CPUs.
static char *g_aszAmdFlags[] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, "mmxext", NULL,
NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
};
//! Cache TLB informations
static ts_CacheInfo g_astCacheString[] =
{
{ 0x00, "Unknow cache type"},
{ 0x01, "Instruction TLB: 4KB Pages 4-way set associative, 32 entries" },
{ 0x02, "Instruction TLB: 4MB Pages, 4-way set associative, 2 entries" },
{ 0x03, "Data TLB: 4KB Pages, 4-way set associative, 64 entries" },
{ 0x04, "Data TLB: 4MB Pages, 4-way set associative, 8 entries" },
{ 0x06, "1st-level instruction cache: 8KB, 4-way set associative, 32 byte line size" },
{ 0x08, "1st-level instruction cache: 16KB, 4-way set associative, 32 byte line size" },
{ 0x0A, "1st-level data cache: 8KB, 2-way set associative, 32 byte line size" },
{ 0x0C, "1st-level data cache: 16KB, 4-way set associative, 32 byte line size" },
{ 0x22, "3rd-level cache: 512KB, 4-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x23, "3rd-level cache: 1MB, 8-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x40, "No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache" },
{ 0x41, "2nd-level cache: 128KB, 4-way set associative, 32 byte line size" },
{ 0x42, "2nd-level cache: 256KB, 4-way set associative, 32 byte line size" },
{ 0x43, "2nd-level cache: 512KB, 4-way set associative, 32 byte line size" },
{ 0x44, "2nd-level cache: 1MB, 4-way set associative, 32 byte line size" },
{ 0x45, "2nd-level cache: 2MB, 4-way set associative, 32 byte line size" },
{ 0x50, "Instruction TLB: 4KB and 2MB or 4MB pages, 64 entries" },
{ 0x51, "Instruction TLB: 4KB and 2MB or 4MB pages, 128 entries" },
{ 0x52, "Instruction TLB: 4KB and 2MB or 4MB pages, 256 entries" },
{ 0x5B, "Data TLB: 4KB and 4MB pages, 64 entries" },
{ 0x5C, "Data TLB: 4KB and 4MB pages, 128 entries" },
{ 0x5D, "Data TLB: 4KB and 4MB pages, 256 entries" },
{ 0x66, "1st-level data cache: 8KB, 4-way set associative, 64 byte line size" },
{ 0x67, "1st-level data cache: 16KB, 4-way set associative, 64 byte line size" },
{ 0x68, "1st-level data cache: 32KB, 4-way set associative, 64 byte line size" },
{ 0x70, "Trace cache: 12K-op, 8-way set associative" },
{ 0x71, "Trace cache: 16K-op, 8-way set associative" },
{ 0x72, "Trace cache: 32K-op, 8-way set associative" },
{ 0x79, "2nd-level cache: 128KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x7A, "2nd-level cache: 256KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x7B, "2nd-level cache: 512KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x7C, "2nd-level cache: 1MB, 8-way set associative, dual-sectored line, 64 byte sector size" },
{ 0x82, "2nd-level cache: 256KB, 8-way set associative, 32 byte line size" },
{ 0x83, "2nd-level cache: 512KB, 8-way set associative, 32 byte line size" },
{ 0x84, "2nd-level cache: 1MB, 8-way set associative, 32 byte line size" },
{ 0x85, "2nd-level cache: 2MB, 8-way set associative, 32 byte line size" },
};
/*******************local function prototype***************/
static inline int iCpuCpuidIsAvailable();
static inline int iCpuIs486();
static void CpuEvaluateFrequency( ts_CpuInfo* pstCpuInfo );
static int iCpuGetModelName( ts_CpuInfo* pstCpuInfo);
static int iCpuGetBandString( ts_CpuInfo* pstCpuInfo );
static void CpuShowBriefInfo();
static void CpuDumpCacheInfo ();
int iCpuGetInfo( ts_CpuInfo* pstCpuInfo );
/************************************************************
*************************************************************
** Function Name: CpuInitialize
** Author: x.cheng
**
** Comment:
** Initialize the main CPU.
**
** List of parameters:
** no
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
void CpuInitialize( void )
{
iCpuGetInfo( &g_stCpuInfo );
#ifdef _DEBUG__
kprintf("\nCPU: Detected '%s' %u.%u MHz processor.\n"
"CPU: %s (%d %d %d)\n",
g_stCpuInfo.unVendor.szString,
g_stCpuInfo.ulFrequency/1000, g_stCpuInfo.ulFrequency%1000,
g_stCpuInfo.szName,
g_stCpuInfo.unSignature.stFlags.family,
g_stCpuInfo.unSignature.stFlags.model,
g_stCpuInfo.unSignature.stFlags.stepping );
#endif
if (g_stCpuInfo.unFeature.stFlags.stEdx.fxsr)
{
// Set bit 9 of CR4 (the OXFSXR). Setting this bit assumes that the
// operating system provides facility for saving and restoring the
// SSE state, using the "fxsave" and "fxrstor" instructions.
// This is also needed to use SSE or SSE2 processor extensions.
unsigned int __cr4;
__asm__ __volatile__ (
"movl %%cr4, %0\n"
"or $512, %0\n"
"movl %0, %%cr4" : "=r"(__cr4));
}
}
/************************************************************
*************************************************************
** Function Name: CpuShowInfo
** Author: x.cheng
**
** Comment:
** Dump all the CPU informations to standard output.
**
** List of parameters:
** no
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
void CpuShowInfo()
{
CpuShowBriefInfo();
kprintf( "Feature Flags : \n " );
if( strcmp(g_stCpuInfo.unVendor.szString, "GenuineIntel")==0 )
{
// Intel cpu.
int i;
// Test each bit of the feature flags.
for( i=0; i<32; i++ )
if( iTestBit(i, &g_stCpuInfo.unFeature.stFlags.stEdx) )
kprintf( "%s ", g_aszIntelFlagsEdx[i] );
for( i=0; i<32; i++ )
if( iTestBit(i, &g_stCpuInfo.unFeature.stFlags.stEcx) )
kprintf( "%s ", g_aszIntelFlagsEcx[i] );
}
else if( strcmp(g_stCpuInfo.unVendor.szString, "GenuineIntel")==0 )
{
// AMD cpu.
int i;
// Test each bit of the feature flags.
for( i=0; i<32; i++ )
if( iTestBit(i, &g_stCpuInfo.unFeature.stFlags.stEdx) )
kprintf( "%s ", g_aszAmdFlags[i] );
}
// Print the BogoMIPS evaluation.
kprintf( "\n" );
// Dump internal cache informations.
kprintf( "Cache informations : \n" );
CpuDumpCacheInfo();
}
//----------------------------------------------------------------------------------
//==============================local function======================================
//----------------------------------------------------------------------------------
/************************************************************
*************************************************************
** Function Name: CpuGetInfo
** Author: x.cheng
**
** Comment:
** Get the CPU informations and fill the
** ts_CpuInfo * structure.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
int iCpuGetInfo( ts_CpuInfo* pstCpuInfo )
{
unsigned long ulDummy;
//reset the structure.
memset( pstCpuInfo, 0, sizeof(pstCpuInfo) );
//Check if 'cpuid' instruction is available.
if ( !iCpuCpuidIsAvailable() ) {
if ( !iCpuIs486() ) {
//80386 detected.
pstCpuInfo->unSignature.stFlags.family = 3;
} else {
//80486 detected.
pstCpuInfo->unSignature.stFlags.family = 4;
}
} else {
// Execute the 'cpuid' instruction command #0.
CPUID( GET_CPU_VENDOR,
&ulDummy, &pstCpuInfo->unVendor.aulNum[0],
&pstCpuInfo->unVendor.aulNum[2], &pstCpuInfo->unVendor.aulNum[1] );
// Execute the 'cpuid' instruction command #1.
CPUID( GET_CPU_INFO,
&pstCpuInfo->unSignature.ulNum, &pstCpuInfo->unBrand.ulNum,
&pstCpuInfo->unFeature.aulNum[0], &pstCpuInfo->unFeature.aulNum[1] );
// Evaluate the frequency if it is possible.
CpuEvaluateFrequency( pstCpuInfo );
}
// Get the model name.
iCpuGetModelName( pstCpuInfo );
// Well done.
return( 0 );
}
/************************************************************
*************************************************************
** Function Name: iCpuCpuidIsAvailable
** Author: x.cheng
**
** Comment:
** Check if the 'cpuid' instruction is available.
** This is true if the cpuid detection flag in
** EFLAGS register is changeable.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static inline int iCpuCpuidIsAvailable()
{
int iFlag1, iFlag2;
__asm__ __volatile__ (
"pushfl\n"
"pushfl\n"
"popl %0\n"
"movl %0, %1\n"
"xorl %2, %0\n"
"pushl %0\n"
"popfl\n"
"pushfl\n"
"popl %0\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -