PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/source/cpuid.cpp

https://github.com/prophile/crisscross
C++ | 1036 lines | 810 code | 142 blank | 84 comment | 78 complexity | d8fba97ad7a100a9c035055bd0d99b6a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * CrissCross
  3. * A multi-purpose cross-platform library.
  4. *
  5. * A product of Uplink Laboratories.
  6. *
  7. * (c) 2006-2009 Steven Noonan.
  8. * Licensed under the New BSD License.
  9. *
  10. */
  11. /*
  12. * Last updated 1/9/2008
  13. * using Intel CPUID documentation (AP-485) updated 12/2007
  14. */
  15. #include <crisscross/universal_include.h>
  16. #ifdef ENABLE_CPUID
  17. #ifdef TARGET_OS_MACOSX
  18. extern "C" {
  19. int chudProcessorCount();
  20. int utilBindThreadToCPU(int n);
  21. int utilUnbindThreadFromCPU();
  22. }
  23. #endif
  24. /* The following definition enables some rather suspicious cache descriptors */
  25. /* from sandpile.org which haven't been verified with Intel's docs. */
  26. /* # define ENABLE_SANDPILE */
  27. #include <crisscross/cpuid.h>
  28. #include <crisscross/core_io.h>
  29. namespace CrissCross
  30. {
  31. namespace System
  32. {
  33. #define FPU_FLAG 0x0001
  34. #define LAHF_FLAG 0x0001
  35. #define SSE3_FLAG 0x0001
  36. #define VME_FLAG 0x0002
  37. #define DE_FLAG 0x0004
  38. #define DTES64_FLAG 0x0004
  39. #define MONITOR_FLAG 0x0008
  40. #define PSE_FLAG 0x0008
  41. #define DS_CPL_FLAG 0x0010
  42. #define TSC_FLAG 0x0010
  43. #define MSR_FLAG 0x0020
  44. #define VMX_FLAG 0x0020
  45. #define PAE_FLAG 0x0040
  46. #define SMX_FLAG 0x0040
  47. #define EIST_FLAG 0x0080
  48. #define MCE_FLAG 0x0080
  49. #define CX8_FLAG 0x0100
  50. #define TM2_FLAG 0x0100
  51. #define APIC_FLAG 0x0200
  52. #define SSSE3_FLAG 0x0200
  53. #define CNXTID_FLAG 0x0400
  54. #define SEP_FLAG 0x0800
  55. #define SYSCALL_FLAG 0x0800
  56. #define MTRR_FLAG 0x1000
  57. #define CX16_FLAG 0x2000
  58. #define PGE_FLAG 0x2000
  59. #define MCA_FLAG 0x4000
  60. #define XTPR_FLAG 0x4000
  61. #define PDCM_FLAG 0x8000
  62. #define CMOV_FLAG 0x8000
  63. #define PAT_FLAG 0x10000
  64. #define PSE36_FLAG 0x20000
  65. #define DCA_FLAG 0x40000
  66. #define PSNUM_FLAG 0x40000
  67. #define CLFLUSH_FLAG 0x80000
  68. #define SSE4_1_FLAG 0x80000
  69. #define SSE4_2_FLAG 0x100000
  70. #define XD_FLAG 0x100000
  71. #define DTS_FLAG 0x200000
  72. #define ACPI_FLAG 0x400000
  73. #define MMX_FLAG 0x800000
  74. #define FXSR_FLAG 0x1000000
  75. #define SSE_FLAG 0x2000000
  76. #define SSE2_FLAG 0x4000000
  77. #define SS_FLAG 0x8000000
  78. #define HTT_FLAG 0x10000000
  79. #define EM64T_FLAG 0x20000000
  80. #define TM1_FLAG 0x20000000
  81. #define IA64_FLAG 0x40000000
  82. #define PBE_FLAG 0x80000000
  83. /* AMD 8000_0001 EDX flags */
  84. #define _3DNOW_FLAG 0x80000000
  85. #define _3DNOWEXT_FLAG 0x40000000
  86. #define LM_FLAG 0x20000000
  87. #define RDTSCP_FLAG 0x8000000
  88. #define FFXSR_FLAG 0x2000000
  89. #define FXSR_FLAG 0x1000000
  90. #define MMXEXT_FLAG 0x800000
  91. #define NX_FLAG 0x100000
  92. /* AMD 8000_0001 ECX flags */
  93. #define WDT_FLAG 0x2000
  94. #define SKINIT_FLAG 0x1000
  95. #define OSVW_FLAG 0x200
  96. #define _3DNP_FLAG 0x100
  97. #define MAS_FLAG 0x80
  98. #define SSE4A_FLAG 0x40
  99. #define ABM_FLAG 0x20
  100. #define AMC8_FLAG 0x10
  101. #define EAS_FLAG 0x8
  102. #define SVM_FLAG 0x4
  103. #define CL_FLAG 0x2
  104. #define LS_FLAG 0x1
  105. struct Registers
  106. {
  107. unsigned int eax;
  108. unsigned int ebx;
  109. unsigned int ecx;
  110. unsigned int edx;
  111. };
  112. struct Registers *Std;
  113. unsigned int StdMax;
  114. struct Registers *Ext;
  115. unsigned int ExtMax;
  116. /* If the current processor supports the CPUID instruction, execute
  117. * one, with REQUEST in %eax, and set *EAX, *EBX, *ECX, and *EDX to
  118. * the values the 'cpuid' stored in those registers. Return true if
  119. * the current processor supports CPUID, false otherwise. */
  120. namespace
  121. {
  122. bool call_cpuid(unsigned int request, unsigned int *_eax, unsigned int *_ebx, unsigned int *_ecx, unsigned int *_edx)
  123. {
  124. #ifndef TARGET_CPU_X64
  125. unsigned int pre_change, post_change;
  126. const unsigned int id_flag = 0x200000;
  127. #endif
  128. /* This is pretty much the standard way to detect whether the CPUID
  129. * instruction is supported: try to change the ID bit in the EFLAGS
  130. * register. If we can change it, then the CPUID instruction is
  131. * implemented. */
  132. #ifndef TARGET_CPU_X64
  133. #if defined (TARGET_COMPILER_GCC)
  134. asm ("pushfl\n\t" /* Save %eflags to restore later. */
  135. "pushfl\n\t" /* Push second copy, for manipulation. */
  136. "popl %1\n\t" /* Pop it into post_change. */
  137. "movl %1,%0\n\t" /* Save copy in pre_change. */
  138. "xorl %2,%1\n\t" /* Tweak bit in post_change. */
  139. "pushl %1\n\t" /* Push tweaked copy... */
  140. "popfl\n\t" /* ... and pop it into %eflags. */
  141. "pushfl\n\t" /* Did it change? Push new %eflags... */
  142. "popl %1\n\t" /* ... and pop it into post_change. */
  143. "popfl" /* Restore original value. */
  144. : "=&r" (pre_change), "=&r" (post_change)
  145. : "ir" (id_flag));
  146. #else
  147. __asm {
  148. mov edx, id_flag;
  149. pushfd; /* Save %eflags to restore later. */
  150. pushfd; /* Push second copy, for manipulation. */
  151. pop ebx; /* Pop it into post_change. */
  152. mov eax, ebx; /* Save copy in pre_change. */
  153. xor ebx, edx; /* Tweak bit in post_change. */
  154. push ebx; /* Push tweaked copy... */
  155. popfd; /* ... and pop it into eflags. */
  156. pushfd; /* Did it change? Push new %eflags... */
  157. pop ebx; /* ... and pop it into post_change. */
  158. popfd; /* Restore original value. */
  159. mov pre_change, eax;
  160. mov post_change, ebx;
  161. }
  162. #endif
  163. #endif
  164. /* If the bit changed, then we support the CPUID instruction. */
  165. #ifndef TARGET_CPU_X64
  166. if ((pre_change ^ post_change) & id_flag) {
  167. #endif
  168. #if defined (TARGET_COMPILER_GCC)
  169. asm volatile ("mov %%ebx, %%esi\n\t" /* Save %ebx. */
  170. "xorl %%ecx, %%ecx\n\t"
  171. "cpuid\n\t"
  172. "xchgl %%ebx, %%esi" /* Restore %ebx. */
  173. : "=a" (*_eax), "=S" (*_ebx), "=c" (*_ecx), "=d" (*_edx)
  174. : "0" (request)
  175. : "memory");
  176. #else
  177. __asm {
  178. push esi;
  179. push edi;
  180. xor ecx, ecx;
  181. mov eax, request;
  182. cpuid;
  183. mov edi, [_eax];
  184. mov esi, [_ebx];
  185. mov[edi], eax;
  186. mov[esi], ebx;
  187. mov edi, [_ecx];
  188. mov esi, [_edx];
  189. mov[edi], ecx;
  190. mov[esi], edx;
  191. pop edi;
  192. pop esi;
  193. }
  194. #endif
  195. return true;
  196. #ifndef TARGET_CPU_X64
  197. } else
  198. return false;
  199. #endif
  200. }
  201. }
  202. CPUID::CPUID()
  203. {
  204. unsigned int i = 0;
  205. for (i = 0; i < MAX_PROCESSORS; i++) {
  206. proc[i] = new Processor();
  207. CoreAssert(proc[i]);
  208. proc[i]->Manufacturer = NULL;
  209. proc[i]->ProcessorName = NULL;
  210. }
  211. Std = new Registers[32];
  212. Ext = new Registers[32];
  213. memset(Std, 0, sizeof(Registers) * 32);
  214. memset(Ext, 0, sizeof(Registers) * 32);
  215. StdMax = 0;
  216. ExtMax = 0;
  217. /* Basic initializations complete */
  218. call_cpuid(0, &Std[0].eax, &Std[0].ebx, &Std[0].ecx, &Std[0].edx);
  219. StdMax = Std[0].eax;
  220. if (StdMax > 31) {
  221. #ifdef CPUID_DEBUG
  222. g_console->WriteLine("CPUID.0.EAX has an invalid value: %d",
  223. StdMax);
  224. #endif
  225. StdMax = 31;
  226. } else {
  227. #ifdef CPUID_DEBUG
  228. g_console->WriteLine("Standard CPUID maximum input is %d.",
  229. StdMax);
  230. #endif
  231. }
  232. for (i = 1; i <= StdMax; i++) {
  233. call_cpuid(i, &Std[i].eax, &Std[i].ebx, &Std[i].ecx, &Std[i].edx);
  234. }
  235. call_cpuid(0x80000000, &Ext[0].eax, &Ext[0].ebx, &Ext[0].ecx, &Ext[0].edx);
  236. if (Ext[0].eax < 0x80000004) {
  237. return;
  238. } else {
  239. ExtMax = Ext[0].eax - 0x80000000;
  240. }
  241. for (i = 0; i <= ExtMax; i++) {
  242. call_cpuid(0x80000000 + i, &Ext[i].eax, &Ext[i].ebx, &Ext[i].ecx, &Ext[i].edx);
  243. }
  244. }
  245. CPUID::~CPUID()
  246. {
  247. /* Time to deallocate all the memory we allocated. */
  248. size_t i = 0, j = 0;
  249. delete [] Std;
  250. delete [] Ext;
  251. for (i = 0; i < MAX_PROCESSORS; i++) {
  252. for (j = 0; j < proc[i]->caches.size(); j++) {
  253. if (proc[i]->caches.valid(j))
  254. delete [] proc[i]->caches.get(j);
  255. }
  256. delete [] (char *)proc[i]->Manufacturer;
  257. delete [] (char *)proc[i]->ProcessorName;
  258. delete proc[i];
  259. }
  260. }
  261. int CPUID::VirtualCount()
  262. {
  263. CoreAssert(this != NULL);
  264. int count = 0, i;
  265. for (i = 0; i < MAX_PROCESSORS; i++) {
  266. if (proc[i]->Manufacturer)
  267. count++;
  268. }
  269. return count;
  270. }
  271. int CPUID::CoresPerPackage()
  272. {
  273. CoreAssert(this != NULL);
  274. return proc[0]->CoresPerPackage;
  275. }
  276. int CPUID::LogicalPerPackage()
  277. {
  278. CoreAssert(this != NULL);
  279. return proc[0]->LogicalPerPackage;
  280. }
  281. #ifdef TARGET_OS_WINDOWS
  282. DWORD WINAPI CPUID::GoThread(LPVOID * params)
  283. #else
  284. long int CPUID::GoThread(int processor)
  285. #endif
  286. {
  287. CoreAssert(this != NULL);
  288. #ifdef TARGET_OS_WINDOWS
  289. int processor;
  290. memcpy(&processor, params, sizeof(int));
  291. #endif
  292. if (processor < 0 || processor > MAX_PROCESSORS) {
  293. return 1;
  294. }
  295. DetectManufacturer(processor);
  296. DetectProcessorName(processor);
  297. DetectFeatures(processor);
  298. DetectCacheInfo(processor);
  299. DetectFMS(processor);
  300. DetectBrandID(processor);
  301. DetectCount(processor);
  302. DetectAPIC(processor);
  303. return 0;
  304. }
  305. void CPUID::Go()
  306. {
  307. CoreAssert(this != NULL);
  308. #ifdef TARGET_OS_WINDOWS
  309. DWORD dThread = NULL;
  310. SYSTEM_INFO siSystem;
  311. int iCount = 0;
  312. struct GoThreadProc_Params params;
  313. params.cpuid_class = this;
  314. GetSystemInfo(&siSystem);
  315. iCount = siSystem.dwNumberOfProcessors;
  316. if (iCount > MAX_PROCESSORS) {
  317. iCount = MAX_PROCESSORS;
  318. }
  319. for (params.processor = 0; params.processor < iCount;
  320. params.processor++) {
  321. HANDLE hThread =
  322. CreateThread(NULL, 0, ( LPTHREAD_START_ROUTINE )s_GoThreadProc,
  323. &params, CREATE_SUSPENDED, &dThread);
  324. SetThreadAffinityMask(hThread,
  325. ( DWORD )pow(( double )2,
  326. ( double )params.
  327. processor));
  328. Sleep(0); /* Wait for affinity switch. */
  329. SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
  330. ResumeThread(hThread);
  331. WaitForSingleObject(hThread, INFINITE);
  332. }
  333. #elif defined (TARGET_OS_LINUX)
  334. int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF), i;
  335. cpu_set_t mask;
  336. cpu_set_t originalmask;
  337. sched_getaffinity(0, sizeof(originalmask), &originalmask);
  338. for (i = 0; i < NUM_PROCS; i++) {
  339. CPU_ZERO(&mask);
  340. CPU_SET(( int )pow(2, i), &mask);
  341. sched_setaffinity(0, sizeof(mask), &mask);
  342. GoThread(i);
  343. }
  344. sched_setaffinity(0, sizeof(originalmask), &originalmask);
  345. #elif defined (TARGET_OS_MACOSX)
  346. int NUM_PROCS = chudProcessorCount();
  347. for (int i = 0; i < NUM_PROCS; i++) {
  348. utilUnbindThreadFromCPU();
  349. utilBindThreadToCPU(i);
  350. GoThread(i);
  351. }
  352. utilUnbindThreadFromCPU();
  353. #endif
  354. }
  355. void CPUID::DetectManufacturer(int processor)
  356. {
  357. CoreAssert(this != NULL);
  358. char *manufacturer = new char[(4 * 3) + 1];
  359. char *_man = &manufacturer[0];
  360. memcpy(_man, &Std[0].ebx, 4);
  361. _man += 4;
  362. memcpy(_man, &Std[0].edx, 4);
  363. _man += 4;
  364. memcpy(_man, &Std[0].ecx, 4);
  365. _man += 4;
  366. *_man = '\x0';
  367. proc[processor]->Manufacturer = manufacturer;
  368. }
  369. void CPUID::DetectProcessorName(int processor)
  370. {
  371. CoreAssert(this != NULL);
  372. char *processorname = new char[(4 * 12) + 1];
  373. char *_proc = &processorname[0];
  374. memcpy(_proc, &Ext[2].eax, 4);
  375. _proc += 4;
  376. memcpy(_proc, &Ext[2].ebx, 4);
  377. _proc += 4;
  378. memcpy(_proc, &Ext[2].ecx, 4);
  379. _proc += 4;
  380. memcpy(_proc, &Ext[2].edx, 4);
  381. _proc += 4;
  382. memcpy(_proc, &Ext[3].eax, 4);
  383. _proc += 4;
  384. memcpy(_proc, &Ext[3].ebx, 4);
  385. _proc += 4;
  386. memcpy(_proc, &Ext[3].ecx, 4);
  387. _proc += 4;
  388. memcpy(_proc, &Ext[3].edx, 4);
  389. _proc += 4;
  390. memcpy(_proc, &Ext[4].eax, 4);
  391. _proc += 4;
  392. memcpy(_proc, &Ext[4].ebx, 4);
  393. _proc += 4;
  394. memcpy(_proc, &Ext[4].ecx, 4);
  395. _proc += 4;
  396. memcpy(_proc, &Ext[4].edx, 4);
  397. _proc += 4;
  398. *_proc = '\x0';
  399. proc[processor]->ProcessorName = processorname;
  400. }
  401. void CPUID::DetectCacheInfo(int processor)
  402. {
  403. CoreAssert(this != NULL);
  404. if (proc[processor]->Manufacturer) {
  405. if (strcmp(proc[processor]->Manufacturer, "GenuineIntel") == 0) {
  406. int ntlb = 255, i;
  407. for (i = 0; i < ntlb; i++) {
  408. ntlb = Std[2].eax & 0xff;
  409. AddIntelCacheData(processor, Std[2].eax >> 8);
  410. AddIntelCacheData(processor, Std[2].eax >> 16);
  411. AddIntelCacheData(processor, Std[2].eax >> 24);
  412. if ((Std[2].ebx & 0x80000000) == 0) {
  413. AddIntelCacheData(processor, Std[2].ebx);
  414. AddIntelCacheData(processor, Std[2].ebx >> 8);
  415. AddIntelCacheData(processor, Std[2].ebx >> 16);
  416. AddIntelCacheData(processor, Std[2].ebx >> 24);
  417. }
  418. if ((Std[2].ecx & 0x80000000) == 0) {
  419. AddIntelCacheData(processor, Std[2].ecx);
  420. AddIntelCacheData(processor, Std[2].ecx >> 8);
  421. AddIntelCacheData(processor, Std[2].ecx >> 16);
  422. AddIntelCacheData(processor, Std[2].ecx >> 24);
  423. }
  424. if ((Std[2].edx & 0x80000000) == 0) {
  425. AddIntelCacheData(processor, Std[2].edx);
  426. AddIntelCacheData(processor, Std[2].edx >> 8);
  427. AddIntelCacheData(processor, Std[2].edx >> 16);
  428. AddIntelCacheData(processor, Std[2].edx >> 24);
  429. }
  430. }
  431. } else if (strcmp(proc[processor]->Manufacturer, "AuthenticAMD") == 0) {
  432. DecodeAMDCacheIdentifiers(processor);
  433. }
  434. }
  435. #ifdef ENABLE_SORTS
  436. CrissCross::Data::QuickSort<char *> sorter;
  437. proc[processor]->caches.sort(sorter);
  438. #endif
  439. }
  440. const char *CPUID::CreateCacheDescription(cacheType _type, const char *_pages, unsigned int _size, unsigned int _assoc, unsigned int _entries, unsigned int _linesize, bool _sectored)
  441. {
  442. CoreAssert(this != NULL);
  443. static char description[512];
  444. char assoc[64], prefix[64], size[32], sectored[32], linesz[32], entries[32];
  445. /* No associativity? Invalid cache entry. Abort, abort! */
  446. if (_assoc == 0)
  447. return NULL;
  448. memset(prefix, 0, sizeof(prefix));
  449. /* Get the prefix worked out. */
  450. switch (_type)
  451. {
  452. case CACHE_TYPE_TRACE:
  453. sprintf(prefix, "Trace cache: ");
  454. break;
  455. case CACHE_TYPE_L0DATA_TLB:
  456. sprintf(prefix, "L0 Data TLB: %s pages, ", _pages);
  457. break;
  458. case CACHE_TYPE_L1DATA_TLB:
  459. sprintf(prefix, "L1 Data TLB: %s pages, ", _pages);
  460. break;
  461. case CACHE_TYPE_L2DATA_TLB:
  462. sprintf(prefix, "L2 Data TLB: %s pages, ", _pages);
  463. break;
  464. case CACHE_TYPE_L0CODE_TLB:
  465. sprintf(prefix, "L0 Code TLB: %s pages, ", _pages);
  466. break;
  467. case CACHE_TYPE_L1CODE_TLB:
  468. sprintf(prefix, "L1 Code TLB: %s pages, ", _pages);
  469. break;
  470. case CACHE_TYPE_L2CODE_TLB:
  471. sprintf(prefix, "L2 Code TLB: %s pages, ", _pages);
  472. break;
  473. case CACHE_TYPE_DATA_TLB:
  474. sprintf(prefix, "Data TLB: %s pages, ", _pages);
  475. break;
  476. case CACHE_TYPE_CODE_TLB:
  477. sprintf(prefix, "Code TLB: %s pages, ", _pages);
  478. break;
  479. case CACHE_TYPE_L1CODE:
  480. sprintf(prefix, "1st-level code cache: ");
  481. break;
  482. case CACHE_TYPE_L1DATA:
  483. sprintf(prefix, "1st-level data cache: ");
  484. break;
  485. case CACHE_TYPE_L2:
  486. sprintf(prefix, "2nd-level cache: ");
  487. break;
  488. case CACHE_TYPE_L3:
  489. sprintf(prefix, "3rd-level cache: ");
  490. break;
  491. }
  492. /* Figure out the appropriate size descriptor. */
  493. memset(size, 0, sizeof(size));
  494. switch (_type)
  495. {
  496. case CACHE_TYPE_L0DATA_TLB:
  497. case CACHE_TYPE_L1DATA_TLB:
  498. case CACHE_TYPE_L2DATA_TLB:
  499. case CACHE_TYPE_L0CODE_TLB:
  500. case CACHE_TYPE_L1CODE_TLB:
  501. case CACHE_TYPE_L2CODE_TLB:
  502. case CACHE_TYPE_DATA_TLB:
  503. case CACHE_TYPE_CODE_TLB:
  504. break;
  505. case CACHE_TYPE_TRACE:
  506. sprintf(size, "%dK-uops, ", _size);
  507. break;
  508. default:
  509. if (_size >= 1024)
  510. sprintf(size, "%dMB, ", _size / 1024);
  511. else
  512. sprintf(size, "%dKB, ", _size);
  513. }
  514. /* Get the associativity part set up */
  515. switch (_assoc)
  516. {
  517. case 0x01: sprintf(assoc, "direct mapped"); break;
  518. case 0xFF: sprintf(assoc, "fully associative"); break;
  519. default: sprintf(assoc, "%d-way set associative", _assoc); break;
  520. }
  521. /* If this is a TLB, we have entries */
  522. if (_entries)
  523. sprintf(entries, ", %d entries", _entries);
  524. else
  525. memset(entries, 0, sizeof(entries));
  526. /* Is it a sectored cache? */
  527. sprintf(sectored, _sectored ? ", sectored cache" : "");
  528. /* If there's a line size, we append it. */
  529. if (_linesize)
  530. sprintf(linesz, ", %d byte line size", _linesize);
  531. else
  532. memset(linesz, 0, sizeof(linesz));
  533. sprintf(description, "%s%s%s%s%s%s\n", prefix, size, assoc, entries, sectored, linesz);
  534. return description;
  535. }
  536. void CPUID::DecodeAMDCacheIdentifiers(int processor)
  537. {
  538. CoreAssert(this != NULL);
  539. /* L1 Cache Information */
  540. unsigned int L1DTlb2and4MAssoc, L1DTlb2and4MSize, L1ITlb2and4MAssoc, L1ITlb2and4MSize;
  541. unsigned int L1DTlb4KAssoc, L1DTlb4KSize, L1ITlb4KAssoc, L1ITlb4KSize;
  542. unsigned int L1DcSize, L1DcAssoc, L1DcLinesPerTag, L1DcLineSize;
  543. unsigned int L1IcSize, L1IcAssoc, L1IcLinesPerTag, L1IcLineSize;
  544. /* */
  545. /* L1 Data 2MB/4MB TLB */
  546. L1DTlb2and4MAssoc = (Ext[5].eax & 0xFF000000) >> 24;
  547. L1DTlb2and4MSize = (Ext[5].eax & 0x00FF0000) >> 16;
  548. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "2MB or 4MB", 0, L1DTlb2and4MAssoc, L1DTlb2and4MSize, 0, false));
  549. /* */
  550. /* L1 Code 2MB/4MB TLB */
  551. L1ITlb2and4MAssoc = (Ext[5].eax & 0x0000FF00) >> 8;
  552. L1ITlb2and4MSize = (Ext[5].eax & 0x000000FF);
  553. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "2MB or 4MB", 0, L1ITlb2and4MAssoc, L1ITlb2and4MSize, 0, false));
  554. /* */
  555. /* L1 Data 4KB TLB */
  556. L1DTlb4KAssoc = (Ext[5].ebx & 0xFF000000) >> 24;
  557. L1DTlb4KSize = (Ext[5].ebx & 0x00FF0000) >> 16;
  558. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB", 0, L1DTlb4KAssoc, L1DTlb4KSize, 0, false));
  559. /* */
  560. /* L1 Code 4KB TLB */
  561. L1ITlb4KAssoc = (Ext[5].ebx & 0x0000FF00) >> 8;
  562. L1ITlb4KSize = (Ext[5].ebx & 0x000000FF);
  563. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB", 0, L1ITlb4KAssoc, L1ITlb4KSize, 0, false));
  564. /* */
  565. /* L1 Data Cache */
  566. L1DcSize = (Ext[5].ecx & 0xFF000000) >> 24;
  567. L1DcAssoc = (Ext[5].ecx & 0x00FF0000) >> 16;
  568. L1DcLinesPerTag = (Ext[5].ecx & 0x0000FF00) >> 8;
  569. L1DcLineSize = (Ext[5].ecx & 0x000000FF);
  570. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, L1DcSize, L1DcAssoc, 0, L1DcLineSize, false));
  571. /* */
  572. /* L1 Code Cache */
  573. L1IcSize = (Ext[5].edx & 0xFF000000) >> 24;
  574. L1IcAssoc = (Ext[5].edx & 0x00FF0000) >> 16;
  575. L1IcLinesPerTag = (Ext[5].edx & 0x0000FF00) >> 8;
  576. L1IcLineSize = (Ext[5].edx & 0x000000FF);
  577. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, L1IcSize, L1IcAssoc, 0, L1IcLineSize, false));
  578. /* L2 Cache Information */
  579. unsigned int L2DTlb2and4MAssoc, L2DTlb2and4MSize, L2ITlb2and4MAssoc, L2ITlb2and4MSize;
  580. unsigned int L2DTlb4KAssoc, L2DTlb4KSize, L2ITlb4KAssoc, L2ITlb4KSize;
  581. unsigned int L2Size, L2Assoc, L2LinesPerTag, L2LineSize;
  582. /* */
  583. /* L2 Data 2MB/4MB TLB */
  584. L2DTlb2and4MAssoc = (Ext[6].eax & 0xF0000000) >> 28;
  585. L2DTlb2and4MSize = (Ext[6].eax & 0x0FFF0000) >> 16;
  586. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2DATA_TLB, "2MB or 4MB", 0, L2DTlb2and4MAssoc, L2DTlb2and4MSize, 0, false));
  587. /* */
  588. /* L2 Code 2MB/4MB TLB */
  589. L2ITlb2and4MAssoc = (Ext[6].eax & 0x0000F000) >> 12;
  590. L2ITlb2and4MSize = (Ext[6].eax & 0x00000FFF);
  591. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2CODE_TLB, "2MB or 4MB", 0, L2ITlb2and4MAssoc, L2ITlb2and4MSize, 0, false));
  592. /* */
  593. /* L2 Data 4KB TLB */
  594. L2DTlb4KAssoc = (Ext[6].ebx & 0xF0000000) >> 28;
  595. L2DTlb4KSize = (Ext[6].ebx & 0x0FFF0000) >> 16;
  596. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2DATA_TLB, "4KB", 0, L2DTlb4KAssoc, L2DTlb4KSize, 0, false));
  597. /* */
  598. /* L2 Code 4KB TLB */
  599. L2ITlb4KAssoc = (Ext[6].ebx & 0x0000F000) >> 12;
  600. L2ITlb4KSize = (Ext[6].ebx & 0x00000FFF);
  601. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2CODE_TLB, "4KB", 0, L2ITlb4KAssoc, L2ITlb4KSize, 0, false));
  602. /* */
  603. /* L2 Cache */
  604. L2Size = (Ext[6].ecx & 0xFFFF0000) >> 16;
  605. L2Assoc = (Ext[6].ecx & 0x0000F000) >> 12;
  606. L2LinesPerTag = (Ext[6].ecx & 0x00000F00) >> 8;
  607. L2LineSize = (Ext[6].ecx & 0x000000FF);
  608. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, L2Size, L2Assoc, 0, L2LineSize, false));
  609. /* L3 Cache Information */
  610. unsigned int L3Size, L3Assoc, L3LinesPerTag, L3LineSize;
  611. /* */
  612. /* L3 Cache */
  613. L3Size = (Ext[6].edx & 0xFFFC0000) >> 18;
  614. L3Assoc = (Ext[6].edx & 0x0000F000) >> 12;
  615. L3LinesPerTag = (Ext[6].edx & 0x00000F00) >> 8;
  616. L3LineSize = (Ext[6].edx & 0x000000FF);
  617. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, L3Size * 512, L3Assoc, 0, L3LineSize, false));
  618. }
  619. void CPUID::AddCacheDescription(int processor, const char *description)
  620. {
  621. CoreAssert(this != NULL);
  622. if (!description) return;
  623. char *temp = new char[strlen(description) + 1];
  624. CoreAssert(temp);
  625. strcpy(temp, description);
  626. proc[processor]->caches.insert(temp);
  627. temp = NULL;
  628. }
  629. void CPUID::AddIntelCacheData(int processor, int x)
  630. {
  631. CoreAssert(this != NULL);
  632. /* Compliant with Intel document #241618, save for the ENABLE_SANDPILE sections. */
  633. x &= 0xff;
  634. switch (x)
  635. {
  636. case 0: break;
  637. case 0x1: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB", 0, 4, 32, 0, false)); break;
  638. case 0x2: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4MB", 0, 255, 2, 0, false)); break;
  639. case 0x3: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB", 0, 4, 64, 0, false)); break;
  640. case 0x4: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4MB", 0, 4, 8, 0, false)); break;
  641. case 0x5: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4MB", 0, 4, 32, 0, false)); break;
  642. case 0x6: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, 8, 4, 0, 32, false)); break;
  643. case 0x8: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, 16, 4, 0, 32, false)); break;
  644. case 0xa: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 8, 2, 0, 32, false)); break;
  645. #if defined (ENABLE_SANDPILE)
  646. case 0xb: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4MB", 0, 4, 4, 0, false)); break;
  647. #endif
  648. case 0xc: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 16, 4, 0, 32, false)); break;
  649. #if defined (ENABLE_SANDPILE)
  650. case 0x10: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 16, 4, 0, 32, false)); break;
  651. case 0x15: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, 16, 4, 0, 32, false)); break;
  652. case 0x1A: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 96, 6, 0, 64, false)); break;
  653. #endif
  654. case 0x22: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 512, 4, 0, 64, true)); break;
  655. case 0x23: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 1024, 8, 0, 64, true)); break;
  656. case 0x25: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 2048, 8, 0, 64, true)); break;
  657. case 0x29: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 4096, 8, 0, 64, true)); break;
  658. case 0x2C: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 32, 8, 0, 64, false)); break;
  659. case 0x30: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, 32, 8, 0, 64, false)); break;
  660. case 0x39: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 128, 4, 0, 64, true)); break;
  661. case 0x3A: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 192, 6, 0, 64, true)); break;
  662. case 0x3B: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 128, 2, 0, 64, true)); break;
  663. case 0x3C: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 256, 4, 0, 64, true)); break;
  664. case 0x3D: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 384, 6, 0, 64, true)); break;
  665. case 0x3E: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 4, 0, 64, true)); break;
  666. case 0x40: AddCacheDescription(processor, "No 2nd-level cache, or if 2nd-level cache exists, no 3rd-level cache\n"); break;
  667. case 0x41: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 128, 4, 0, 32, false)); break;
  668. case 0x42: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 256, 4, 0, 32, false)); break;
  669. case 0x43: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 4, 0, 32, false)); break;
  670. case 0x44: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 1024, 4, 0, 32, false)); break;
  671. case 0x45: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 2048, 4, 0, 32, false)); break;
  672. case 0x46: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 4096, 4, 0, 64, false)); break;
  673. case 0x47: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 8192, 8, 0, 64, false)); break;
  674. #if defined (ENABLE_SANDPILE)
  675. case 0x48: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 3072, 12, 0, 64, false)); break;
  676. #endif
  677. case 0x49: AddCacheDescription(processor, CreateCacheDescription(
  678. /* This is an L3 on the P4 and an L2 on the Core 2 */
  679. proc[processor]->features.exists("SSSE3") ? CACHE_TYPE_L2 : CACHE_TYPE_L3, NULL, 4096, 16, 0, 64, false)); break;
  680. case 0x4A: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 6144, 12, 0, 64, false)); break;
  681. case 0x4B: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 8192, 16, 0, 64, false)); break;
  682. case 0x4C: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 12288, 12, 0, 64, false)); break;
  683. case 0x4D: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 16384, 16, 0, 64, false)); break;
  684. case 0x4E: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 6144, 24, 0, 64, false)); break;
  685. case 0x50: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB, 2MB or 4MB", 0, 255, 64, 0, false)); break;
  686. case 0x51: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB, 2MB or 4MB", 0, 255, 128, 0, false)); break;
  687. case 0x52: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB, 2MB or 4MB", 0, 255, 256, 0, false)); break;
  688. case 0x56: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA_TLB, "4MB", 0, 4, 16, 0, false)); break;
  689. case 0x57: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA_TLB, "4KB", 0, 4, 16, 0, false)); break;
  690. case 0x5b: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB or 4MB", 0, 255, 64, 0, false)); break;
  691. case 0x5c: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB or 4MB", 0, 255, 128, 0, false)); break;
  692. case 0x5d: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB or 4MB", 0, 255, 256, 0, false)); break;
  693. case 0x60: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 16, 8, 0, 64, true)); break;
  694. case 0x66: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 8, 4, 0, 64, true)); break;
  695. case 0x67: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 16, 4, 0, 64, true)); break;
  696. case 0x68: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA, NULL, 32, 4, 0, 64, true)); break;
  697. case 0x70: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_TRACE, NULL, 12, 8, 0, 0, false)); break;
  698. case 0x71: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_TRACE, NULL, 16, 8, 0, 0, false)); break;
  699. case 0x72: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_TRACE, NULL, 32, 8, 0, 0, false)); break;
  700. case 0x73: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_TRACE, NULL, 64, 8, 0, 0, false)); break;
  701. #if defined (ENABLE_SANDPILE)
  702. case 0x77: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1CODE, NULL, 16, 4, 0, 64, true)); break;
  703. #endif
  704. case 0x78: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 1024, 4, 0, 64, false)); break;
  705. case 0x79: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 128, 8, 0, 64, true)); break;
  706. case 0x7A: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 256, 8, 0, 64, true)); break;
  707. case 0x7B: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 8, 0, 64, true)); break;
  708. case 0x7C: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 1024, 8, 0, 64, true)); break;
  709. case 0x7D: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 2048, 8, 0, 64, false)); break;
  710. #if defined (ENABLE_SANDPILE)
  711. case 0x7E: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 256, 8, 0, 128, true)); break;
  712. #endif
  713. case 0x7F: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 2, 0, 64, false)); break;
  714. #if defined (ENABLE_SANDPILE)
  715. case 0x81: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 128, 8, 0, 128, true)); break;
  716. #endif
  717. case 0x82: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 256, 8, 0, 32, false)); break;
  718. case 0x83: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 8, 0, 32, false)); break;
  719. case 0x84: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 1024, 8, 0, 32, false)); break;
  720. case 0x85: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 2048, 8, 0, 32, false)); break;
  721. case 0x86: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 512, 4, 0, 64, false)); break;
  722. case 0x87: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2, NULL, 1024, 8, 0, 64, false)); break;
  723. #if defined (ENABLE_SANDPILE)
  724. case 0x88: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 2048, 4, 0, 64, false)); break;
  725. case 0x89: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 4096, 4, 0, 64, false)); break;
  726. case 0x8A: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 8192, 4, 0, 64, false)); break;
  727. case 0x8D: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L3, NULL, 3072, 12, 0, 128, false)); break;
  728. case 0x90: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB or 256MB", 0, 255, 64, 0, false)); break;
  729. case 0x96: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L1DATA_TLB, "4KB or 256MB", 0, 255, 32, 0, false)); break;
  730. case 0x9B: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_L2DATA_TLB, "4KB or 256MB", 0, 255, 96, 0, false)); break;
  731. #endif
  732. case 0xB0: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4KB", 0, 4, 128, 0, false)); break;
  733. case 0xB1: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "4MB", 0, 4, 4, 0, false));
  734. AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_CODE_TLB, "2MB", 0, 4, 8, 0, false)); break;
  735. case 0xB3: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB", 0, 4, 128, 0, false)); break;
  736. case 0xB4: AddCacheDescription(processor, CreateCacheDescription(CACHE_TYPE_DATA_TLB, "4KB", 0, 4, 256, 0, false)); break;
  737. case 0xF0: AddCacheDescription(processor, "64 byte prefetching\n"); break;
  738. case 0xF1: AddCacheDescription(processor, "128 byte prefetching\n"); break;
  739. default:
  740. {
  741. char temp[256];
  742. sprintf(temp, "Unknown cache descriptor 0x%02x\n", x);
  743. AddCacheDescription(processor, temp);
  744. }
  745. break;
  746. }
  747. }
  748. void CPUID::DetectFMS(int processor)
  749. {
  750. CoreAssert(this != NULL);
  751. /* Compliant with Intel document #241618. */
  752. proc[processor]->Family = (char)(((Std[1].eax >> 8) + (Std[1].eax >> 20)) & 0xff);
  753. proc[processor]->Model = (char)(((((Std[1].eax >> 16) & 0xf) << 4) + ((Std[1].eax >> 4) & 0xf)) & 0xff);
  754. proc[processor]->Stepping = (char)(Std[1].eax & 0xf);
  755. }
  756. void CPUID::DetectBrandID(int processor)
  757. {
  758. CoreAssert(this != NULL);
  759. /* Compliant with Intel document #241618. */
  760. proc[processor]->BrandID = (char)(Std[1].ebx & 0xff);
  761. }
  762. void CPUID::DetectCount(int processor)
  763. {
  764. CoreAssert(this != NULL);
  765. /* Compliant with Intel document #241618. */
  766. /* Do we have HTT flag set? */
  767. if (proc[processor]->features.exists("HTT")) {
  768. /* AMD and Intel documentations state that if HTT is supported */
  769. /* then this the EBX:16 will reflect the logical processor count */
  770. /* otherwise the flag is reserved. */
  771. proc[processor]->features.insert("CMP", NULL);
  772. proc[processor]->CoresPerPackage = (char)((Std[4].eax & 0xFC000000) >> 26) + 1;
  773. proc[processor]->LogicalPerPackage = (char)((Std[1].ebx & 0x00FF0000) >> 16);
  774. if (proc[processor]->CoresPerPackage < 1)
  775. proc[processor]->CoresPerPackage = 1;
  776. if (proc[processor]->LogicalPerPackage < 1)
  777. proc[processor]->LogicalPerPackage = 1;
  778. if (proc[processor]->CoresPerPackage > 1 &&
  779. proc[processor]->LogicalPerPackage > proc[processor]->CoresPerPackage) {
  780. /* Hyperthreaded dual core. */
  781. } else if (proc[processor]->CoresPerPackage > 1 &&
  782. proc[processor]->LogicalPerPackage == proc[processor]->CoresPerPackage) {
  783. /* Dual core. */
  784. proc[processor]->features.erase("HTT");
  785. } else if (proc[processor]->CoresPerPackage == 1 &&
  786. proc[processor]->LogicalPerPackage > proc[processor]->CoresPerPackage) {
  787. /* Hyperthreaded. */
  788. proc[processor]->features.erase("CMP");
  789. }
  790. } else {
  791. /* HTT not supported. Report logical processor count as 1. */
  792. proc[processor]->LogicalPerPackage = 1;
  793. }
  794. }
  795. void CPUID::DetectAPIC(int processor)
  796. {
  797. CoreAssert(this != NULL);
  798. /* Found at http://www.intel.com/cd/ids/developer/asmo-na/eng/211924.htm */
  799. proc[processor]->APICID = (char)((Std[1].ebx & 0xFF000000) >> 24);
  800. }
  801. void CPUID::DetectFeature(const unsigned int *_register, long _flag, int _processor, const char *_name)
  802. {
  803. CoreAssert(this != NULL);
  804. /* Compliant with Intel document #241618. */
  805. bool supported = (*_register & _flag) > 0;
  806. if (supported)
  807. proc[_processor]->features.insert(_name, NULL);
  808. }
  809. void CPUID::DetectFeatures(int processor)
  810. {
  811. CoreAssert(this != NULL);
  812. /* Compliant with Intel document #241618. */
  813. DetectFeature(&Std[1].edx, FPU_FLAG, processor, "FPU");
  814. DetectFeature(&Std[1].edx, VME_FLAG, processor, "VME");
  815. DetectFeature(&Std[1].edx, DE_FLAG, processor, "DE");
  816. DetectFeature(&Std[1].edx, PSE_FLAG, processor, "PSE");
  817. DetectFeature(&Std[1].edx, TSC_FLAG, processor, "TSC");
  818. DetectFeature(&Std[1].edx, MSR_FLAG, processor, "MSR");
  819. DetectFeature(&Std[1].edx, PAE_FLAG, processor, "PAE");
  820. DetectFeature(&Std[1].edx, MCE_FLAG, processor, "MCE");
  821. DetectFeature(&Std[1].edx, CX8_FLAG, processor, "CX8");
  822. DetectFeature(&Std[1].edx, APIC_FLAG, processor, "APIC");
  823. DetectFeature(&Std[1].edx, SEP_FLAG, processor, "SEP");
  824. DetectFeature(&Std[1].edx, MTRR_FLAG, processor, "MTRR");
  825. DetectFeature(&Std[1].edx, PGE_FLAG, processor, "PGE");
  826. DetectFeature(&Std[1].edx, MCA_FLAG, processor, "MCA");
  827. DetectFeature(&Std[1].edx, CMOV_FLAG, processor, "CMOV");
  828. DetectFeature(&Std[1].edx, PAT_FLAG, processor, "PAT");
  829. DetectFeature(&Std[1].edx, PSE36_FLAG, processor, "PSE36");
  830. DetectFeature(&Std[1].edx, PSNUM_FLAG, processor, "PSNUM");
  831. DetectFeature(&Std[1].edx, CLFLUSH_FLAG, processor, "CLFLUSH");
  832. DetectFeature(&Std[1].edx, DTS_FLAG, processor, "DTS");
  833. DetectFeature(&Std[1].edx, ACPI_FLAG, processor, "ACPI");
  834. DetectFeature(&Std[1].edx, MMX_FLAG, processor, "MMX");
  835. DetectFeature(&Std[1].edx, FXSR_FLAG, processor, "FXSR");
  836. DetectFeature(&Std[1].edx, SSE_FLAG, processor, "SSE");
  837. DetectFeature(&Std[1].edx, SSE2_FLAG, processor, "SSE2");
  838. DetectFeature(&Std[1].edx, SS_FLAG, processor, "SS");
  839. DetectFeature(&Std[1].edx, HTT_FLAG, processor, "HTT");
  840. DetectFeature(&Std[1].edx, TM1_FLAG, processor, "TM1");
  841. DetectFeature(&Std[1].ecx, SSE3_FLAG, processor, "SSE3");
  842. DetectFeature(&Std[1].ecx, CX16_FLAG, processor, "CX16");
  843. if (proc[processor]->Manufacturer) {
  844. if (strcmp(proc[processor]->Manufacturer, "GenuineIntel") == 0) {
  845. /* IA64 and PBE are on Intel where the 3DNow! flags are on AMD */
  846. DetectFeature(&Std[1].edx, IA64_FLAG, processor, "IA64");
  847. DetectFeature(&Std[1].edx, PBE_FLAG, processor, "PBE");
  848. /* Intel-only flags */
  849. DetectFeature(&Ext[1].ecx, LAHF_FLAG, processor, "LAHF");
  850. DetectFeature(&Std[1].ecx, DS_CPL_FLAG, processor, "DS_CPL");
  851. DetectFeature(&Std[1].ecx, MONITOR_FLAG, processor, "MONITOR");
  852. DetectFeature(&Std[1].ecx, DTES64_FLAG, processor, "DTES64");
  853. DetectFeature(&Std[1].ecx, EIST_FLAG, processor, "EIST");
  854. DetectFeature(&Std[1].ecx, TM2_FLAG, processor, "TM2");
  855. DetectFeature(&Std[1].ecx, SSSE3_FLAG, processor, "SSSE3");
  856. DetectFeature(&Std[1].ecx, CNXTID_FLAG, processor, "CNXTID");
  857. DetectFeature(&Ext[1].edx, SYSCALL_FLAG, processor, "SYSCALL");
  858. DetectFeature(&Std[1].ecx, XTPR_FLAG, processor, "XTPR");
  859. DetectFeature(&Ext[1].edx, XD_FLAG, processor, "XD");
  860. DetectFeature(&Std[1].ecx, DCA_FLAG, processor, "DCA");
  861. DetectFeature(&Ext[1].edx, EM64T_FLAG, processor, "EM64T");
  862. DetectFeature(&Std[1].ecx, SSE4_1_FLAG, processor, "SSE4.1");
  863. DetectFeature(&Std[1].ecx, SSE4_2_FLAG, processor, "SSE4.2");
  864. DetectFeature(&Std[1].ecx, VMX_FLAG, processor, "VMX");
  865. DetectFeature(&Std[1].ecx, SMX_FLAG, processor, "SMX");
  866. DetectFeature(&Std[1].ecx, PDCM_FLAG, processor, "PDCM");
  867. } else if (strcmp(proc[processor]->Manufacturer, "AuthenticAMD") == 0) {
  868. /* AMD-only flags, EDX 8000_0001 */
  869. DetectFeature(&Ext[1].edx, NX_FLAG, processor, "NX");
  870. DetectFeature(&Ext[1].edx, MMXEXT_FLAG, processor, "MMXEXT");
  871. DetectFeature(&Ext[1].edx, FFXSR_FLAG, processor, "FFXSR");
  872. DetectFeature(&Ext[1].edx, RDTSCP_FLAG, processor, "RDTSCP");
  873. DetectFeature(&Ext[1].edx, LM_FLAG, processor, "LM");
  874. DetectFeature(&Ext[1].edx, _3DNOWEXT_FLAG, processor, "3DNOWEXT");
  875. DetectFeature(&Ext[1].edx, _3DNOW_FLAG, processor, "3DNOW");
  876. /* AMD-only flags, ECX 8000_0001 */
  877. DetectFeature(&Ext[1].ecx, LS_FLAG, processor, "LS");
  878. DetectFeature(&Ext[1].ecx, CL_FLAG, processor, "CL");
  879. DetectFeature(&Ext[1].ecx, SVM_FLAG, processor, "SVM");
  880. DetectFeature(&Ext[1].ecx, EAS_FLAG, processor, "EAS");
  881. DetectFeature(&Ext[1].ecx, AMC8_FLAG, processor, "AMC8");
  882. DetectFeature(&Ext[1].ecx, ABM_FLAG, processor, "ABM");
  883. DetectFeature(&Ext[1].ecx, SSE4A_FLAG, processor, "SSE4A");
  884. DetectFeature(&Ext[1].ecx, MAS_FLAG, processor, "MAS");
  885. DetectFeature(&Ext[1].ecx, _3DNP_FLAG, processor, "3DNP");
  886. DetectFeature(&Ext[1].ecx, OSVW_FLAG, processor, "OSVW");
  887. DetectFeature(&Ext[1].ecx, SKINIT_FLAG, processor, "SKINIT");
  888. DetectFeature(&Ext[1].ecx, WDT_FLAG, processor, "WDT");
  889. }
  890. }
  891. }
  892. }
  893. }
  894. #endif