⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
**     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 + -