archsup.S 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566
  1. /*++
  2. Copyright (c) 2013 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. archsup.S
  9. Abstract:
  10. This module implements assembly-based architecture support routines for the
  11. x86 platform.
  12. Author:
  13. Evan Green 7-Aug-2013
  14. Environment:
  15. Boot
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/x86.inc>
  21. //
  22. // -------------------------------------------------------------------- Macros
  23. //
  24. //
  25. // This macro switches the DS and ES data segments to the kernel's data
  26. // segments.
  27. //
  28. .macro LoadBootDataSegments
  29. movw $KERNEL_DS, %ax # Get the data segment selector,
  30. mov %ax, %ds # and save it into the data segments.
  31. mov %ax, %es #
  32. .endm
  33. //
  34. // ---------------------------------------------------------------- Definitions
  35. //
  36. //
  37. // -------------------------------------------------------------------- Globals
  38. //
  39. //
  40. // ----------------------------------------------------------------------- Code
  41. //
  42. //
  43. // .text specifies that this code belongs in the executable section.
  44. //
  45. // .code32 specifies that this is 32-bit protected mode code.
  46. //
  47. .text
  48. .code32
  49. //
  50. // BOOLEAN
  51. // EfiDisableInterrupts (
  52. // VOID
  53. // )
  54. //
  55. /*++
  56. Routine Description:
  57. This routine disables all interrupts on the current processor.
  58. Arguments:
  59. None.
  60. Return Value:
  61. TRUE if interrupts were previously enabled.
  62. FALSE if interrupts were previously disabled.
  63. --*/
  64. FUNCTION(EfiDisableInterrupts)
  65. pushfl # Push flags.
  66. cli # Clear the interrupt flag.
  67. popl %eax # Pop flags into eax.
  68. andl $IA32_EFLAG_IF, %eax # Isolate the Interrupt flag.
  69. jz EfiDisableInterruptsFalse # If the flag is not set, return FALSE.
  70. movl $TRUE, %eax # Return TRUE.
  71. ret #
  72. EfiDisableInterruptsFalse:
  73. movl $FALSE, %eax # Return FALSE.
  74. ret
  75. END_FUNCTION(EfiDisableInterrupts)
  76. //
  77. // VOID
  78. // EfiEnableInterrupts (
  79. // VOID
  80. // )
  81. //
  82. /*++
  83. Routine Description:
  84. This routine enables interrupts on the current processor.
  85. Arguments:
  86. None.
  87. Return Value:
  88. None.
  89. --*/
  90. FUNCTION(EfiEnableInterrupts)
  91. sti # Set the interrupt flag.
  92. ret #
  93. END_FUNCTION(EfiEnableInterrupts)
  94. //
  95. // BOOLEAN
  96. // EfiAreInterruptsEnabled (
  97. // VOID
  98. // )
  99. //
  100. /*++
  101. Routine Description:
  102. This routine determines whether or not interrupts are currently enabled
  103. on the processor.
  104. Arguments:
  105. None.
  106. Return Value:
  107. TRUE if interrupts are enabled in the processor.
  108. FALSE if interrupts are globally disabled.
  109. --*/
  110. FUNCTION(EfiAreInterruptsEnabled)
  111. pushfl # Get Eflags.
  112. popl %eax # Eflags in eax.
  113. andl $IA32_EFLAG_IF, %eax # Isolate the Interrupt flag.
  114. jz EfiInterruptsNotEnabled # If the flag is not set, return FALSE.
  115. movl $TRUE, %eax # Return TRUE.
  116. jmp EfiAreInterruptsEnabledEnd
  117. EfiInterruptsNotEnabled:
  118. movl $FALSE, %eax # Return FALSE.
  119. EfiAreInterruptsEnabledEnd:
  120. ret #
  121. END_FUNCTION(EfiAreInterruptsEnabled)
  122. //
  123. // VOID
  124. // EfipBreakExceptionHandlerAsm (
  125. // ULONG ReturnEip,
  126. // ULONG ReturnCodeSelector,
  127. // ULONG ReturnEflags
  128. // )
  129. //
  130. /*++
  131. Routine Description:
  132. This routine is called directly when an debug exception occurs. It sets up
  133. the parameters and calls a C routine to handle the break. It then restores
  134. machine state to return from the exception. The arguments to this function
  135. are pushed by the hardware.
  136. Arguments:
  137. ReturnEip - Supplies the address after the instruction that caused the trap.
  138. ReturnCodeSelector - Supplies the code selector the code that trapped was
  139. running under.
  140. ReturnEflags - Supplies the EFLAGS register immediately before the trap.
  141. Return Value:
  142. None.
  143. --*/
  144. FUNCTION(EfipBreakExceptionHandlerAsm)
  145. pushl $0 # Push a dummy error code.
  146. call EfipGenerateTrapFrame # Create a local trap frame.
  147. pushl %esp # Push a pointer to it as a parameter.
  148. pushl $0 # Push a NULL parameter.
  149. pushl $EXCEPTION_BREAK # Push the break parameter.
  150. call KdDebugExceptionHandler # Call the main exception handler.
  151. addl $0xC, %esp # Pop the parameters.
  152. call EfipRestoreTrapFrame # Restore the trap frame
  153. addl $4, %esp # Pop the error code.
  154. iret # Return from the exception.
  155. END_FUNCTION(EfipBreakExceptionHandlerAsm)
  156. //
  157. // VOID
  158. // EfipSingleStepExceptionHandlerAsm (
  159. // ULONG ReturnEip,
  160. // ULONG ReturnCodeSelector,
  161. // ULONG ReturnEflags
  162. // )
  163. //
  164. /*++
  165. Routine Description:
  166. This routine is called directly when an debug exception occurs. It sets up
  167. the parameters and calls the executive to dispatch the trap.
  168. Arguments:
  169. ReturnEip - Supplies the address after the instruction that caused the trap.
  170. ReturnCodeSelector - Supplies the code selector the code that trapped was
  171. running under.
  172. ReturnEflags - Supplies the EFLAGS register immediately before the trap.
  173. Return Value:
  174. None.
  175. --*/
  176. FUNCTION(EfipSingleStepExceptionHandlerAsm)
  177. pushl $0 # Push a dummy error code.
  178. call EfipGenerateTrapFrame # Create a local trap frame.
  179. pushl %esp # Push a pointer to it as a parameter.
  180. pushl $0 # Push a NULL parameter.
  181. pushl $EXCEPTION_SINGLE_STEP # Push the exception parameter.
  182. call KdDebugExceptionHandler # Call the main exception handler.
  183. addl $0xC, %esp # Pop the parameters.
  184. call EfipRestoreTrapFrame # Restore the trap frame
  185. addl $4, %esp # Pop the error code.
  186. iret # Return from the exception.
  187. END_FUNCTION(EfipSingleStepExceptionHandlerAsm)
  188. //
  189. // VOID
  190. // EfipDebugServiceHandlerAsm (
  191. // ULONG ReturnEip,
  192. // ULONG ReturnCodeSelector,
  193. // ULONG ReturnEflags
  194. // )
  195. //
  196. /*++
  197. Routine Description:
  198. This routine is entered via an IDT entry to request debug service. It sets
  199. up the parameters and calls KdDebugExceptionHandler, and then restores
  200. machine state to return from the exception. The arguments to this function
  201. are pushed by the hardware. Upon Entry:
  202. eax - Supplies the debug service request.
  203. ecx - Supplies the parameter to the request.
  204. Arguments:
  205. ReturnEip - Supplies the address after the instruction that caused the trap.
  206. ReturnCodeSelector - Supplies the code selector the code that trapped was
  207. running under.
  208. ReturnEflags - Supplies the EFLAGS register immediately before the trap.
  209. Return Value:
  210. None.
  211. --*/
  212. FUNCTION(EfipDebugServiceHandlerAsm)
  213. pushl $0 # Push a dummy error code.
  214. call EfipGenerateTrapFrame # Create a local trap frame.
  215. mov TRAP_EAX(%esp), %eax # Get eax, containing the service request.
  216. mov TRAP_ECX(%esp), %ecx # Get ecx, containing the parameter.
  217. pushl %esp # Push a pointer to the trap frame.
  218. pushl %ecx # Push exception parameter.
  219. pushl %eax # Push exception type.
  220. call KdDebugExceptionHandler # Call the main exception handler.
  221. addl $0xc, %esp # Pop the parameters.
  222. call EfipRestoreTrapFrame # Restore the trap frame
  223. addl $4, %esp # Pop the error code.
  224. iret # Return from the exception.
  225. END_FUNCTION(EfipDebugServiceHandlerAsm)
  226. //
  227. // VOID
  228. // EfipDivideByZeroExceptionHandlerAsm (
  229. // ULONG ReturnEip,
  230. // ULONG ReturnCodeSelector,
  231. // ULONG ReturnEflags
  232. // )
  233. //
  234. /*++
  235. Routine Description:
  236. This routine is called directly when a divide by zero exception occurs.
  237. Arguments:
  238. ReturnEip - Supplies the address after the instruction that caused the trap.
  239. ReturnCodeSelector - Supplies the code selector the code that trapped was
  240. running under.
  241. ReturnEflags - Supplies the EFLAGS register immediately before the trap.
  242. Return Value:
  243. None.
  244. --*/
  245. FUNCTION(EfipDivideByZeroExceptionHandlerAsm)
  246. pushl $0 # Push a dummy error code.
  247. call EfipGenerateTrapFrame # Create a local trap frame.
  248. pushl %esp # Push a pointer to it as a parameter.
  249. call EfipDivideByZeroHandler # Call the main exception handler.
  250. addl $0x4, %esp # Pop the parameters.
  251. call EfipRestoreTrapFrame # Restore the trap frame
  252. addl $4, %esp # Pop the error code.
  253. iret # Return from the exception.
  254. END_FUNCTION(EfipDivideByZeroExceptionHandlerAsm)
  255. //
  256. // VOID
  257. // EfipProtectionFaultHandlerAsm (
  258. // ULONG ReturnEip,
  259. // ULONG ReturnCodeSelector,
  260. // ULONG ReturnEflags
  261. // )
  262. //
  263. /*++
  264. Routine Description:
  265. This routine is called directly when a general protection fault occurs.
  266. It's job is to prepare the trap frame, call the appropriate handler, and
  267. then restore the trap frame.
  268. Arguments:
  269. ReturnEip - Supplies the address after the instruction that caused the trap.
  270. ReturnCodeSelector - Supplies the code selector the code that trapped was
  271. running under.
  272. ReturnEflags - Supplies the EFLAGS register immediately before the trap.
  273. Return Value:
  274. None.
  275. --*/
  276. FUNCTION(EfipProtectionFaultHandlerAsm)
  277. call EfipGenerateTrapFrame # Create a local trap frame.
  278. pushl %esp # Push a pointer to it as a parameter.
  279. pushl $0 # Push dummy parameter.
  280. pushl $EXCEPTION_ACCESS_VIOLATION # Push exception type parameter.
  281. call KdDebugExceptionHandler # Let the debugger handle this.
  282. addl $0xC, %esp # Pop the parameter.
  283. call EfipRestoreTrapFrame # Restore the trap frame
  284. addl $4, %esp # Pop the dummy error code.
  285. iret # Return from the exception.
  286. END_FUNCTION(EfipProtectionFaultHandlerAsm)
  287. //
  288. // VOID
  289. // EfipPageFaultHandlerAsm (
  290. // ULONG ReturnEip,
  291. // ULONG ReturnCodeSelector,
  292. // ULONG ReturnEflags
  293. // )
  294. //
  295. /*++
  296. Routine Description:
  297. This routine is called directly when a page fault occurs.
  298. Arguments:
  299. ReturnEip - Supplies the address after the instruction that caused the
  300. fault.
  301. ReturnCodeSelector - Supplies the code selector the code that faulted was
  302. running under.
  303. ReturnEflags - Supplies the EFLAGS register immediately before the fault.
  304. Return Value:
  305. None.
  306. --*/
  307. FUNCTION(EfipPageFaultHandlerAsm)
  308. call EfipGenerateTrapFrame # Create a local trap frame.
  309. movl %cr2, %eax # Get the faulting address.
  310. xor %edx, %edx # Zero edx.
  311. movl %edx, %cr2 # Clear CR2.
  312. sti # Re-enable interrupts.
  313. pushl %esp # Push a pointer to it as a parameter.
  314. pushl %eax #
  315. call EfipPageFaultHandler # Call the main exception handler.
  316. addl $8, %esp # Pop the parameters.
  317. call EfipRestoreTrapFrame # Restore the trap frame
  318. addl $4, %esp # Pop the error code.
  319. iret # Return from the exception.
  320. END_FUNCTION(EfipPageFaultHandlerAsm)
  321. //
  322. // VOID
  323. // EfipLoadBootDataSegments (
  324. // VOID
  325. // )
  326. //
  327. /*++
  328. Routine Description:
  329. This routine switches the data segments DS and ES to the boot data
  330. segment selectors.
  331. Arguments:
  332. None.
  333. Return Value:
  334. None.
  335. --*/
  336. FUNCTION(EfipLoadBootDataSegments)
  337. LoadBootDataSegments # Load the boot data segments.
  338. movw $KERNEL_DS, %ax # Get the data segment selector,
  339. mov %ax, %ss # and save it into the stack register.
  340. mov %ax, %fs # Load it.
  341. mov %ax, %gs # Load it in GS as well.
  342. ret #
  343. END_FUNCTION(EfipLoadBootDataSegments)
  344. //
  345. // EFIAPI
  346. // UINTN
  347. // EfipArchSetJump (
  348. // PEFI_JUMP_BUFFER JumpBuffer
  349. // )
  350. //
  351. /*++
  352. Routine Description:
  353. This routine sets the context in the given jump buffer such that when
  354. long jump is called, execution continues at the return value from this
  355. routine with a non-zero return value.
  356. Arguments:
  357. JumpBuffer - Supplies a pointer where the architecture-specific context
  358. will be saved.
  359. Return Value:
  360. 0 upon the initial return from this routine.
  361. Non-zero when returning as the target of a long jump.
  362. --*/
  363. FUNCTION(EfipArchSetJump)
  364. popl %ecx # Get the return address.
  365. movl (%esp), %edx # Get the jump buffer address.
  366. movl %ebx, (%edx) # Save EBX.
  367. movl %esi, 4(%edx) # Save ESI.
  368. movl %edi, 8(%edx) # Save EDI.
  369. movl %ebp, 12(%edx) # Save EBP.
  370. movl %esp, 16(%edx) # Save ESP.
  371. movl %ecx, 20(%edx) # Save EIP (the function return address).
  372. xorl %eax, %eax # Zero out return address.
  373. jmp *%ecx # Jump to the return value.
  374. END_FUNCTION(EfipArchSetJump)
  375. //
  376. // EFIAPI
  377. // VOID
  378. // EfipArchLongJump (
  379. // PEFI_JUMP_BUFFER JumpBuffer,
  380. // UINTN Value
  381. // )
  382. //
  383. /*++
  384. Routine Description:
  385. This routine restores machine context to the state it was in when the
  386. set jump that saved into the given jump buffer was called. The return
  387. value will be set to the given value.
  388. Arguments:
  389. JumpBuffer - Supplies a pointer to the context to restore.
  390. Value - Supplies the new return value to set from set jump. This should not
  391. be zero, otherwise the caller of set jump will not be able to
  392. differentiate it from its initial return.
  393. Return Value:
  394. This routine does not return.
  395. --*/
  396. FUNCTION(EfipArchLongJump)
  397. popl %eax # Skip the return address.
  398. popl %edx # Get the jump buffer.
  399. popl %eax # Get the new return value.
  400. movl (%edx), %ebx # Restore EBX.
  401. movl 4(%edx), %esi # Restore ESI.
  402. movl 8(%edx), %edi # Restore EDI.
  403. movl 12(%edx), %ebp # Restore EBP.
  404. movl 16(%edx), %esp # Restore ESP.
  405. jmp *20(%edx) # Restore EIP.
  406. END_FUNCTION(EfipArchLongJump)
  407. //
  408. // VOID
  409. // ArLoadTr (
  410. // USHORT TssSegment
  411. // )
  412. //
  413. /*++
  414. Routine Description:
  415. This routine loads a TSS (Task Selector State).
  416. Arguments:
  417. TssSegment - Supplies the segment selector in the GDT that describes the
  418. TSS.
  419. Return Value:
  420. None.
  421. --*/
  422. FUNCTION(ArLoadTr)
  423. ltr 4(%esp) # Load the Task Register.
  424. ret # That's it!
  425. END_FUNCTION(ArLoadTr)
  426. //
  427. // VOID
  428. // ArStoreTr (
  429. // PULONG TssSegment
  430. // )
  431. //
  432. /*++
  433. Routine Description:
  434. This routine retrieves the current TSS (Task Selector State) register.
  435. Arguments:
  436. TssSegment - Supplies a pointer where the current TSS segment register will
  437. be returned.
  438. Return Value:
  439. None.
  440. --*/
  441. FUNCTION(ArStoreTr)
  442. movl 4(%esp), %eax # Get the address parameter.
  443. str (%eax) # Store the TR register into it.
  444. ret # Return
  445. END_FUNCTION(ArStoreTr)
  446. //
  447. // VOID
  448. // ArLoadIdtr (
  449. // PVOID IdtBase
  450. // )
  451. //
  452. /*++
  453. Routine Description:
  454. This routine loads the given Interrupt Descriptor Table.
  455. Arguments:
  456. IdtBase - Supplies a pointer to the base of the IDT.
  457. Return Value:
  458. None.
  459. --*/
  460. FUNCTION(ArLoadIdtr)
  461. movl 4(%esp), %eax # Get the base parameter.
  462. lidt (%eax) # Load the IDT register.
  463. ret # That's it!
  464. END_FUNCTION(ArLoadIdtr)
  465. //
  466. // VOID
  467. // ArStoreIdtr (
  468. // PTABLE_REGISTER IdtRegister
  469. // )
  470. //
  471. /*++
  472. Routine Description:
  473. This routine stores the interrupt descriptor table register into the given
  474. value.
  475. Arguments:
  476. IdtRegister - Supplies a pointer that will receive the value.
  477. Return Value:
  478. None.
  479. --*/
  480. FUNCTION(ArStoreIdtr)
  481. movl 4(%esp), %eax # Get the address parameter.
  482. sidt (%eax) # Store the IDT register into it.
  483. ret # Return politely.
  484. END_FUNCTION(ArStoreIdtr)
  485. //
  486. // VOID
  487. // ArLoadGdtr (
  488. // TABLE_REGISTER Gdt
  489. // )
  490. //
  491. /*++
  492. Routine Description:
  493. This routine loads a global descriptor table.
  494. Arguments:
  495. Gdt - Supplies a pointer to the Gdt pointer, which contains the base and
  496. limit for the GDT.
  497. Return Value:
  498. None.
  499. --*/
  500. FUNCTION(ArLoadGdtr)
  501. //
  502. // Load the GDT and then perform a long jump. The long jump is required for
  503. // the new GDT to actually be loaded.
  504. //
  505. lgdt 4(%esp) # Load the GDT.
  506. ljmp $KERNEL_CS, $LoadGdtJump # Long jump.
  507. LoadGdtJump:
  508. ret # Simply return.
  509. END_FUNCTION(ArLoadGdtr)
  510. //
  511. // VOID
  512. // ArStoreGdtr (
  513. // PTABLE_REGISTER GdtRegister
  514. // )
  515. //
  516. /*++
  517. Routine Description:
  518. This routine stores the GDT register into the given value.
  519. Arguments:
  520. GdtRegister - Supplies a pointer that will receive the value.
  521. Return Value:
  522. None.
  523. --*/
  524. FUNCTION(ArStoreGdtr)
  525. movl 4(%esp), %eax # Get the address parameter.
  526. sgdt (%eax) # Store the GDT register into it.
  527. ret # Return politely.
  528. END_FUNCTION(ArStoreGdtr)
  529. //
  530. // PVOID
  531. // ArGetFaultingAddress (
  532. // VOID
  533. // )
  534. //
  535. /*++
  536. Routine Description:
  537. This routine determines which address caused a page fault.
  538. Arguments:
  539. None.
  540. Return Value:
  541. Returns the faulting address.
  542. --*/
  543. FUNCTION(ArGetFaultingAddress)
  544. movl %cr2, %eax # Return CR2.
  545. ret #
  546. END_FUNCTION(ArGetFaultingAddress)
  547. //
  548. // VOID
  549. // ArSetFaultingAddress (
  550. // PVOID Value
  551. // )
  552. //
  553. /*++
  554. Routine Description:
  555. This routine sets the CR2 register.
  556. Arguments:
  557. Value - Supplies the value to set.
  558. Return Value:
  559. None.
  560. --*/
  561. FUNCTION(ArSetFaultingAddress)
  562. movl 4(%esp), %eax
  563. movl %eax, %cr2
  564. ret
  565. END_FUNCTION(ArSetFaultingAddress)
  566. //
  567. // ULONG
  568. // ArGetCurrentPageDirectory (
  569. // VOID
  570. // )
  571. //
  572. /*++
  573. Routine Description:
  574. This routine returns the active page directory.
  575. Arguments:
  576. None.
  577. Return Value:
  578. Returns the page directory currently in use by the system.
  579. --*/
  580. FUNCTION(ArGetCurrentPageDirectory)
  581. movl %cr3, %eax # Return CR3.
  582. ret #
  583. END_FUNCTION(ArGetCurrentPageDirectory)
  584. //
  585. // VOID
  586. // ArSetCurrentPageDirectory (
  587. // ULONG Value
  588. // )
  589. //
  590. /*++
  591. Routine Description:
  592. This routine sets the CR3 register.
  593. Arguments:
  594. Value - Supplies the value to set.
  595. Return Value:
  596. None.
  597. --*/
  598. FUNCTION(ArSetCurrentPageDirectory)
  599. movl 4(%esp), %eax
  600. movl %eax, %cr3
  601. ret
  602. END_FUNCTION(ArSetCurrentPageDirectory)
  603. //
  604. // ULONG
  605. // ArGetControlRegister0 (
  606. // VOID
  607. // )
  608. //
  609. /*++
  610. Routine Description:
  611. This routine returns the current value of CR0.
  612. Arguments:
  613. None.
  614. Return Value:
  615. Returns CR0.
  616. --*/
  617. FUNCTION(ArGetControlRegister0)
  618. movl %cr0, %eax
  619. ret
  620. END_FUNCTION(ArGetControlRegister0)
  621. //
  622. // VOID
  623. // ArSetControlRegister0 (
  624. // ULONG Value
  625. // )
  626. //
  627. /*++
  628. Routine Description:
  629. This routine sets the CR0 register.
  630. Arguments:
  631. Value - Supplies the value to set.
  632. Return Value:
  633. None.
  634. --*/
  635. FUNCTION(ArSetControlRegister0)
  636. movl 4(%esp), %eax
  637. movl %eax, %cr0
  638. ret
  639. END_FUNCTION(ArSetControlRegister0)
  640. //
  641. // ULONG
  642. // ArGetControlRegister4 (
  643. // VOID
  644. // )
  645. //
  646. /*++
  647. Routine Description:
  648. This routine returns the current value of CR4.
  649. Arguments:
  650. None.
  651. Return Value:
  652. Returns CR4.
  653. --*/
  654. FUNCTION(ArGetControlRegister4)
  655. movl %cr4, %eax
  656. ret
  657. END_FUNCTION(ArGetControlRegister4)
  658. //
  659. // VOID
  660. // ArSetControlRegister4 (
  661. // ULONG Value
  662. // )
  663. //
  664. /*++
  665. Routine Description:
  666. This routine sets the CR4 register.
  667. Arguments:
  668. Value - Supplies the value to set.
  669. Return Value:
  670. None.
  671. --*/
  672. FUNCTION(ArSetControlRegister4)
  673. movl 4(%esp), %eax
  674. movl %eax, %cr4
  675. ret
  676. END_FUNCTION(ArSetControlRegister4)
  677. //
  678. // ULONG
  679. // ArGetDebugRegister0 (
  680. // VOID
  681. // )
  682. //
  683. /*++
  684. Routine Description:
  685. This routine returns the current value of DR0.
  686. Arguments:
  687. None.
  688. Return Value:
  689. Returns DR0.
  690. --*/
  691. FUNCTION(ArGetDebugRegister0)
  692. movl %dr0, %eax
  693. ret
  694. END_FUNCTION(ArGetDebugRegister0)
  695. //
  696. // VOID
  697. // ArSetDebugRegister0 (
  698. // ULONG Value
  699. // )
  700. //
  701. /*++
  702. Routine Description:
  703. This routine sets the DR0 register.
  704. Arguments:
  705. Value - Supplies the value to set.
  706. Return Value:
  707. None.
  708. --*/
  709. FUNCTION(ArSetDebugRegister0)
  710. movl 4(%esp), %eax
  711. movl %eax, %dr0
  712. ret
  713. END_FUNCTION(ArSetDebugRegister0)
  714. //
  715. // ULONG
  716. // ArGetDebugRegister1 (
  717. // VOID
  718. // )
  719. //
  720. /*++
  721. Routine Description:
  722. This routine returns the current value of DR1.
  723. Arguments:
  724. None.
  725. Return Value:
  726. Returns DR1.
  727. --*/
  728. FUNCTION(ArGetDebugRegister1)
  729. movl %dr1, %eax
  730. ret
  731. END_FUNCTION(ArGetDebugRegister1)
  732. //
  733. // VOID
  734. // ArSetDebugRegister1 (
  735. // ULONG Value
  736. // )
  737. //
  738. /*++
  739. Routine Description:
  740. This routine sets the DR1 register.
  741. Arguments:
  742. Value - Supplies the value to set.
  743. Return Value:
  744. None.
  745. --*/
  746. FUNCTION(ArSetDebugRegister1)
  747. movl 4(%esp), %eax
  748. movl %eax, %dr1
  749. ret
  750. END_FUNCTION(ArSetDebugRegister1)
  751. //
  752. // ULONG
  753. // ArGetDebugRegister2 (
  754. // VOID
  755. // )
  756. //
  757. /*++
  758. Routine Description:
  759. This routine returns the current value of DR2.
  760. Arguments:
  761. None.
  762. Return Value:
  763. Returns DR2.
  764. --*/
  765. FUNCTION(ArGetDebugRegister2)
  766. movl %dr2, %eax
  767. ret
  768. END_FUNCTION(ArGetDebugRegister2)
  769. //
  770. // VOID
  771. // ArSetDebugRegister2 (
  772. // ULONG Value
  773. // )
  774. //
  775. /*++
  776. Routine Description:
  777. This routine sets the DR2 register.
  778. Arguments:
  779. Value - Supplies the value to set.
  780. Return Value:
  781. None.
  782. --*/
  783. FUNCTION(ArSetDebugRegister2)
  784. movl 4(%esp), %eax
  785. movl %eax, %dr2
  786. ret
  787. END_FUNCTION(ArSetDebugRegister2)
  788. //
  789. // ULONG
  790. // ArGetDebugRegister3 (
  791. // VOID
  792. // )
  793. //
  794. /*++
  795. Routine Description:
  796. This routine returns the current value of DR3.
  797. Arguments:
  798. None.
  799. Return Value:
  800. Returns DR3.
  801. --*/
  802. FUNCTION(ArGetDebugRegister3)
  803. movl %dr3, %eax
  804. ret
  805. END_FUNCTION(ArGetDebugRegister3)
  806. //
  807. // VOID
  808. // ArSetDebugRegister3 (
  809. // ULONG Value
  810. // )
  811. //
  812. /*++
  813. Routine Description:
  814. This routine sets the DR3 register.
  815. Arguments:
  816. Value - Supplies the value to set.
  817. Return Value:
  818. None.
  819. --*/
  820. FUNCTION(ArSetDebugRegister3)
  821. movl 4(%esp), %eax
  822. movl %eax, %dr3
  823. ret
  824. END_FUNCTION(ArSetDebugRegister3)
  825. //
  826. // ULONG
  827. // ArGetDebugRegister6 (
  828. // VOID
  829. // )
  830. //
  831. /*++
  832. Routine Description:
  833. This routine returns the current value of DR6.
  834. Arguments:
  835. None.
  836. Return Value:
  837. Returns DR6.
  838. --*/
  839. FUNCTION(ArGetDebugRegister6)
  840. movl %dr6, %eax
  841. ret
  842. END_FUNCTION(ArGetDebugRegister6)
  843. //
  844. // VOID
  845. // ArSetDebugRegister6 (
  846. // ULONG Value
  847. // )
  848. //
  849. /*++
  850. Routine Description:
  851. This routine sets the DR6 register.
  852. Arguments:
  853. Value - Supplies the value to set.
  854. Return Value:
  855. None.
  856. --*/
  857. FUNCTION(ArSetDebugRegister6)
  858. movl 4(%esp), %eax
  859. movl %eax, %dr6
  860. ret
  861. END_FUNCTION(ArSetDebugRegister6)
  862. //
  863. // ULONG
  864. // ArGetDebugRegister7 (
  865. // VOID
  866. // )
  867. //
  868. /*++
  869. Routine Description:
  870. This routine returns the current value of DR7.
  871. Arguments:
  872. None.
  873. Return Value:
  874. Returns DR7.
  875. --*/
  876. FUNCTION(ArGetDebugRegister7)
  877. movl %dr7, %eax
  878. ret
  879. END_FUNCTION(ArGetDebugRegister7)
  880. //
  881. // VOID
  882. // ArSetDebugRegister7 (
  883. // ULONG Value
  884. // )
  885. //
  886. /*++
  887. Routine Description:
  888. This routine sets the DR7 register.
  889. Arguments:
  890. Value - Supplies the value to set.
  891. Return Value:
  892. None.
  893. --*/
  894. FUNCTION(ArSetDebugRegister7)
  895. movl 4(%esp), %eax
  896. movl %eax, %dr7
  897. ret
  898. END_FUNCTION(ArSetDebugRegister7)
  899. //
  900. // --------------------------------------------------------- Internal Functions
  901. //
  902. //
  903. // VOID
  904. // EfipRestoreTrapFrame (
  905. // TRAP_FRAME TrapFrame
  906. // )
  907. //
  908. /*++
  909. Routine Description:
  910. This routine restores information contained in a trap frame to the
  911. processor and prepares the machine for an iret back to the code that
  912. generated this trap frame. It's not really a function because it assumes
  913. a specific stack layout and modifies data that technically belongs to the
  914. caller. It should only be called immediately before returning from an
  915. exception or interrupt.
  916. Arguments:
  917. TrapFrame - Supplies the trap frame to restore. It is assumed that the
  918. IOPL and VM fields of the Eflags register have remained unchanged from
  919. when the exception was generated.
  920. Return Value:
  921. Upon return, the trap frame will have been popped off the stack, and the
  922. machine will be in the same state as right after the exception happened.
  923. --*/
  924. FUNCTION(EfipRestoreTrapFrame)
  925. //
  926. // Restore the common data segment registers. Hold off on DS, as this routine
  927. // will make a couple more DS: accesses. Save it in ESI.
  928. //
  929. movl TRAP_DS+4(%esp), %esi # Save DS into ESI for now.
  930. movl TRAP_ES+4(%esp), %eax # Restore ES.
  931. movw %ax, %es #
  932. movl TRAP_FS+4(%esp), %eax # Restore FS.
  933. movw %ax, %fs #
  934. movl TRAP_GS+4(%esp), %eax # Restore GS.
  935. movw %ax, %gs #
  936. RestoreTrapFrameToKernelMode:
  937. //
  938. // The exception came from kernel mode, so restore the stack segment register.
  939. //
  940. movl TRAP_SS+4(%esp), %eax # Restore SS. If this doesn't allow access
  941. movw %ax, %ss # to the current stack, this will be bad.
  942. //
  943. // Build the iret return on the value The parameters going on the new stack are
  944. // Ebx, Return Address, Error Code, Eip, CS, and Eflags.
  945. //
  946. // Note that if the stack pointer doesn't change, the Ebx and Return address
  947. // values destroy data that was on the stack there (immediately after the
  948. // Eflags, CS, Eip). This happens to be the last two values in the trap frame
  949. // structure. Luckily those members are Esp and Eflags, which are restored
  950. // immediately before their values are destroyed.
  951. //
  952. movl TRAP_ESP+4(%esp), %ebx # Get the kernel Esp.
  953. RestoreTrapFrameGeneralRegisters:
  954. subl $24, %ebx # Make room for the new parameters.
  955. movl TRAP_EIP+4(%esp), %ecx # Restore Eip.
  956. movl %ecx, 12(%ebx) #
  957. movl TRAP_CS+4(%esp), %ecx # Restore CS.
  958. movl %ecx, 16(%ebx) #
  959. movl TRAP_EFLAGS+4(%esp), %ecx # Restore Eflags.
  960. movl %ecx, 20(%ebx) #
  961. movl TRAP_EBX+4(%esp), %ecx # Save Ebx.
  962. movl %ecx, (%ebx) #
  963. movl (%esp), %ecx # Save this function's return address.
  964. movl %ecx, 4(%ebx) #
  965. //
  966. // Now that all DS: accesses are finished, restore DS.
  967. //
  968. movw %si, %ds
  969. //
  970. // Restore the general registers.
  971. //
  972. movl TRAP_EAX+4(%esp), %eax #
  973. movl TRAP_ECX+4(%esp), %ecx #
  974. movl TRAP_EDX+4(%esp), %edx #
  975. movl TRAP_ESI+4(%esp), %esi #
  976. movl TRAP_EDI+4(%esp), %edi #
  977. movl TRAP_EBP+4(%esp), %ebp #
  978. //
  979. // Transition to the new kernel mode stack pointer, pop Ebx, and return.
  980. //
  981. movl %ebx, %esp # Move stacks!
  982. popl %ebx # Restore Ebx.
  983. ret
  984. END_FUNCTION(EfipRestoreTrapFrame)
  985. //
  986. // TRAP_FRAME
  987. // EfipGenerateTrapFrame (
  988. // ULONG ReturnEip,
  989. // ULONG ReturnCs,
  990. // ULONG ReturnEflags,
  991. // ...
  992. // )
  993. //
  994. /*++
  995. Routine Description:
  996. This routine generates a trap frame based on the data pushed onto the
  997. stack by the processor after an exception. It is not really a function
  998. in that it assumes a certain stack layout and will modify data that
  999. belongs to the caller. This function should only be called immediately
  1000. after an interrupt/exception.
  1001. Arguments:
  1002. ReturnEip - Supplies the instruction that generated the exception.
  1003. ReturnCs - Supplies the code selector of the code that generated the
  1004. exception.
  1005. ReturnEflags - Supplies the flags of the code that generated the
  1006. exception.
  1007. Return Value:
  1008. Upon return, a TRAP_FRAME will be on the top of the stack.
  1009. --*/
  1010. FUNCTION(EfipGenerateTrapFrame)
  1011. //
  1012. // Allocate room on the stack for the trap frame plus the return address,
  1013. // minus the original return address.
  1014. //
  1015. subl $TRAP_FRAME_SIZE, %esp #
  1016. pushl %eax # Save eax for a moment while the return
  1017. movl TRAP_FRAME_SIZE+4(%esp), %eax # address is moved.
  1018. movl %eax, 4(%esp) #
  1019. popl %eax # Restore eax
  1020. movl %eax, TRAP_EAX+4(%esp) # Save the general registers.
  1021. movl %ebx, TRAP_EBX+4(%esp) #
  1022. movl %ecx, TRAP_ECX+4(%esp) #
  1023. movl %edx, TRAP_EDX+4(%esp) #
  1024. movl %esi, TRAP_ESI+4(%esp) #
  1025. movl %edi, TRAP_EDI+4(%esp) #
  1026. movl %ebp, TRAP_EBP+4(%esp) #
  1027. movl TRAP_RET_ERRORCODE+4(%esp), %eax # Save the error code.
  1028. movl %eax, TRAP_ERRORCODE+4(%esp) #
  1029. movl TRAP_RET_EIP+4(%esp), %eax # Save the return address.
  1030. movl %eax, TRAP_EIP+4(%esp) #
  1031. movl TRAP_RET_CS+4(%esp), %eax # Save the return CS.
  1032. movl %eax, TRAP_CS+4(%esp) #
  1033. movl TRAP_RET_EFLAGS+4(%esp), %eax # Save eflags.
  1034. movl %eax, TRAP_EFLAGS+4(%esp)
  1035. //
  1036. // The exception came from ring 0, so the only things pushed on the stack
  1037. // by the processor are Eip, CS, and Eflags. The data segments also don't need
  1038. // to be saved. Get the data segments from their current values. Since there
  1039. // was no stack change, the Esp is simply this current one except all the
  1040. // stuff pushed by the exception, plus the error code.
  1041. //
  1042. movl %esp, %eax # Save Esp.
  1043. addl $TRAP_FRAME_SIZE+20, %eax # Remove exception stack items.
  1044. movl %eax, TRAP_ESP+4(%esp) #
  1045. xorl %eax, %eax # Zero out eax.
  1046. movw %ds, %ax # Save DS.
  1047. movl %eax, TRAP_DS+4(%esp) #
  1048. movw %es, %ax # Save ES.
  1049. movl %eax, TRAP_ES+4(%esp) #
  1050. movw %fs, %ax # Save FS.
  1051. movl %eax, TRAP_FS+4(%esp) #
  1052. movw %gs, %ax # Save GS.
  1053. movl %eax, TRAP_GS+4(%esp) #
  1054. movw %ss, %ax # Save SS.
  1055. movl %eax, TRAP_SS+4(%esp) #
  1056. GenerateTrapFrameEnd:
  1057. LoadBootDataSegments # Load valid data segments.
  1058. ret #
  1059. END_FUNCTION(EfipGenerateTrapFrame)