cpu.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * cpu.h
  3. *
  4. * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef _CPU_H_
  20. #define _CPU_H_
  21. #include <sdk/defs.h>
  22. #include <sdk/cpu.h>
  23. #define CPU_CONTROL_FLAG_PE (1 << 0)
  24. #define CPU_CONTROL_FLAG_MP (1 << 1)
  25. #define CPU_CONTROL_FLAG_EM (1 << 2)
  26. #define CPU_CONTROL_FLAG_TS (1 << 3)
  27. #define CPU_CONTROL_FLAG_ET (1 << 4)
  28. #define CPU_CONTROL_FLAG_NE (1 << 5)
  29. #define CPU_CONTROL_FLAG_WP (1 << 16)
  30. #define CPU_CONTROL_FLAG_AM (1 << 18)
  31. #define CPU_CONTROL_FLAG_NW (1 << 29)
  32. #define CPU_CONTROL_FLAG_CD (1 << 30)
  33. #define CPU_CONTROL_FLAG_PG (1 << 31)
  34. #define CPU_FEATURE_FLAG_VME (1 << 0)
  35. #define CPU_FEATURE_FLAG_PVI (1 << 1)
  36. #define CPU_FEATURE_FLAG_TSD (1 << 2)
  37. #define CPU_FEATURE_FLAG_DE (1 << 3)
  38. #define CPU_FEATURE_FLAG_PSE (1 << 4)
  39. #define CPU_FEATURE_FLAG_PAE (1 << 5)
  40. #define CPU_FEATURE_FLAG_MCE (1 << 6)
  41. #define CPU_FEATURE_FLAG_PGE (1 << 7)
  42. #define CPU_FEATURE_FLAG_PCE (1 << 8)
  43. #define CPU_FEATURE_FLAG_OSXFSR (1 << 9)
  44. #define CPU_FEATURE_FLAG_OSXMMEXCPT (1 << 10)
  45. #define CPU_FEATURE_FLAG_UMIP (1 << 11)
  46. #define CPU_FEATURE_FLAG_LA57 (1 << 12)
  47. #define CPU_FEATURE_FLAG_VMXE (1 << 13)
  48. #define CPU_FEATURE_FLAG_SMXE (1 << 14)
  49. #define CPU_FEATURE_FLAG_FSGSBASE (1 << 16)
  50. #define CPU_FEATURE_FLAG_PCIDE (1 << 17)
  51. #define CPU_FEATURE_FLAG_OSXSAVE (1 << 18)
  52. #define CPU_FEATURE_FLAG_SMEP (1 << 20)
  53. #define CPU_FEATURE_FLAG_SMAP (1 << 21)
  54. #define CPU_FEATURE_FLAG_PKE (1 << 22)
  55. enum
  56. {
  57. FPU_NOT_PRESENT = 0,
  58. FPU_LEGACY,
  59. FPU_XFSR,
  60. };
  61. typedef word_t port_t;
  62. #define IO_PORT_FUNCTIONS(type, prefix) \
  63. static inline type##_t cpu_read_port_##type(port_t port) \
  64. { \
  65. type##_t value; \
  66. __asm__ volatile ("in %1, %0\n" : "=a"(value) : "Nd"(port)); \
  67. return value; \
  68. } \
  69. \
  70. static inline void cpu_write_port_##type(port_t port, type##_t value) \
  71. { \
  72. __asm__ volatile ("out %0, %1\n" :: "a"(value), "Nd"(port)); \
  73. } \
  74. \
  75. static inline void cpu_read_port_buffer_##type(port_t port, type##_t *buffer, size_t size) \
  76. { \
  77. __asm__ volatile("cld\n" \
  78. "rep; ins" prefix "\n" \
  79. :"+D"(buffer), "+c"(size) \
  80. : "d"(port) \
  81. : "cc"); \
  82. } \
  83. \
  84. static inline void cpu_write_port_buffer_##type(port_t port, const type##_t *buffer, size_t size) \
  85. { \
  86. __asm__ volatile("cld\n" \
  87. "rep; outs " prefix "\n" \
  88. : "+S"(buffer), "+c"(size) \
  89. : "d"(port) \
  90. : "cc"); \
  91. }
  92. IO_PORT_FUNCTIONS(byte, "b")
  93. IO_PORT_FUNCTIONS(word, "w")
  94. IO_PORT_FUNCTIONS(dword, "l")
  95. static inline uintptr_t cpu_read_master_control_register(void)
  96. {
  97. uintptr_t value;
  98. __asm__ volatile ("movl %%cr0, %0"
  99. : "=r"((dword_t)value) /* output */
  100. : /* input */
  101. : /* clobber */);
  102. return value;
  103. }
  104. static inline void cpu_write_master_control_register(uintptr_t value)
  105. {
  106. __asm__ volatile ("movl %0, %%cr0"
  107. : /* output */
  108. : "r"((dword_t)value) /* input */
  109. : /* clobber */);
  110. }
  111. static inline uintptr_t cpu_read_faulting_address(void)
  112. {
  113. uintptr_t value;
  114. __asm__ volatile ("movl %%cr2, %0"
  115. : "=r"((dword_t)value) /* output */
  116. : /* input */
  117. : /* clobber */);
  118. return value;
  119. }
  120. static inline uintptr_t cpu_read_page_table_register(void)
  121. {
  122. uintptr_t value;
  123. __asm__ volatile ("movl %%cr3, %0"
  124. : "=r"((dword_t)value) /* output */
  125. : /* input */
  126. : /* clobber */);
  127. return value;
  128. }
  129. static inline void cpu_write_page_table_register(uintptr_t value)
  130. {
  131. __asm__ volatile ("movl %0, %%cr3"
  132. : /* output */
  133. : "r"((dword_t)value) /* input */
  134. : /* clobber */);
  135. }
  136. static inline uintptr_t cpu_read_feature_register(void)
  137. {
  138. uintptr_t value;
  139. __asm__ volatile ("movl %%cr4, %0"
  140. : "=r"((dword_t)value) /* output */
  141. : /* input */
  142. : /* clobber */);
  143. return value;
  144. }
  145. static inline void cpu_write_feature_register(uintptr_t value)
  146. {
  147. __asm__ volatile ("movl %0, %%cr4"
  148. : /* output */
  149. : "r"((dword_t)value) /* input */
  150. : /* clobber */);
  151. }
  152. static inline bool_t cpu_enable_interrupts(void)
  153. {
  154. dword_t flags;
  155. __asm__ volatile ("pushf\n"
  156. "sti\n"
  157. "pop %0"
  158. : "=g"(flags) /* output */
  159. : /* input */
  160. : /* clobber */);
  161. return !!(flags & CPU_STATUS_FLAG_IF);
  162. }
  163. static inline bool_t cpu_disable_interrupts(void)
  164. {
  165. dword_t flags;
  166. __asm__ volatile ("pushf\n"
  167. "cli\n"
  168. "pop %0"
  169. : "=g"(flags) /* output */
  170. : /* input */
  171. : /* clobber */);
  172. return !!(flags & CPU_STATUS_FLAG_IF);
  173. }
  174. static inline void cpu_set_interrupt_table(void *base, word_t size)
  175. {
  176. struct
  177. {
  178. word_t length;
  179. void *base;
  180. } __attribute__((__packed__)) idtr = { size - 1, base };
  181. __asm__ volatile ("lidt %0"
  182. : /* output */
  183. : "m"(idtr) /* input */
  184. : /* clobber */);
  185. }
  186. static inline void cpu_invalidate_tlb(void *address)
  187. {
  188. __asm__ volatile ("invlpg (%0)"
  189. : /* output */
  190. : "r"(address) /* input */
  191. : "memory" /* clobber */);
  192. }
  193. static inline void cpu_halt(void)
  194. {
  195. __asm__ volatile ("hlt");
  196. }
  197. extern int cpu_fpu_present;
  198. extern byte_t cpu_max_physical_bits;
  199. static inline void cpu_save_fpu_state(void *state)
  200. {
  201. switch (cpu_fpu_present)
  202. {
  203. case FPU_LEGACY:
  204. asm volatile ("fsave %0"
  205. : "=m"(*(byte_t*)state) /* output */
  206. : /* input */
  207. : /* clobber */);
  208. break;
  209. case FPU_XFSR:
  210. asm volatile ("fxsave %0"
  211. : "=m"(*(byte_t*)state) /* output */
  212. : /* input */
  213. : /* clobber */);
  214. break;
  215. }
  216. }
  217. static inline void cpu_restore_fpu_state(void *state)
  218. {
  219. switch (cpu_fpu_present)
  220. {
  221. case FPU_LEGACY:
  222. asm volatile ("frstor %0"
  223. : /* output */
  224. : "m"(*(byte_t*)state) /* input */
  225. : /* clobber */);
  226. break;
  227. case FPU_XFSR:
  228. asm volatile ("fxrstor %0"
  229. : /* output */
  230. : "m"(*(byte_t*)state) /* input */
  231. : /* clobber */);
  232. break;
  233. }
  234. }
  235. void cpu_init(void);
  236. #endif