📄 cpu.c
字号:
"popfl\n"
: "=r"(iFlag1), "=r"(iFlag2) : "i"(EFLAGS_ID)
);
return( (iFlag1^iFlag2) & EFLAGS_ID );
}
/************************************************************
*************************************************************
** Function Name: iCpuIs486
** Author: x.cheng
**
** Comment:
** Check if the processor is a 486 or higher.
** This is true if the alignement check bit in
** EFLAGS register is changeable.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static inline int iCpuIs486()
{
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"
"popfl\n"
: "=r"(iFlag1), "=r"(iFlag2) : "i"(EFLAGS_AC)
);
return( (iFlag1^iFlag2) & EFLAGS_AC );
}
/************************************************************
*************************************************************
** Function Name: CpuEvaluateFrequency
** Author: x.cheng
**
** Comment:
** Evaluate and return the CPU frequency in kHz.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
void CpuEvaluateFrequency( ts_CpuInfo* pstCpuInfo )
{
unsigned long long ullTimeStamp1, ullTimeStamp2; // 64 bit...
unsigned long ulFlags;
if( !pstCpuInfo->unFeature.stFlags.stEdx.tsc ) {
// CPU doesn't support Time Stamp Counter!
// Cannot evaluate the frequency.
pstCpuInfo->ulFrequency = 0;
return;
}
SaveEflagsAndCli( ulFlags );
// Wait until the second has precisely just started.
// (void)sys_time( NULL );
// Read the value of the current time-stamp counter (64-bit).
RDTSCLL( ullTimeStamp1 );
// Wait exactly one second.
// (void)sys_time( NULL );
// Read the value of the current time-stamp counter again.
RDTSCLL( ullTimeStamp2 );
// Now we can estimate the CPU frequency as follows.
pstCpuInfo->ulFrequency = ( (unsigned long)(ullTimeStamp2 - ullTimeStamp1)/1000);
RestoreEflags( ulFlags );
}
/************************************************************
*************************************************************
** Function Name: iCpuGetModelName
** Author: x.cheng
**
** Comment:
** Get the cpu model name.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static int iCpuGetModelName( ts_CpuInfo* pstCpuInfo)
{
ts_CpuName* pstNames;
int iCnt, i;
// First of all try to get the brand string.
if( iCpuGetBandString(pstCpuInfo)==0 )
{
// Well done, brand string supported.
return( 0 );
}
// Find the vendor of the CPU.
if( strcmp(pstCpuInfo->unVendor.szString, "GenuineIntel")==0 ) {
// Intel CPU name.
// Try to identify the cpu name with the brand ID.
// This is useful to identify Celeron and Xeon
// processor.
switch( pstCpuInfo->unBrand.ulId )
{
case 1:
case 10:
strncpy( pstCpuInfo->szName,
"Intel(R) Celeron(R)",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 3:
if( pstCpuInfo->unSignature.ulNum==0x6b1 )
strncpy( pstCpuInfo->szName,
"Intel(R) Celeron(R)",
sizeof(pstCpuInfo->szName) );
else
strncpy( pstCpuInfo->szName,
"Intel(R) Pentium(R) Xeon",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 6:
strncpy( pstCpuInfo->szName,
"Mobile Intel(R) Pentium(R) III",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 7:
case 15:
strncpy( pstCpuInfo->szName,
"Mobile Intel(R) Celeron(R)",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 11:
if( pstCpuInfo->unSignature.ulNum<0xf13 )
strncpy( pstCpuInfo->szName,
"Intel(R) Xeon MP",
sizeof(pstCpuInfo->szName) );
else
strncpy( pstCpuInfo->szName,
"Intel(R) Xeon",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 12:
strncpy( pstCpuInfo->szName,
"Intel(R) Xeon MP",
sizeof(pstCpuInfo->szName) );
return( 0 );
break;
case 13:
if( pstCpuInfo->unSignature.ulNum<0xf13 )
strncpy( pstCpuInfo->szName,
"Intel(R) Xeon",
sizeof(pstCpuInfo->szName) );
else
strncpy( pstCpuInfo->szName,
"Mobile Intel(R) Pentium 4",
sizeof(pstCpuInfo->szName) );
break;
}
// Find the cpu name in the intel list.
pstNames = g_astIntelCpuNames;
iCnt = CountOfArray( g_astIntelCpuNames );
}
else if( strcmp(pstCpuInfo->unVendor.szString, "AuthenticAMD")==0 )
{
// AMD CPU name.
// Find the cpu name in the amd list.
pstNames = g_astAmdCpuNames;
iCnt = CountOfArray( g_astAmdCpuNames );
}
else
{
// Copy the unknown string to the cpu name and vendor string.
strncpy( pstCpuInfo->unVendor.szString, "Unknown", sizeof(pstCpuInfo->unVendor.szString) );
switch( pstCpuInfo->unSignature.stFlags.family )
{
case 3:
strncpy( pstCpuInfo->szName, "386", sizeof(pstCpuInfo->szName) );
break;
case 4:
strncpy( pstCpuInfo->szName, "486", sizeof(pstCpuInfo->szName) );
break;
default:
strncpy( pstCpuInfo->szName, "Unknown", sizeof(pstCpuInfo->szName) );
break;
}
return( -1 );
}
// Get the right CPU model name.
for( i=0; i<iCnt; i++ )
{
if( pstCpuInfo->unSignature.stFlags.family==pstNames[i].iFamily )
{
int id = pstCpuInfo->unSignature.stFlags.model;
// Copy the cpu name.
strncpy( pstCpuInfo->szName,
pstNames[i].aszModelNames[ id ],
sizeof(pstCpuInfo->szName) );
}
}
return( 0 );
}
/************************************************************
*************************************************************
** Function Name: iCpuGetBandString
** Author: x.cheng
**
** Comment:
** Get the cpu brand string if it is available.
**
** List of parameters:
** pstCpuInfo -
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static int iCpuGetBandString( ts_CpuInfo* pstCpuInfo )
{
unsigned long* pulName = (unsigned long*)pstCpuInfo->szName;
char *p, *q;
unsigned long ulDummy, ulEax;
// Check if brand string is available.
CPUID( CPU_BRAND_STRING_IS_AVAILABLE,
&ulEax, &ulDummy, &ulDummy, &ulDummy );
if( ulEax<0x80000004 ) {
// Brand string not supported! Zero the cpu name.
memset( pstCpuInfo->szName, 0, sizeof(pstCpuInfo->szName) );
return( -1 );
}
// Get the cpu brand string.
CPUID( CPU_GET_BRAND_STRING1, &pulName[0], &pulName[1], &pulName[2], &pulName[3] );
CPUID( CPU_GET_BRAND_STRING2, &pulName[4], &pulName[5], &pulName[6], &pulName[7] );
CPUID( CPU_GET_BRAND_STRING3, &pulName[8], &pulName[9], &pulName[10], &pulName[11] );
pstCpuInfo->szName[48] = '\0';
// Intel chips right justify the string.
// Left justify this string.
p = q = &pstCpuInfo->szName[0];
while ( *p == ' ' )
p++;
if ( p != q )
{
while ( *p )
*q++ = *p++;
// Zero pad the rest.
while ( q <= &pstCpuInfo->szName[48] )
*q++ = '\0';
}
// Well done.
return( 0 );
}
/************************************************************
*************************************************************
** Function Name: CpuShowBriefInfo
** Author: x.cheng
**
** Comment:
** Show a brief description of the cpu.
**
** List of parameters:
** no
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static void CpuShowBriefInfo()
{
kprintf( "Vender ID : %s\n", g_stCpuInfo.unVendor.szString );
kprintf( "Name : %s\n", g_stCpuInfo.szName );
if ( g_stCpuInfo.ulFrequency ) {
kprintf( "Frequency : %u.%u MHz\n",
g_stCpuInfo.ulFrequency/1000, g_stCpuInfo.ulFrequency%1000 );
} else {
kprintf( "Frequency : ???? MHz\n" );
}
kprintf( "Family : %u\n"
"Model : %u\n"
"Stepping ID : %u\n"
"Extended Family : %u\n"
"Extended Model : %u\n",
g_stCpuInfo.unSignature.stFlags.family,
g_stCpuInfo.unSignature.stFlags.model,
g_stCpuInfo.unSignature.stFlags.stepping,
g_stCpuInfo.unSignature.stFlags.ext_family,
g_stCpuInfo.unSignature.stFlags.ext_model );
}
/************************************************************
*************************************************************
** Function Name: CpuDumpCacheInfo
** Author: x.cheng
**
** Comment:
** Dump CPU internal cache informations.
**
** List of parameters:
** no
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
static void CpuDumpCacheInfo ()
{
unsigned long aulCacheInfo[4];
char* szDescription;
unsigned long ulDummy;
int i, j, n;
// Get the number of times to iterate (lower 8-bits).
CPUID( GET_CPU_CACHE, (unsigned long*)&n, &ulDummy, &ulDummy, &ulDummy );
n &= 0xff;
for( i=0; i<n; i++ )
{
CPUID( GET_CPU_CACHE,
&aulCacheInfo[0], &aulCacheInfo[1],
&aulCacheInfo[2], &aulCacheInfo[3] );
}
// If bit 31 is set this is an unknown format.
for( i=0; i<3; i++ )
if ( (aulCacheInfo[i] & 0x80000000) )
aulCacheInfo[i] = 0;
// Look up in the cache strings table.
szDescription = (char *)aulCacheInfo;
//HexDump(szDescription, 16);
// Byte 0 is the level count, not a descriptor.
for( i=1; i<4*sizeof(unsigned long); i++ )
{
if ( szDescription[i] )
{
for( j = 0; j < CountOfArray(g_astCacheString); j++ )
{
if ( szDescription[i]==g_astCacheString[j].ucIndex )
{
kprintf( "%s\n", g_astCacheString[j].szString );
break;
}
}
}
}
kprintf("\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -