xsave.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "libcflat.h"
  2. #include "desc.h"
  3. #include "processor.h"
  4. #ifdef __x86_64__
  5. #define uint64_t unsigned long
  6. #else
  7. #define uint64_t unsigned long long
  8. #endif
  9. int xgetbv_checking(u32 index, u64 *result)
  10. {
  11. u32 eax, edx;
  12. asm volatile(ASM_TRY("1f")
  13. ".byte 0x0f,0x01,0xd0\n\t" /* xgetbv */
  14. "1:"
  15. : "=a" (eax), "=d" (edx)
  16. : "c" (index));
  17. *result = eax + ((u64)edx << 32);
  18. return exception_vector();
  19. }
  20. int xsetbv_checking(u32 index, u64 value)
  21. {
  22. u32 eax = value;
  23. u32 edx = value >> 32;
  24. asm volatile(ASM_TRY("1f")
  25. ".byte 0x0f,0x01,0xd1\n\t" /* xsetbv */
  26. "1:"
  27. : : "a" (eax), "d" (edx), "c" (index));
  28. return exception_vector();
  29. }
  30. int write_cr4_checking(unsigned long val)
  31. {
  32. asm volatile(ASM_TRY("1f")
  33. "mov %0,%%cr4\n\t"
  34. "1:": : "r" (val));
  35. return exception_vector();
  36. }
  37. #define CPUID_1_ECX_XSAVE (1 << 26)
  38. #define CPUID_1_ECX_OSXSAVE (1 << 27)
  39. int check_cpuid_1_ecx(unsigned int bit)
  40. {
  41. return (cpuid(1).c & bit) != 0;
  42. }
  43. uint64_t get_supported_xcr0(void)
  44. {
  45. struct cpuid r;
  46. r = cpuid_indexed(0xd, 0);
  47. printf("eax %x, ebx %x, ecx %x, edx %x\n",
  48. r.a, r.b, r.c, r.d);
  49. return r.a + ((u64)r.d << 32);
  50. }
  51. #define X86_CR4_OSXSAVE 0x00040000
  52. #define XCR_XFEATURE_ENABLED_MASK 0x00000000
  53. #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010
  54. #define XSTATE_FP 0x1
  55. #define XSTATE_SSE 0x2
  56. #define XSTATE_YMM 0x4
  57. void test_xsave(void)
  58. {
  59. unsigned long cr4;
  60. uint64_t supported_xcr0;
  61. uint64_t test_bits;
  62. u64 xcr0;
  63. printf("Legal instruction testing:\n");
  64. supported_xcr0 = get_supported_xcr0();
  65. printf("Supported XCR0 bits: %#lx\n", supported_xcr0);
  66. test_bits = XSTATE_FP | XSTATE_SSE;
  67. report("Check minimal XSAVE required bits",
  68. (supported_xcr0 & test_bits) == test_bits);
  69. cr4 = read_cr4();
  70. report("Set CR4 OSXSAVE", write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == 0);
  71. report("Check CPUID.1.ECX.OSXSAVE - expect 1",
  72. check_cpuid_1_ecx(CPUID_1_ECX_OSXSAVE));
  73. printf("\tLegal tests\n");
  74. test_bits = XSTATE_FP;
  75. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)",
  76. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0);
  77. test_bits = XSTATE_FP | XSTATE_SSE;
  78. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)",
  79. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0);
  80. report(" xgetbv(XCR_XFEATURE_ENABLED_MASK)",
  81. xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0);
  82. printf("\tIllegal tests\n");
  83. test_bits = 0;
  84. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP",
  85. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR);
  86. test_bits = XSTATE_SSE;
  87. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP",
  88. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR);
  89. if (supported_xcr0 & XSTATE_YMM) {
  90. test_bits = XSTATE_YMM;
  91. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP",
  92. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR);
  93. test_bits = XSTATE_FP | XSTATE_YMM;
  94. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP",
  95. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR);
  96. }
  97. test_bits = XSTATE_SSE;
  98. report("\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP",
  99. xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR);
  100. test_bits = XSTATE_SSE;
  101. report("\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP",
  102. xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR);
  103. cr4 &= ~X86_CR4_OSXSAVE;
  104. report("Unset CR4 OSXSAVE", write_cr4_checking(cr4) == 0);
  105. report("Check CPUID.1.ECX.OSXSAVE - expect 0",
  106. check_cpuid_1_ecx(CPUID_1_ECX_OSXSAVE) == 0);
  107. printf("\tIllegal tests:\n");
  108. test_bits = XSTATE_FP;
  109. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD",
  110. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR);
  111. test_bits = XSTATE_FP | XSTATE_SSE;
  112. report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD",
  113. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR);
  114. printf("\tIllegal tests:\n");
  115. report("\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD",
  116. xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR);
  117. }
  118. void test_no_xsave(void)
  119. {
  120. unsigned long cr4;
  121. u64 xcr0;
  122. report("Check CPUID.1.ECX.OSXSAVE - expect 0",
  123. check_cpuid_1_ecx(CPUID_1_ECX_OSXSAVE) == 0);
  124. printf("Illegal instruction testing:\n");
  125. cr4 = read_cr4();
  126. report("Set OSXSAVE in CR4 - expect #GP",
  127. write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR);
  128. report("Execute xgetbv - expect #UD",
  129. xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR);
  130. report("Execute xsetbv - expect #UD",
  131. xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR);
  132. }
  133. int main(void)
  134. {
  135. setup_idt();
  136. if (check_cpuid_1_ecx(CPUID_1_ECX_XSAVE)) {
  137. printf("CPU has XSAVE feature\n");
  138. test_xsave();
  139. } else {
  140. printf("CPU don't has XSAVE feature\n");
  141. test_no_xsave();
  142. }
  143. return report_summary();
  144. }