You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cpuid.c 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <string.h>
  25. #include <ipxe/cpuid.h>
  26. /** @file
  27. *
  28. * x86 CPU feature detection
  29. *
  30. */
  31. /**
  32. * Check whether or not CPUID instruction is supported
  33. *
  34. * @ret is_supported CPUID instruction is supported
  35. */
  36. int cpuid_is_supported ( void ) {
  37. unsigned long original;
  38. unsigned long inverted;
  39. __asm__ ( "pushf\n\t"
  40. "pushf\n\t"
  41. "pop %0\n\t"
  42. "mov %0,%1\n\t"
  43. "xor %2,%1\n\t"
  44. "push %1\n\t"
  45. "popf\n\t"
  46. "pushf\n\t"
  47. "pop %1\n\t"
  48. "popf\n\t"
  49. : "=&r" ( original ), "=&r" ( inverted )
  50. : "ir" ( CPUID_FLAG ) );
  51. return ( ( original ^ inverted ) & CPUID_FLAG );
  52. }
  53. /**
  54. * Get Intel-defined x86 CPU features
  55. *
  56. * @v features x86 CPU features to fill in
  57. */
  58. static void x86_intel_features ( struct x86_features *features ) {
  59. uint32_t max_level;
  60. uint32_t discard_a;
  61. uint32_t discard_b;
  62. uint32_t discard_c;
  63. uint32_t discard_d;
  64. /* Check that features are available via CPUID */
  65. cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c,
  66. &discard_d );
  67. if ( max_level < CPUID_FEATURES ) {
  68. DBGC ( features, "CPUID has no Intel-defined features (max "
  69. "level %08x)\n", max_level );
  70. return;
  71. }
  72. /* Get features */
  73. cpuid ( CPUID_FEATURES, &discard_a, &discard_b,
  74. &features->intel.ecx, &features->intel.edx );
  75. DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
  76. features->intel.ecx, features->intel.edx );
  77. }
  78. /**
  79. * Get AMD-defined x86 CPU features
  80. *
  81. * @v features x86 CPU features to fill in
  82. */
  83. static void x86_amd_features ( struct x86_features *features ) {
  84. uint32_t max_level;
  85. uint32_t discard_a;
  86. uint32_t discard_b;
  87. uint32_t discard_c;
  88. uint32_t discard_d;
  89. /* Check that features are available via CPUID */
  90. cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c,
  91. &discard_d );
  92. if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) {
  93. DBGC ( features, "CPUID has no extended functions\n" );
  94. return;
  95. }
  96. if ( max_level < CPUID_AMD_FEATURES ) {
  97. DBGC ( features, "CPUID has no AMD-defined features (max "
  98. "level %08x)\n", max_level );
  99. return;
  100. }
  101. /* Get features */
  102. cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b,
  103. &features->amd.ecx, &features->amd.edx );
  104. DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
  105. features->amd.ecx, features->amd.edx );
  106. }
  107. /**
  108. * Get x86 CPU features
  109. *
  110. * @v features x86 CPU features to fill in
  111. */
  112. void x86_features ( struct x86_features *features ) {
  113. /* Clear all features */
  114. memset ( features, 0, sizeof ( *features ) );
  115. /* Check that CPUID instruction is available */
  116. if ( ! cpuid_is_supported() ) {
  117. DBGC ( features, "CPUID instruction is not supported\n" );
  118. return;
  119. }
  120. /* Get Intel-defined features */
  121. x86_intel_features ( features );
  122. /* Get AMD-defined features */
  123. x86_amd_features ( features );
  124. }