cpu.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #define _POSIX_C_SOURCE 200112L
  2. #define _GNU_SOURCE
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include <unistd.h>
  7. #include <stdint.h>
  8. #include <assert.h>
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include <sched.h>
  12. #include <arpa/inet.h>
  13. #include <sys/time.h>
  14. #include "pci.h"
  15. #include "tools.h"
  16. #include "error.h"
  17. static void pcilib_run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd) {
  18. uint32_t ebx = 0, edx;
  19. # if defined( __i386__ ) && defined ( __PIC__ )
  20. /* in case of PIC under 32-bit EBX cannot be clobbered */
  21. __asm__ ( "movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx),
  22. # else
  23. __asm__ ( "cpuid" : "+b" (ebx),
  24. # endif
  25. "+a" (eax), "+c" (ecx), "=d" (edx) );
  26. abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
  27. }
  28. static int pcilib_check_xcr0_ymm() {
  29. uint32_t xcr0;
  30. __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
  31. return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
  32. }
  33. static int pcilib_check_4th_gen_intel_core_features() {
  34. uint32_t abcd[4];
  35. uint32_t fma_movbe_osxsave_mask = ((1 << 12) | (1 << 22) | (1 << 27));
  36. uint32_t avx2_bmi12_mask = (1 << 5) | (1 << 3) | (1 << 8);
  37. /* CPUID.(EAX=01H, ECX=0H):ECX.FMA[bit 12]==1 &&
  38. CPUID.(EAX=01H, ECX=0H):ECX.MOVBE[bit 22]==1 &&
  39. CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1 */
  40. pcilib_run_cpuid( 1, 0, abcd );
  41. if ( (abcd[2] & fma_movbe_osxsave_mask) != fma_movbe_osxsave_mask )
  42. return 0;
  43. if ( ! pcilib_check_xcr0_ymm() )
  44. return 0;
  45. /* CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1 &&
  46. CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]==1 &&
  47. CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]==1 */
  48. pcilib_run_cpuid( 7, 0, abcd );
  49. if ( (abcd[1] & avx2_bmi12_mask) != avx2_bmi12_mask )
  50. return 0;
  51. /* CPUID.(EAX=80000001H):ECX.LZCNT[bit 5]==1 */
  52. pcilib_run_cpuid( 0x80000001, 0, abcd );
  53. if ( (abcd[2] & (1 << 5)) == 0)
  54. return 0;
  55. return 1;
  56. }
  57. static int pcilib_detect_cpu_gen() {
  58. if (pcilib_check_4th_gen_intel_core_features())
  59. return 4;
  60. return 0;
  61. }
  62. int pcilib_get_cpu_gen() {
  63. int gen = -1;
  64. if (gen < 0 )
  65. gen = pcilib_detect_cpu_gen();
  66. return gen;
  67. }
  68. int pcilib_get_page_mask() {
  69. int pagesize,pagemask,temp;
  70. pagesize = sysconf(_SC_PAGESIZE);
  71. for( pagemask=0, temp = pagesize; temp != 1; ) {
  72. temp = (temp >> 1);
  73. pagemask = (pagemask << 1)+1;
  74. }
  75. return pagemask;
  76. }
  77. int pcilib_get_cpu_count() {
  78. int err;
  79. int cpu_count;
  80. cpu_set_t mask;
  81. err = sched_getaffinity(getpid(), sizeof(mask), &mask);
  82. if (err) return 1;
  83. #ifdef CPU_COUNT
  84. cpu_count = CPU_COUNT(&mask);
  85. #else
  86. for (cpu_count = 0; cpu_count < CPU_SETSIZE; cpu_count++) {
  87. if (!CPU_ISSET(cpu_count, &mask)) break;
  88. }
  89. #endif
  90. if (!cpu_count) cpu_count = PCILIB_DEFAULT_CPU_COUNT;
  91. return cpu_count;
  92. }