cpuid.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* Sanity checks on values returned by CPUID. */
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. struct regs {
  7. uint32_t eax;
  8. uint32_t ebx;
  9. uint32_t ecx;
  10. uint32_t edx;
  11. } __attribute__((packed));
  12. static void cpuid(uint32_t leaf, uint32_t subleaf, struct regs* r) {
  13. __asm__ volatile("cpuid" : "=a"(r->eax), "=b"(r->ebx), "=c"(r->ecx), "=d"(r->edx)
  14. : "0"(leaf), "2"(subleaf));
  15. }
  16. static void test_cpuid_leaf_0xd(void) {
  17. struct regs r = {0, };
  18. const uint32_t leaf = 0xd;
  19. // Sub-leaf IDs for the various extensions.
  20. enum cpu_extension {
  21. x87 = 0, SSE, AVX, MPX_1, MPX_2, AVX512_1, AVX512_2, AVX512_3, PKRU = 9 };
  22. const uint32_t extension_sizes_bytes[] =
  23. { [AVX] = 256, [MPX_1] = 64, [MPX_2] = 64, [AVX512_1] = 64, [AVX512_2] = 512,
  24. [AVX512_3] = 1024, [PKRU] = 8};
  25. enum register_index {
  26. EAX = 0, EBX, ECX, EDX
  27. };
  28. const uint32_t extension_unavailable = 0;
  29. cpuid(leaf, AVX, &r);
  30. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[AVX]))
  31. abort();
  32. memset(&r, 0, sizeof(r));
  33. cpuid(leaf, MPX_1, &r);
  34. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[MPX_1]))
  35. abort();
  36. memset(&r, 0, sizeof(r));
  37. cpuid(leaf, MPX_2, &r);
  38. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[MPX_2]))
  39. abort();
  40. memset(&r, 0, sizeof(r));
  41. cpuid(leaf, AVX512_1, &r);
  42. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[AVX512_1]))
  43. abort();
  44. memset(&r, 0, sizeof(r));
  45. cpuid(leaf, AVX512_2, &r);
  46. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[AVX512_2]))
  47. abort();
  48. memset(&r, 0, sizeof(r));
  49. cpuid(leaf, AVX512_3, &r);
  50. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[AVX512_3]))
  51. abort();
  52. memset(&r, 0, sizeof(r));
  53. cpuid(leaf, PKRU, &r);
  54. if (!(r.eax == extension_unavailable || r.eax == extension_sizes_bytes[PKRU]))
  55. abort();
  56. memset(&r, 0, sizeof(r));
  57. }
  58. int main(int argc, char** argv, char** envp) {
  59. test_cpuid_leaf_0xd();
  60. printf("CPUID test passed.\n");
  61. return 0;
  62. }