prochw.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*++
  2. Copyright (c) 2017 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. prochw.c
  9. Abstract:
  10. This module processor architecture specific support for the boot loader.
  11. Author:
  12. Evan Green 6-Jun-2017
  13. Environment:
  14. Boot
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/kernel.h>
  20. #include <minoca/kernel/bootload.h>
  21. #include <minoca/kernel/x64.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. #define BOOT_GDT_ENTRIES 4
  26. #define BOOT_IDT_SIZE (VECTOR_DEBUG_SERVICE + 1)
  27. //
  28. // ------------------------------------------------------ Data Type Definitions
  29. //
  30. //
  31. // ----------------------------------------------- Internal Function Prototypes
  32. //
  33. //
  34. // Assembly routines
  35. //
  36. VOID
  37. BoBreakExceptionHandlerAsm (
  38. VOID
  39. );
  40. VOID
  41. BoSingleStepExceptionHandlerAsm (
  42. VOID
  43. );
  44. VOID
  45. BoDebugServiceHandlerAsm (
  46. VOID
  47. );
  48. VOID
  49. BoDivideByZeroExceptionHandlerAsm (
  50. VOID
  51. );
  52. VOID
  53. BoProtectionFaultHandlerAsm (
  54. VOID
  55. );
  56. VOID
  57. BoPageFaultHandlerAsm (
  58. VOID
  59. );
  60. VOID
  61. BoLoadBootDataSegments (
  62. VOID
  63. );
  64. //
  65. // C routines
  66. //
  67. VOID
  68. BopInitializeGdt (
  69. PGDT_ENTRY GdtTable
  70. );
  71. VOID
  72. BopInitializeInterrupts (
  73. PVOID Idt
  74. );
  75. VOID
  76. BopCreateGate (
  77. PPROCESSOR_GATE Gate,
  78. PVOID HandlerRoutine,
  79. USHORT Selector,
  80. UCHAR StackIndex,
  81. UCHAR Access
  82. );
  83. //
  84. // -------------------------------------------------------------------- Globals
  85. //
  86. //
  87. // Store global processor structures.
  88. //
  89. PROCESSOR_GATE BoIdt[BOOT_IDT_SIZE];
  90. //
  91. // Create the GDT, which has the following entries:
  92. // 0x00 - Null entry, required.
  93. // 0x08 - KERNEL_CS, flat long mode code segment.
  94. // 0x10 - KERNEL_DS, flat data segment.
  95. // 0x18 - KERNEL64_TRANSITION_CS, flat 32-bit code segment.
  96. //
  97. GDT_ENTRY BoGdt[BOOT_GDT_ENTRIES] = {
  98. {0},
  99. {
  100. MAX_USHORT,
  101. 0,
  102. 0,
  103. GATE_ACCESS_PRESENT | GDT_TYPE_CODE,
  104. GDT_GRANULARITY_KILOBYTE | GDT_GRANULARITY_64BIT |
  105. (MAX_GDT_LIMIT >> 16),
  106. 0
  107. },
  108. {
  109. MAX_USHORT,
  110. 0,
  111. 0,
  112. GATE_ACCESS_PRESENT | GDT_TYPE_DATA_WRITE,
  113. GDT_GRANULARITY_KILOBYTE | GDT_GRANULARITY_64BIT |
  114. (MAX_GDT_LIMIT >> 16),
  115. 0
  116. },
  117. {
  118. MAX_USHORT,
  119. 0,
  120. 0,
  121. GATE_ACCESS_PRESENT | GDT_TYPE_CODE,
  122. GDT_GRANULARITY_KILOBYTE | GDT_GRANULARITY_32BIT |
  123. (MAX_GDT_LIMIT >> 16),
  124. 0
  125. }
  126. };
  127. //
  128. // ------------------------------------------------------------------ Functions
  129. //
  130. ULONG
  131. MmPageSize (
  132. VOID
  133. )
  134. /*++
  135. Routine Description:
  136. This routine returns the size of a page of memory.
  137. Arguments:
  138. None.
  139. Return Value:
  140. Returns the size of one page of memory (ie the minimum mapping granularity).
  141. --*/
  142. {
  143. return PAGE_SIZE;
  144. }
  145. ULONG
  146. MmPageShift (
  147. VOID
  148. )
  149. /*++
  150. Routine Description:
  151. This routine returns the amount to shift by to truncate an address to a
  152. page number.
  153. Arguments:
  154. None.
  155. Return Value:
  156. Returns the amount to shift to reach page granularity.
  157. --*/
  158. {
  159. return PAGE_SHIFT;
  160. }
  161. VOID
  162. BoInitializeProcessor (
  163. VOID
  164. )
  165. /*++
  166. Routine Description:
  167. This routine initializes processor-specific structures. In the case of x86,
  168. it initializes the GDT and TSS.
  169. Arguments:
  170. None.
  171. Return Value:
  172. None.
  173. --*/
  174. {
  175. //
  176. // Initialize and load the GDT and Tasks.
  177. //
  178. BopInitializeGdt(BoGdt);
  179. BopInitializeInterrupts(BoIdt);
  180. return;
  181. }
  182. VOID
  183. BoDivideByZeroHandler (
  184. PTRAP_FRAME TrapFrame
  185. )
  186. /*++
  187. Routine Description:
  188. This routine responds to a divide by zero exception.
  189. Arguments:
  190. TrapFrame - Supplies a pointer to the trap frame.
  191. Return Value:
  192. None.
  193. --*/
  194. {
  195. RtlDebugPrint(" *** Divide by zero ***\n");
  196. KdDebugExceptionHandler(EXCEPTION_DIVIDE_BY_ZERO, NULL, TrapFrame);
  197. return;
  198. }
  199. VOID
  200. BoPageFaultHandler (
  201. PVOID FaultingAddress,
  202. PTRAP_FRAME TrapFrame
  203. )
  204. /*++
  205. Routine Description:
  206. This routine handles page faults, or rather doesn't handle them.
  207. Arguments:
  208. FaultingAddress - Supplies the address that caused the fault.
  209. TrapFrame - Supplies a pointer to the trap frame of the fault.
  210. Return Value:
  211. None.
  212. --*/
  213. {
  214. RtlDebugPrint(" *** Page Fault: Faulting Address 0x%08llx, "
  215. "Instruction 0x%08llx",
  216. FaultingAddress,
  217. TrapFrame->Rip);
  218. if ((TrapFrame->ErrorCode & X86_FAULT_ERROR_CODE_PRESENT) != 0) {
  219. RtlDebugPrint(", Protection Violation");
  220. } else {
  221. RtlDebugPrint(", Page Not Present");
  222. }
  223. if ((TrapFrame->ErrorCode & X86_FAULT_ERROR_CODE_WRITE) != 0) {
  224. RtlDebugPrint(", Write ***\n");
  225. } else {
  226. RtlDebugPrint(", Read ***\n");
  227. }
  228. KdDebugExceptionHandler(EXCEPTION_ACCESS_VIOLATION, NULL, TrapFrame);
  229. return;
  230. }
  231. //
  232. // --------------------------------------------------------- Internal Functions
  233. //
  234. VOID
  235. BopInitializeGdt (
  236. PGDT_ENTRY GdtTable
  237. )
  238. /*++
  239. Routine Description:
  240. This routine initializes and loads the system's Global Descriptor Table
  241. (GDT).
  242. Arguments:
  243. GdtTable - Supplies a pointer to the global descriptor table to use. It is
  244. assumed this table contains enough entries to hold all the segment
  245. descriptors.
  246. Task - Supplies a pointer to the main task.
  247. Return Value:
  248. None.
  249. --*/
  250. {
  251. TABLE_REGISTER Gdt;
  252. //
  253. // Install the new GDT table.
  254. //
  255. Gdt.Limit = sizeof(GDT_ENTRY) * BOOT_GDT_ENTRIES;
  256. Gdt.Base = (UINTN)GdtTable;
  257. ArLoadGdtr(&Gdt);
  258. BoLoadBootDataSegments();
  259. return;
  260. }
  261. VOID
  262. BopInitializeInterrupts (
  263. PVOID Idt
  264. )
  265. /*++
  266. Routine Description:
  267. This routine initializes and enables interrupts.
  268. Arguments:
  269. Idt - Supplies a pointer to the Interrrupt Descriptor Table for this
  270. processor.
  271. Return Value:
  272. None.
  273. --*/
  274. {
  275. TABLE_REGISTER IdtRegister;
  276. PPROCESSOR_GATE IdtTable;
  277. IdtTable = Idt;
  278. //
  279. // Set up the debug trap handlers.
  280. //
  281. BopCreateGate(IdtTable + VECTOR_DIVIDE_ERROR,
  282. BoDivideByZeroExceptionHandlerAsm,
  283. KERNEL_CS,
  284. 0,
  285. GATE_ACCESS_USER | GATE_TYPE_TRAP);
  286. BopCreateGate(IdtTable + VECTOR_BREAKPOINT,
  287. BoBreakExceptionHandlerAsm,
  288. KERNEL_CS,
  289. 0,
  290. GATE_ACCESS_USER | GATE_TYPE_INTERRUPT);
  291. BopCreateGate(IdtTable + VECTOR_DEBUG,
  292. BoSingleStepExceptionHandlerAsm,
  293. KERNEL_CS,
  294. 0,
  295. GATE_TYPE_INTERRUPT);
  296. BopCreateGate(IdtTable + VECTOR_DEBUG_SERVICE,
  297. BoDebugServiceHandlerAsm,
  298. KERNEL_CS,
  299. 0,
  300. GATE_TYPE_INTERRUPT);
  301. BopCreateGate(IdtTable + VECTOR_PROTECTION_FAULT,
  302. BoProtectionFaultHandlerAsm,
  303. KERNEL_CS,
  304. 0,
  305. GATE_TYPE_INTERRUPT);
  306. //
  307. // Set up the page fault handler.
  308. //
  309. BopCreateGate(IdtTable + VECTOR_PAGE_FAULT,
  310. BoPageFaultHandlerAsm,
  311. KERNEL_CS,
  312. 0,
  313. GATE_TYPE_INTERRUPT);
  314. BopCreateGate(IdtTable + VECTOR_STACK_EXCEPTION,
  315. BoPageFaultHandlerAsm,
  316. KERNEL_CS,
  317. 0,
  318. GATE_TYPE_INTERRUPT);
  319. //
  320. // Load the IDT register with our interrupt descriptor table.
  321. //
  322. IdtRegister.Limit = (BOOT_IDT_SIZE * sizeof(PROCESSOR_GATE)) - 1;
  323. IdtRegister.Base = (UINTN)IdtTable;
  324. ArLoadIdtr(&IdtRegister);
  325. return;
  326. }
  327. VOID
  328. BopCreateGate (
  329. PPROCESSOR_GATE Gate,
  330. PVOID HandlerRoutine,
  331. USHORT Selector,
  332. UCHAR StackIndex,
  333. UCHAR Access
  334. )
  335. /*++
  336. Routine Description:
  337. This routine initializes a task, call, trap, or interrupt gate with the
  338. given values.
  339. Arguments:
  340. Gate - Supplies a pointer to the structure where the gate will be returned.
  341. It is assumed this structure is already allocated.
  342. HandlerRoutine - Supplies a pointer to the destination routine of this gate.
  343. Selector - Supplies the code selector this gate should run in.
  344. StackIndex - Supplies the interrupt stack index to use. Supply to to not
  345. switch stacks.
  346. Access - Supplies the gate access bits, similar to the GDT access bits.
  347. Return Value:
  348. None.
  349. --*/
  350. {
  351. Gate->LowOffset = (USHORT)((UINTN)HandlerRoutine & 0xFFFF);
  352. Gate->MidOffset = (USHORT)((UINTN)HandlerRoutine >> 16);
  353. Gate->HighWord = (ULONG)((UINTN)HandlerRoutine >> 32);
  354. Gate->Selector = Selector;
  355. Gate->Ist = StackIndex;
  356. Gate->Access = Access | GATE_ACCESS_PRESENT;
  357. Gate->Reserved = 0;
  358. return;
  359. }