cpu.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * Copyright (c) 2014 The Chromium OS Authors.
  3. *
  4. * Part of this file is adapted from coreboot
  5. * src/arch/x86/include/arch/cpu.h and
  6. * src/arch/x86/lib/cpu.c
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #ifndef _ASM_CPU_H
  11. #define _ASM_CPU_H
  12. enum {
  13. X86_VENDOR_INVALID = 0,
  14. X86_VENDOR_INTEL,
  15. X86_VENDOR_CYRIX,
  16. X86_VENDOR_AMD,
  17. X86_VENDOR_UMC,
  18. X86_VENDOR_NEXGEN,
  19. X86_VENDOR_CENTAUR,
  20. X86_VENDOR_RISE,
  21. X86_VENDOR_TRANSMETA,
  22. X86_VENDOR_NSC,
  23. X86_VENDOR_SIS,
  24. X86_VENDOR_ANY = 0xfe,
  25. X86_VENDOR_UNKNOWN = 0xff
  26. };
  27. struct cpuid_result {
  28. uint32_t eax;
  29. uint32_t ebx;
  30. uint32_t ecx;
  31. uint32_t edx;
  32. };
  33. /*
  34. * Generic CPUID function
  35. */
  36. static inline struct cpuid_result cpuid(int op)
  37. {
  38. struct cpuid_result result;
  39. asm volatile(
  40. "mov %%ebx, %%edi;"
  41. "cpuid;"
  42. "mov %%ebx, %%esi;"
  43. "mov %%edi, %%ebx;"
  44. : "=a" (result.eax),
  45. "=S" (result.ebx),
  46. "=c" (result.ecx),
  47. "=d" (result.edx)
  48. : "0" (op)
  49. : "edi");
  50. return result;
  51. }
  52. /*
  53. * Generic Extended CPUID function
  54. */
  55. static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
  56. {
  57. struct cpuid_result result;
  58. asm volatile(
  59. "mov %%ebx, %%edi;"
  60. "cpuid;"
  61. "mov %%ebx, %%esi;"
  62. "mov %%edi, %%ebx;"
  63. : "=a" (result.eax),
  64. "=S" (result.ebx),
  65. "=c" (result.ecx),
  66. "=d" (result.edx)
  67. : "0" (op), "2" (ecx)
  68. : "edi");
  69. return result;
  70. }
  71. /*
  72. * CPUID functions returning a single datum
  73. */
  74. static inline unsigned int cpuid_eax(unsigned int op)
  75. {
  76. unsigned int eax;
  77. __asm__("mov %%ebx, %%edi;"
  78. "cpuid;"
  79. "mov %%edi, %%ebx;"
  80. : "=a" (eax)
  81. : "0" (op)
  82. : "ecx", "edx", "edi");
  83. return eax;
  84. }
  85. static inline unsigned int cpuid_ebx(unsigned int op)
  86. {
  87. unsigned int eax, ebx;
  88. __asm__("mov %%ebx, %%edi;"
  89. "cpuid;"
  90. "mov %%ebx, %%esi;"
  91. "mov %%edi, %%ebx;"
  92. : "=a" (eax), "=S" (ebx)
  93. : "0" (op)
  94. : "ecx", "edx", "edi");
  95. return ebx;
  96. }
  97. static inline unsigned int cpuid_ecx(unsigned int op)
  98. {
  99. unsigned int eax, ecx;
  100. __asm__("mov %%ebx, %%edi;"
  101. "cpuid;"
  102. "mov %%edi, %%ebx;"
  103. : "=a" (eax), "=c" (ecx)
  104. : "0" (op)
  105. : "edx", "edi");
  106. return ecx;
  107. }
  108. static inline unsigned int cpuid_edx(unsigned int op)
  109. {
  110. unsigned int eax, edx;
  111. __asm__("mov %%ebx, %%edi;"
  112. "cpuid;"
  113. "mov %%edi, %%ebx;"
  114. : "=a" (eax), "=d" (edx)
  115. : "0" (op)
  116. : "ecx", "edi");
  117. return edx;
  118. }
  119. /* Standard macro to see if a specific flag is changeable */
  120. static inline int flag_is_changeable_p(uint32_t flag)
  121. {
  122. uint32_t f1, f2;
  123. asm(
  124. "pushfl\n\t"
  125. "pushfl\n\t"
  126. "popl %0\n\t"
  127. "movl %0,%1\n\t"
  128. "xorl %2,%0\n\t"
  129. "pushl %0\n\t"
  130. "popfl\n\t"
  131. "pushfl\n\t"
  132. "popl %0\n\t"
  133. "popfl\n\t"
  134. : "=&r" (f1), "=&r" (f2)
  135. : "ir" (flag));
  136. return ((f1^f2) & flag) != 0;
  137. }
  138. static inline void mfence(void)
  139. {
  140. __asm__ __volatile__("mfence" : : : "memory");
  141. }
  142. /**
  143. * cpu_enable_paging_pae() - Enable PAE-paging
  144. *
  145. * @cr3: Value to set in cr3 (PDPT or PML4T)
  146. */
  147. void cpu_enable_paging_pae(ulong cr3);
  148. /**
  149. * cpu_disable_paging_pae() - Disable paging and PAE
  150. */
  151. void cpu_disable_paging_pae(void);
  152. /**
  153. * cpu_has_64bit() - Check if the CPU has 64-bit support
  154. *
  155. * @return 1 if this CPU supports long mode (64-bit), 0 if not
  156. */
  157. int cpu_has_64bit(void);
  158. /**
  159. * cpu_vendor_name() - Get CPU vendor name
  160. *
  161. * @vendor: CPU vendor enumeration number
  162. *
  163. * @return: Address to hold the CPU vendor name string
  164. */
  165. const char *cpu_vendor_name(int vendor);
  166. #define CPU_MAX_NAME_LEN 49
  167. /**
  168. * cpu_get_name() - Get the name of the current cpu
  169. *
  170. * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
  171. * @return pointer to name, which will likely be a few bytes after the start
  172. * of @name
  173. * \0 terminator
  174. */
  175. char *cpu_get_name(char *name);
  176. /**
  177. * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
  178. *
  179. * The kernel is uncompressed and the 64-bit entry point is expected to be
  180. * at @target.
  181. *
  182. * This function is used internally - see cpu_jump_to_64bit() for a more
  183. * useful function.
  184. *
  185. * @pgtable: Address of 24KB area containing the page table
  186. * @setup_base: Pointer to the setup.bin information for the kernel
  187. * @target: Pointer to the start of the kernel image
  188. */
  189. void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
  190. /**
  191. * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
  192. *
  193. * The kernel is uncompressed and the 64-bit entry point is expected to be
  194. * at @target.
  195. *
  196. * @setup_base: Pointer to the setup.bin information for the kernel
  197. * @target: Pointer to the start of the kernel image
  198. */
  199. int cpu_jump_to_64bit(ulong setup_base, ulong target);
  200. #endif